Add location data to input/output variable reflection

Adds this data to the Inspector API, as well as needed internal
utility methods.
Updates and expands tests to cover changes.

BUG=tint:452

Change-Id: I598f8149cb6abd13abf606416ae61e615b99e1e1
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/38200
Auto-Submit: Ryan Harrison <rharrison@chromium.org>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: Ryan Harrison <rharrison@chromium.org>
This commit is contained in:
Ryan Harrison 2021-01-20 18:58:17 +00:00 committed by Commit Bot service account
parent ed14524b1e
commit afb8cfb254
6 changed files with 135 additions and 38 deletions

View File

@ -71,6 +71,15 @@ bool Variable::HasConstantIdDecoration() const {
return false;
}
LocationDecoration* Variable::GetLocationDecoration() const {
for (auto* deco : decorations_) {
if (deco->Is<LocationDecoration>()) {
return deco->As<LocationDecoration>();
}
}
return nullptr;
}
uint32_t Variable::constant_id() const {
assert(HasConstantIdDecoration());
for (auto* deco : decorations_) {

View File

@ -30,6 +30,8 @@
namespace tint {
namespace ast {
class LocationDecoration;
/// A Variable statement.
///
/// An instance of this class represents one of three constructs in WGSL: "var"
@ -129,6 +131,9 @@ class Variable : public Castable<Variable, Node> {
/// @returns true if the decorations include a ConstantIdDecoration
bool HasConstantIdDecoration() const;
/// @returns pointer to LocationDecoration in decorations, otherwise NULL.
LocationDecoration* GetLocationDecoration() const;
/// @returns the constant_id value for the variable. Assumes that
/// HasConstantIdDecoration() has been called first.
uint32_t constant_id() const;

View File

@ -123,6 +123,10 @@ TEST_F(VariableTest, WithDecorations) {
EXPECT_TRUE(var->HasLocationDecoration());
EXPECT_TRUE(var->HasBuiltinDecoration());
EXPECT_TRUE(var->HasConstantIdDecoration());
auto* location = var->GetLocationDecoration();
ASSERT_NE(nullptr, location);
EXPECT_EQ(1u, location->value());
}
TEST_F(VariableTest, ConstantId) {

View File

@ -24,7 +24,18 @@
namespace tint {
namespace inspector {
/// Container of reflection data for an entry point in the shader.
/// Reflection data about an entry point input or output.
typedef struct {
/// Name of the variable in the shader.
std::string name;
/// Is Location Decoration present
bool has_location_decoration;
/// Value of Location Decoration, only valid if |has_location_decoration| is
/// true.
uint32_t location_decoration;
} StageVariable;
/// Reflection data for an entry point in the shader.
typedef struct EntryPoint {
/// Constructors
EntryPoint();
@ -47,9 +58,9 @@ typedef struct EntryPoint {
/// The workgroup z size
uint32_t workgroup_size_z;
/// List of the input variable accessed via this entry point.
std::vector<std::string> input_variables;
std::vector<StageVariable> input_variables;
/// List of the output variable accessed via this entry point.
std::vector<std::string> output_variables;
std::vector<StageVariable> output_variables;
/// @returns the size of the workgroup in {x,y,z} format
std::tuple<uint32_t, uint32_t, uint32_t> workgroup_size() {

View File

@ -64,10 +64,20 @@ std::vector<EntryPoint> Inspector::GetEntryPoints() {
for (auto* var : func->referenced_module_variables()) {
auto name = module_.SymbolToName(var->symbol());
if (var->storage_class() == ast::StorageClass::kInput) {
entry_point.input_variables.push_back(name);
StageVariable stage_variable;
stage_variable.name = name;
auto* location_decoration = var->GetLocationDecoration();
if (location_decoration) {
stage_variable.has_location_decoration = true;
stage_variable.location_decoration = location_decoration->value();
} else {
entry_point.output_variables.push_back(name);
stage_variable.has_location_decoration = false;
}
if (var->storage_class() == ast::StorageClass::kInput) {
entry_point.input_variables.push_back(stage_variable);
} else if (var->storage_class() == ast::StorageClass::kOutput) {
entry_point.output_variables.push_back(stage_variable);
}
}
result.push_back(std::move(entry_point));

View File

@ -109,12 +109,19 @@ class InspectorHelper : public ast::BuilderWithModule {
/// global variables
void AddInOutVariables(
std::vector<std::tuple<std::string, std::string>> inout_vars) {
uint32_t location = 0;
for (auto inout : inout_vars) {
std::string in, out;
std::tie(in, out) = inout;
mod->AddGlobalVariable(Var(in, ast::StorageClass::kInput, ty.u32));
mod->AddGlobalVariable(Var(out, ast::StorageClass::kOutput, ty.u32));
mod->AddGlobalVariable(
Var(in, ast::StorageClass::kInput, ty.u32, nullptr,
ast::VariableDecorationList{
create<ast::LocationDecoration>(location++)}));
mod->AddGlobalVariable(
Var(out, ast::StorageClass::kOutput, ty.u32, nullptr,
ast::VariableDecorationList{
create<ast::LocationDecoration>(location++)}));
}
}
@ -214,13 +221,13 @@ class InspectorHelper : public ast::BuilderWithModule {
return create<ast::FloatLiteral>(type, *val);
}
/// @param vec Vector of strings to be searched
/// @param str String to be searching for
/// @returns true if str is in vec, otherwise false
bool ContainsString(const std::vector<std::string>& vec,
const std::string& str) {
/// @param vec Vector of StageVariable to be searched
/// @param name Name to be searching for
/// @returns true if name is in vec, otherwise false
bool ContainsName(const std::vector<StageVariable>& vec,
const std::string& name) {
for (auto& s : vec) {
if (s == str) {
if (s.name == name) {
return true;
}
}
@ -865,9 +872,13 @@ TEST_F(InspectorGetEntryPointTest, EntryPointInOutVariables) {
ASSERT_EQ(1u, result.size());
ASSERT_EQ(1u, result[0].input_variables.size());
EXPECT_EQ("in_var", result[0].input_variables[0]);
EXPECT_EQ("in_var", result[0].input_variables[0].name);
EXPECT_TRUE(result[0].input_variables[0].has_location_decoration);
EXPECT_EQ(0u, result[0].input_variables[0].location_decoration);
ASSERT_EQ(1u, result[0].output_variables.size());
EXPECT_EQ("out_var", result[0].output_variables[0]);
EXPECT_EQ("out_var", result[0].output_variables[0].name);
EXPECT_TRUE(result[0].output_variables[0].has_location_decoration);
EXPECT_EQ(1u, result[0].output_variables[0].location_decoration);
}
TEST_F(InspectorGetEntryPointTest, FunctionInOutVariables) {
@ -892,9 +903,13 @@ TEST_F(InspectorGetEntryPointTest, FunctionInOutVariables) {
ASSERT_EQ(1u, result.size());
ASSERT_EQ(1u, result[0].input_variables.size());
EXPECT_EQ("in_var", result[0].input_variables[0]);
EXPECT_EQ("in_var", result[0].input_variables[0].name);
EXPECT_TRUE(result[0].input_variables[0].has_location_decoration);
EXPECT_EQ(0u, result[0].input_variables[0].location_decoration);
ASSERT_EQ(1u, result[0].output_variables.size());
EXPECT_EQ("out_var", result[0].output_variables[0]);
EXPECT_EQ("out_var", result[0].output_variables[0].name);
EXPECT_TRUE(result[0].output_variables[0].has_location_decoration);
EXPECT_EQ(1u, result[0].output_variables[0].location_decoration);
}
TEST_F(InspectorGetEntryPointTest, RepeatedInOutVariables) {
@ -919,9 +934,13 @@ TEST_F(InspectorGetEntryPointTest, RepeatedInOutVariables) {
ASSERT_EQ(1u, result.size());
ASSERT_EQ(1u, result[0].input_variables.size());
EXPECT_EQ("in_var", result[0].input_variables[0]);
EXPECT_EQ("in_var", result[0].input_variables[0].name);
EXPECT_TRUE(result[0].input_variables[0].has_location_decoration);
EXPECT_EQ(0u, result[0].input_variables[0].location_decoration);
ASSERT_EQ(1u, result[0].output_variables.size());
EXPECT_EQ("out_var", result[0].output_variables[0]);
EXPECT_EQ("out_var", result[0].output_variables[0].name);
EXPECT_TRUE(result[0].output_variables[0].has_location_decoration);
EXPECT_EQ(1u, result[0].output_variables[0].location_decoration);
}
TEST_F(InspectorGetEntryPointTest, EntryPointMultipleInOutVariables) {
@ -942,11 +961,19 @@ TEST_F(InspectorGetEntryPointTest, EntryPointMultipleInOutVariables) {
ASSERT_EQ(1u, result.size());
ASSERT_EQ(2u, result[0].input_variables.size());
EXPECT_TRUE(ContainsString(result[0].input_variables, "in_var"));
EXPECT_TRUE(ContainsString(result[0].input_variables, "in2_var"));
EXPECT_TRUE(ContainsName(result[0].input_variables, "in_var"));
EXPECT_TRUE(ContainsName(result[0].input_variables, "in2_var"));
EXPECT_TRUE(result[0].input_variables[0].has_location_decoration);
EXPECT_EQ(0u, result[0].input_variables[0].location_decoration);
EXPECT_TRUE(result[0].input_variables[1].has_location_decoration);
EXPECT_EQ(2u, result[0].input_variables[1].location_decoration);
ASSERT_EQ(2u, result[0].output_variables.size());
EXPECT_TRUE(ContainsString(result[0].output_variables, "out_var"));
EXPECT_TRUE(ContainsString(result[0].output_variables, "out2_var"));
EXPECT_TRUE(ContainsName(result[0].output_variables, "out_var"));
EXPECT_TRUE(ContainsName(result[0].output_variables, "out2_var"));
EXPECT_TRUE(result[0].output_variables[0].has_location_decoration);
EXPECT_EQ(1u, result[0].output_variables[0].location_decoration);
EXPECT_TRUE(result[0].output_variables[1].has_location_decoration);
EXPECT_EQ(3u, result[0].output_variables[1].location_decoration);
}
TEST_F(InspectorGetEntryPointTest, FunctionMultipleInOutVariables) {
@ -971,11 +998,20 @@ TEST_F(InspectorGetEntryPointTest, FunctionMultipleInOutVariables) {
ASSERT_EQ(1u, result.size());
ASSERT_EQ(2u, result[0].input_variables.size());
EXPECT_TRUE(ContainsString(result[0].input_variables, "in_var"));
EXPECT_TRUE(ContainsString(result[0].input_variables, "in2_var"));
EXPECT_TRUE(ContainsName(result[0].input_variables, "in_var"));
EXPECT_TRUE(ContainsName(result[0].input_variables, "in2_var"));
EXPECT_TRUE(result[0].input_variables[0].has_location_decoration);
EXPECT_EQ(0u, result[0].input_variables[0].location_decoration);
EXPECT_TRUE(result[0].input_variables[1].has_location_decoration);
EXPECT_EQ(2u, result[0].input_variables[1].location_decoration);
ASSERT_EQ(2u, result[0].output_variables.size());
EXPECT_TRUE(ContainsString(result[0].output_variables, "out_var"));
EXPECT_TRUE(ContainsString(result[0].output_variables, "out2_var"));
ASSERT_EQ(2u, result[0].output_variables.size());
EXPECT_TRUE(ContainsName(result[0].output_variables, "out_var"));
EXPECT_TRUE(ContainsName(result[0].output_variables, "out2_var"));
EXPECT_TRUE(result[0].output_variables[0].has_location_decoration);
EXPECT_EQ(1u, result[0].output_variables[0].location_decoration);
EXPECT_TRUE(result[0].output_variables[1].has_location_decoration);
EXPECT_EQ(3u, result[0].output_variables[1].location_decoration);
}
TEST_F(InspectorGetEntryPointTest, MultipleEntryPointsInOutVariables) {
@ -1007,16 +1043,24 @@ TEST_F(InspectorGetEntryPointTest, MultipleEntryPointsInOutVariables) {
ASSERT_EQ("foo", result[0].name);
ASSERT_EQ("foo", result[0].remapped_name);
ASSERT_EQ(1u, result[0].input_variables.size());
EXPECT_EQ("in_var", result[0].input_variables[0]);
EXPECT_EQ("in_var", result[0].input_variables[0].name);
EXPECT_TRUE(result[0].input_variables[0].has_location_decoration);
EXPECT_EQ(0u, result[0].input_variables[0].location_decoration);
ASSERT_EQ(1u, result[0].output_variables.size());
EXPECT_EQ("out2_var", result[0].output_variables[0]);
EXPECT_EQ("out2_var", result[0].output_variables[0].name);
EXPECT_TRUE(result[0].output_variables[0].has_location_decoration);
EXPECT_EQ(3u, result[0].output_variables[0].location_decoration);
ASSERT_EQ("bar", result[1].name);
ASSERT_EQ("bar", result[1].remapped_name);
ASSERT_EQ(1u, result[1].input_variables.size());
EXPECT_EQ("in2_var", result[1].input_variables[0]);
EXPECT_EQ("in2_var", result[1].input_variables[0].name);
EXPECT_TRUE(result[1].input_variables[0].has_location_decoration);
EXPECT_EQ(2u, result[1].input_variables[0].location_decoration);
ASSERT_EQ(1u, result[1].output_variables.size());
EXPECT_EQ("out_var", result[1].output_variables[0]);
EXPECT_EQ("out_var", result[1].output_variables[0].name);
EXPECT_TRUE(result[1].output_variables[0].has_location_decoration);
EXPECT_EQ(1u, result[1].output_variables[0].location_decoration);
}
TEST_F(InspectorGetEntryPointTest, MultipleEntryPointsSharedInOutVariables) {
@ -1052,18 +1096,32 @@ TEST_F(InspectorGetEntryPointTest, MultipleEntryPointsSharedInOutVariables) {
ASSERT_EQ("foo", result[0].name);
ASSERT_EQ("foo", result[0].remapped_name);
EXPECT_EQ(2u, result[0].input_variables.size());
EXPECT_TRUE(ContainsString(result[0].input_variables, "in_var"));
EXPECT_TRUE(ContainsString(result[0].input_variables, "in2_var"));
EXPECT_TRUE(ContainsName(result[0].input_variables, "in_var"));
EXPECT_TRUE(ContainsName(result[0].input_variables, "in2_var"));
EXPECT_TRUE(result[0].input_variables[0].has_location_decoration);
EXPECT_EQ(0u, result[0].input_variables[0].location_decoration);
EXPECT_TRUE(result[0].input_variables[1].has_location_decoration);
EXPECT_EQ(2u, result[0].input_variables[1].location_decoration);
EXPECT_EQ(2u, result[0].output_variables.size());
EXPECT_TRUE(ContainsString(result[0].output_variables, "out_var"));
EXPECT_TRUE(ContainsString(result[0].output_variables, "out2_var"));
EXPECT_TRUE(ContainsName(result[0].output_variables, "out_var"));
EXPECT_TRUE(ContainsName(result[0].output_variables, "out2_var"));
EXPECT_TRUE(result[0].output_variables[0].has_location_decoration);
EXPECT_EQ(1u, result[0].output_variables[0].location_decoration);
EXPECT_TRUE(result[0].output_variables[0].has_location_decoration);
EXPECT_EQ(3u, result[0].output_variables[1].location_decoration);
ASSERT_EQ("bar", result[1].name);
ASSERT_EQ("bar", result[1].remapped_name);
EXPECT_EQ(1u, result[1].input_variables.size());
EXPECT_EQ("in2_var", result[1].input_variables[0]);
EXPECT_EQ("in2_var", result[1].input_variables[0].name);
EXPECT_TRUE(result[1].input_variables[0].has_location_decoration);
EXPECT_EQ(2u, result[1].input_variables[0].location_decoration);
EXPECT_EQ(1u, result[1].output_variables.size());
EXPECT_EQ("out2_var", result[1].output_variables[0]);
EXPECT_EQ("out2_var", result[1].output_variables[0].name);
EXPECT_TRUE(result[1].output_variables[0].has_location_decoration);
EXPECT_EQ(3u, result[1].output_variables[0].location_decoration);
}
// TODO(rharrison): Reenable once GetRemappedNameForEntryPoint isn't a pass