diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc index c7a3f26763..d76f4f153b 100644 --- a/src/writer/hlsl/generator_impl.cc +++ b/src/writer/hlsl/generator_impl.cc @@ -2689,8 +2689,8 @@ bool GeneratorImpl::EmitProgramConstVariable(std::ostream& out, auto* sem = builder_.Sem().Get(var); auto* type = sem->Type(); - if (ast::HasDecoration(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 66803415db..6e82c94bd9 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_ModuleConstant) { } TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant) { - auto* var = Const("pos", ty.f32(), Expr(3.0f), - ast::DecorationList{ - create(23), - }); - WrapInFunction(Decl(var)); + auto* var = GlobalConst("pos", ty.f32(), Expr(3.0f), + ast::DecorationList{ + create(23), + }); GeneratorImpl& gen = Build(); @@ -67,6 +66,33 @@ static const float pos = WGSL_SPEC_CONSTANT_23; )"); } +TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant_NoId) { + auto* a = GlobalConst("a", ty.f32(), Expr(3.0f), + ast::DecorationList{ + create(0), + }); + auto* b = GlobalConst("b", ty.f32(), Expr(2.0f), + ast::DecorationList{ + create(), + }); + + 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 afb3c5de1e..09961271db 100644 --- a/src/writer/msl/generator_impl.cc +++ b/src/writer/msl/generator_impl.cc @@ -2257,8 +2257,9 @@ bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) { out_ << " " << program_->Symbols().NameFor(var->symbol()); } - if (ast::HasDecoration(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 a939ee28eb..ec70cf50be 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 @@ namespace { using MslGeneratorImplTest = TestHelper; TEST_F(MslGeneratorImplTest, Emit_ModuleConstant) { - auto* var = Const("pos", ty.array(), array(1.f, 2.f, 3.f)); - WrapInFunction(Decl(var)); + auto* var = + GlobalConst("pos", ty.array(), array(1.f, 2.f, 3.f)); GeneratorImpl& gen = Build(); @@ -33,11 +33,10 @@ TEST_F(MslGeneratorImplTest, Emit_ModuleConstant) { } TEST_F(MslGeneratorImplTest, Emit_SpecConstant) { - auto* var = Const("pos", ty.f32(), Expr(3.f), - ast::DecorationList{ - create(23), - }); - WrapInFunction(Decl(var)); + auto* var = GlobalConst("pos", ty.f32(), Expr(3.f), + ast::DecorationList{ + create(23), + }); GeneratorImpl& gen = Build(); @@ -45,6 +44,25 @@ TEST_F(MslGeneratorImplTest, Emit_SpecConstant) { 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(0), + }); + auto* var_b = GlobalConst("b", ty.f32(), nullptr, + ast::DecorationList{ + create(), + }); + + 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 377ed2c504..2fd180a7a6 100644 --- a/src/writer/spirv/builder.cc +++ b/src/writer/spirv/builder.cc @@ -1493,9 +1493,10 @@ uint32_t Builder::GenerateLiteralIfNeeded(ast::Variable* var, ast::Literal* lit) { ScalarConstant constant; - if (var && ast::HasDecoration(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()) { diff --git a/src/writer/spirv/builder_global_variable_test.cc b/src/writer/spirv/builder_global_variable_test.cc index 79b8d5cfce..d3db49ff72 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_Scalar_U32_NoConstructor) { )"); } +TEST_F(BuilderTest, GlobalVar_Override_NoId) { + auto* var_a = GlobalConst("a", ty.bool_(), Expr(true), + ast::DecorationList{ + create(0), + }); + auto* var_b = GlobalConst("b", ty.bool_(), Expr(false), + ast::DecorationList{ + create(), + }); + + 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 a5be99dcb5..7317829ec3 100644 --- a/src/writer/wgsl/generator_impl.cc +++ b/src/writer/wgsl/generator_impl.cc @@ -609,7 +609,10 @@ bool GeneratorImpl::EmitDecorations(const ast::DecorationList& decos) { } else if (auto* builtin = deco->As()) { out_ << "builtin(" << builtin->value() << ")"; } else if (auto* override_deco = deco->As()) { - out_ << "override(" << override_deco->value() << ")"; + out_ << "override"; + if (override_deco->HasValue()) { + out_ << "(" << override_deco->value() << ")"; + } } else if (auto* size = deco->As()) { out_ << "size(" << size->size() << ")"; } else if (auto* align = deco->As()) { diff --git a/src/writer/wgsl/generator_impl_global_decl_test.cc b/src/writer/wgsl/generator_impl_global_decl_test.cc index 4a9109769c..e9ccecac6b 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 @@ TEST_F(WgslGeneratorImplTest, Emit_Global_Texture) { " [[group(0), binding(0)]] var t : [[access(read)]] texture_1d;\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