writer: Use semantic info for constant IDs
This enables the backends to emit overridable constants that had no ID
specified in the attribute.
Bug: tint:755
Change-Id: I86587205e065715257f546b546e792a5262562e8
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/50842
Commit-Queue: James Price <jrprice@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
index c7a3f26..d76f4f1 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -2689,8 +2689,8 @@
auto* sem = builder_.Sem().Get(var);
auto* type = sem->Type();
- if (ast::HasDecoration<ast::OverrideDecoration>(var->decorations())) {
- auto const_id = var->constant_id();
+ if (sem->IsPipelineConstant()) {
+ auto const_id = sem->ConstantId();
out << "#ifndef WGSL_SPEC_CONSTANT_" << const_id << std::endl;
diff --git a/src/writer/hlsl/generator_impl_module_constant_test.cc b/src/writer/hlsl/generator_impl_module_constant_test.cc
index 6680341..6e82c94 100644
--- a/src/writer/hlsl/generator_impl_module_constant_test.cc
+++ b/src/writer/hlsl/generator_impl_module_constant_test.cc
@@ -33,11 +33,10 @@
}
TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant) {
- auto* var = Const("pos", ty.f32(), Expr(3.0f),
- ast::DecorationList{
- create<ast::OverrideDecoration>(23),
- });
- WrapInFunction(Decl(var));
+ auto* var = GlobalConst("pos", ty.f32(), Expr(3.0f),
+ ast::DecorationList{
+ create<ast::OverrideDecoration>(23),
+ });
GeneratorImpl& gen = Build();
@@ -67,6 +66,33 @@
)");
}
+TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant_NoId) {
+ auto* a = GlobalConst("a", ty.f32(), Expr(3.0f),
+ ast::DecorationList{
+ create<ast::OverrideDecoration>(0),
+ });
+ auto* b = GlobalConst("b", ty.f32(), Expr(2.0f),
+ ast::DecorationList{
+ create<ast::OverrideDecoration>(),
+ });
+
+ GeneratorImpl& gen = Build();
+
+ ASSERT_TRUE(gen.EmitProgramConstVariable(out, a)) << gen.error();
+ ASSERT_TRUE(gen.EmitProgramConstVariable(out, b)) << gen.error();
+ EXPECT_EQ(result(), R"(#ifndef WGSL_SPEC_CONSTANT_0
+#define WGSL_SPEC_CONSTANT_0 3.0f
+#endif
+static const float a = WGSL_SPEC_CONSTANT_0;
+#undef WGSL_SPEC_CONSTANT_0
+#ifndef WGSL_SPEC_CONSTANT_1
+#define WGSL_SPEC_CONSTANT_1 2.0f
+#endif
+static const float b = WGSL_SPEC_CONSTANT_1;
+#undef WGSL_SPEC_CONSTANT_1
+)");
+}
+
} // namespace
} // namespace hlsl
} // namespace writer
diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc
index afb3c5d..0996127 100644
--- a/src/writer/msl/generator_impl.cc
+++ b/src/writer/msl/generator_impl.cc
@@ -2257,8 +2257,9 @@
out_ << " " << program_->Symbols().NameFor(var->symbol());
}
- if (ast::HasDecoration<ast::OverrideDecoration>(var->decorations())) {
- out_ << " [[function_constant(" << var->constant_id() << ")]]";
+ auto* sem_var = program_->Sem().Get(var);
+ if (sem_var->IsPipelineConstant()) {
+ out_ << " [[function_constant(" << sem_var->ConstantId() << ")]]";
} else if (var->constructor() != nullptr) {
out_ << " = ";
if (!EmitExpression(var->constructor())) {
diff --git a/src/writer/msl/generator_impl_module_constant_test.cc b/src/writer/msl/generator_impl_module_constant_test.cc
index a939ee2..ec70cf5 100644
--- a/src/writer/msl/generator_impl_module_constant_test.cc
+++ b/src/writer/msl/generator_impl_module_constant_test.cc
@@ -23,8 +23,8 @@
using MslGeneratorImplTest = TestHelper;
TEST_F(MslGeneratorImplTest, Emit_ModuleConstant) {
- auto* var = Const("pos", ty.array<f32, 3>(), array<f32, 3>(1.f, 2.f, 3.f));
- WrapInFunction(Decl(var));
+ auto* var =
+ GlobalConst("pos", ty.array<f32, 3>(), array<f32, 3>(1.f, 2.f, 3.f));
GeneratorImpl& gen = Build();
@@ -33,11 +33,10 @@
}
TEST_F(MslGeneratorImplTest, Emit_SpecConstant) {
- auto* var = Const("pos", ty.f32(), Expr(3.f),
- ast::DecorationList{
- create<ast::OverrideDecoration>(23),
- });
- WrapInFunction(Decl(var));
+ auto* var = GlobalConst("pos", ty.f32(), Expr(3.f),
+ ast::DecorationList{
+ create<ast::OverrideDecoration>(23),
+ });
GeneratorImpl& gen = Build();
@@ -45,6 +44,25 @@
EXPECT_EQ(gen.result(), "constant float pos [[function_constant(23)]];\n");
}
+TEST_F(MslGeneratorImplTest, Emit_SpecConstant_NoId) {
+ auto* var_a = GlobalConst("a", ty.f32(), nullptr,
+ ast::DecorationList{
+ create<ast::OverrideDecoration>(0),
+ });
+ auto* var_b = GlobalConst("b", ty.f32(), nullptr,
+ ast::DecorationList{
+ create<ast::OverrideDecoration>(),
+ });
+
+ GeneratorImpl& gen = Build();
+
+ ASSERT_TRUE(gen.EmitProgramConstVariable(var_a)) << gen.error();
+ ASSERT_TRUE(gen.EmitProgramConstVariable(var_b)) << gen.error();
+ EXPECT_EQ(gen.result(), R"(constant float a [[function_constant(0)]];
+constant float b [[function_constant(1)]];
+)");
+}
+
} // namespace
} // namespace msl
} // namespace writer
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index 377ed2c..2fd180a 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -1493,9 +1493,10 @@
ast::Literal* lit) {
ScalarConstant constant;
- if (var && ast::HasDecoration<ast::OverrideDecoration>(var->decorations())) {
+ auto* sem_var = builder_.Sem().Get(var);
+ if (sem_var && sem_var->IsPipelineConstant()) {
constant.is_spec_op = true;
- constant.constant_id = var->constant_id();
+ constant.constant_id = sem_var->ConstantId();
}
if (auto* l = lit->As<ast::BoolLiteral>()) {
diff --git a/src/writer/spirv/builder_global_variable_test.cc b/src/writer/spirv/builder_global_variable_test.cc
index 79b8d5c..d3db49f 100644
--- a/src/writer/spirv/builder_global_variable_test.cc
+++ b/src/writer/spirv/builder_global_variable_test.cc
@@ -311,6 +311,32 @@
)");
}
+TEST_F(BuilderTest, GlobalVar_Override_NoId) {
+ auto* var_a = GlobalConst("a", ty.bool_(), Expr(true),
+ ast::DecorationList{
+ create<ast::OverrideDecoration>(0),
+ });
+ auto* var_b = GlobalConst("b", ty.bool_(), Expr(false),
+ ast::DecorationList{
+ create<ast::OverrideDecoration>(),
+ });
+
+ spirv::Builder& b = Build();
+
+ EXPECT_TRUE(b.GenerateGlobalVariable(var_a)) << b.error();
+ EXPECT_TRUE(b.GenerateGlobalVariable(var_b)) << b.error();
+ EXPECT_EQ(DumpInstructions(b.debug()), R"(OpName %2 "a"
+OpName %3 "b"
+)");
+ EXPECT_EQ(DumpInstructions(b.annots()), R"(OpDecorate %2 SpecId 0
+OpDecorate %3 SpecId 1
+)");
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeBool
+%2 = OpSpecConstantTrue %1
+%3 = OpSpecConstantFalse %1
+)");
+}
+
struct BuiltinData {
ast::Builtin builtin;
ast::StorageClass storage;
diff --git a/src/writer/wgsl/generator_impl.cc b/src/writer/wgsl/generator_impl.cc
index a5be99d..7317829 100644
--- a/src/writer/wgsl/generator_impl.cc
+++ b/src/writer/wgsl/generator_impl.cc
@@ -609,7 +609,10 @@
} else if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
out_ << "builtin(" << builtin->value() << ")";
} else if (auto* override_deco = deco->As<ast::OverrideDecoration>()) {
- out_ << "override(" << override_deco->value() << ")";
+ out_ << "override";
+ if (override_deco->HasValue()) {
+ out_ << "(" << override_deco->value() << ")";
+ }
} else if (auto* size = deco->As<ast::StructMemberSizeDecoration>()) {
out_ << "size(" << size->size() << ")";
} else if (auto* align = deco->As<ast::StructMemberAlignDecoration>()) {
diff --git a/src/writer/wgsl/generator_impl_global_decl_test.cc b/src/writer/wgsl/generator_impl_global_decl_test.cc
index 4a91097..e9cceca 100644
--- a/src/writer/wgsl/generator_impl_global_decl_test.cc
+++ b/src/writer/wgsl/generator_impl_global_decl_test.cc
@@ -129,6 +129,21 @@
" [[group(0), binding(0)]] var t : [[access(read)]] texture_1d<f32>;\n");
}
+TEST_F(WgslGeneratorImplTest, Emit_OverridableConstants) {
+ GlobalConst("a", ty.f32(), nullptr, {Override()});
+ GlobalConst("b", ty.f32(), nullptr, {Override(7u)});
+
+ GeneratorImpl& gen = Build();
+
+ gen.increment_indent();
+
+ ASSERT_TRUE(gen.Generate(nullptr)) << gen.error();
+ EXPECT_EQ(gen.result(), R"( [[override]] let a : f32;
+
+ [[override(7)]] let b : f32;
+)");
+}
+
} // namespace
} // namespace wgsl
} // namespace writer