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>
diff --git a/src/ast/variable.cc b/src/ast/variable.cc
index 6ac6976..e053ffd 100644
--- a/src/ast/variable.cc
+++ b/src/ast/variable.cc
@@ -71,6 +71,15 @@
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_) {
diff --git a/src/ast/variable.h b/src/ast/variable.h
index 134b013..88257b2 100644
--- a/src/ast/variable.h
+++ b/src/ast/variable.h
@@ -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 @@
/// @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;
diff --git a/src/ast/variable_test.cc b/src/ast/variable_test.cc
index e6475c1..7f19618 100644
--- a/src/ast/variable_test.cc
+++ b/src/ast/variable_test.cc
@@ -123,6 +123,10 @@
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) {
diff --git a/src/inspector/entry_point.h b/src/inspector/entry_point.h
index 13e0234..028f6d8 100644
--- a/src/inspector/entry_point.h
+++ b/src/inspector/entry_point.h
@@ -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 @@
/// 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() {
diff --git a/src/inspector/inspector.cc b/src/inspector/inspector.cc
index eca911d..f23e954 100644
--- a/src/inspector/inspector.cc
+++ b/src/inspector/inspector.cc
@@ -64,10 +64,20 @@
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));
diff --git a/src/inspector/inspector_test.cc b/src/inspector/inspector_test.cc
index 0dd9ee0..6f6f76c 100644
--- a/src/inspector/inspector_test.cc
+++ b/src/inspector/inspector_test.cc
@@ -109,12 +109,19 @@
/// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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