diff --git a/src/ast/variable.cc b/src/ast/variable.cc index 6ac6976a7b..e053ffddae 100644 --- a/src/ast/variable.cc +++ b/src/ast/variable.cc @@ -71,6 +71,15 @@ bool Variable::HasConstantIdDecoration() const { return false; } +LocationDecoration* Variable::GetLocationDecoration() const { + for (auto* deco : decorations_) { + if (deco->Is()) { + return deco->As(); + } + } + 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 134b013ede..88257b23f1 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 @@ class Variable : public Castable { /// @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 e6475c1d06..7f19618664 100644 --- a/src/ast/variable_test.cc +++ b/src/ast/variable_test.cc @@ -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) { diff --git a/src/inspector/entry_point.h b/src/inspector/entry_point.h index 13e023429e..028f6d8992 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 @@ typedef struct EntryPoint { /// The workgroup z size uint32_t workgroup_size_z; /// List of the input variable accessed via this entry point. - std::vector input_variables; + std::vector input_variables; /// List of the output variable accessed via this entry point. - std::vector output_variables; + std::vector output_variables; /// @returns the size of the workgroup in {x,y,z} format std::tuple workgroup_size() { diff --git a/src/inspector/inspector.cc b/src/inspector/inspector.cc index eca911dea5..f23e95420f 100644 --- a/src/inspector/inspector.cc +++ b/src/inspector/inspector.cc @@ -64,10 +64,20 @@ std::vector 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)); diff --git a/src/inspector/inspector_test.cc b/src/inspector/inspector_test.cc index 0dd9ee0179..6f6f76cdbf 100644 --- a/src/inspector/inspector_test.cc +++ b/src/inspector/inspector_test.cc @@ -109,12 +109,19 @@ class InspectorHelper : public ast::BuilderWithModule { /// global variables void AddInOutVariables( std::vector> 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(location++)})); + mod->AddGlobalVariable( + Var(out, ast::StorageClass::kOutput, ty.u32, nullptr, + ast::VariableDecorationList{ + create(location++)})); } } @@ -214,13 +221,13 @@ class InspectorHelper : public ast::BuilderWithModule { return create(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& 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& 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