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>
This commit is contained in:
James Price 2021-05-13 21:35:42 +00:00 committed by Commit Bot service account
parent f2f3bfc677
commit 26e0312de2
8 changed files with 109 additions and 19 deletions

View File

@ -2689,8 +2689,8 @@ bool GeneratorImpl::EmitProgramConstVariable(std::ostream& out,
auto* sem = builder_.Sem().Get(var); auto* sem = builder_.Sem().Get(var);
auto* type = sem->Type(); auto* type = sem->Type();
if (ast::HasDecoration<ast::OverrideDecoration>(var->decorations())) { if (sem->IsPipelineConstant()) {
auto const_id = var->constant_id(); auto const_id = sem->ConstantId();
out << "#ifndef WGSL_SPEC_CONSTANT_" << const_id << std::endl; out << "#ifndef WGSL_SPEC_CONSTANT_" << const_id << std::endl;

View File

@ -33,11 +33,10 @@ TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_ModuleConstant) {
} }
TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant) { TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant) {
auto* var = Const("pos", ty.f32(), Expr(3.0f), auto* var = GlobalConst("pos", ty.f32(), Expr(3.0f),
ast::DecorationList{ ast::DecorationList{
create<ast::OverrideDecoration>(23), create<ast::OverrideDecoration>(23),
}); });
WrapInFunction(Decl(var));
GeneratorImpl& gen = Build(); 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<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
} // namespace hlsl } // namespace hlsl
} // namespace writer } // namespace writer

View File

@ -2257,8 +2257,9 @@ bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) {
out_ << " " << program_->Symbols().NameFor(var->symbol()); out_ << " " << program_->Symbols().NameFor(var->symbol());
} }
if (ast::HasDecoration<ast::OverrideDecoration>(var->decorations())) { auto* sem_var = program_->Sem().Get(var);
out_ << " [[function_constant(" << var->constant_id() << ")]]"; if (sem_var->IsPipelineConstant()) {
out_ << " [[function_constant(" << sem_var->ConstantId() << ")]]";
} else if (var->constructor() != nullptr) { } else if (var->constructor() != nullptr) {
out_ << " = "; out_ << " = ";
if (!EmitExpression(var->constructor())) { if (!EmitExpression(var->constructor())) {

View File

@ -23,8 +23,8 @@ namespace {
using MslGeneratorImplTest = TestHelper; using MslGeneratorImplTest = TestHelper;
TEST_F(MslGeneratorImplTest, Emit_ModuleConstant) { TEST_F(MslGeneratorImplTest, Emit_ModuleConstant) {
auto* var = Const("pos", ty.array<f32, 3>(), array<f32, 3>(1.f, 2.f, 3.f)); auto* var =
WrapInFunction(Decl(var)); GlobalConst("pos", ty.array<f32, 3>(), array<f32, 3>(1.f, 2.f, 3.f));
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
@ -33,11 +33,10 @@ TEST_F(MslGeneratorImplTest, Emit_ModuleConstant) {
} }
TEST_F(MslGeneratorImplTest, Emit_SpecConstant) { TEST_F(MslGeneratorImplTest, Emit_SpecConstant) {
auto* var = Const("pos", ty.f32(), Expr(3.f), auto* var = GlobalConst("pos", ty.f32(), Expr(3.f),
ast::DecorationList{ ast::DecorationList{
create<ast::OverrideDecoration>(23), create<ast::OverrideDecoration>(23),
}); });
WrapInFunction(Decl(var));
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
@ -45,6 +44,25 @@ TEST_F(MslGeneratorImplTest, Emit_SpecConstant) {
EXPECT_EQ(gen.result(), "constant float pos [[function_constant(23)]];\n"); 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
} // namespace msl } // namespace msl
} // namespace writer } // namespace writer

View File

@ -1493,9 +1493,10 @@ uint32_t Builder::GenerateLiteralIfNeeded(ast::Variable* var,
ast::Literal* lit) { ast::Literal* lit) {
ScalarConstant constant; 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.is_spec_op = true;
constant.constant_id = var->constant_id(); constant.constant_id = sem_var->ConstantId();
} }
if (auto* l = lit->As<ast::BoolLiteral>()) { if (auto* l = lit->As<ast::BoolLiteral>()) {

View File

@ -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<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 { struct BuiltinData {
ast::Builtin builtin; ast::Builtin builtin;
ast::StorageClass storage; ast::StorageClass storage;

View File

@ -609,7 +609,10 @@ bool GeneratorImpl::EmitDecorations(const ast::DecorationList& decos) {
} else if (auto* builtin = deco->As<ast::BuiltinDecoration>()) { } else if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
out_ << "builtin(" << builtin->value() << ")"; out_ << "builtin(" << builtin->value() << ")";
} else if (auto* override_deco = deco->As<ast::OverrideDecoration>()) { } 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>()) { } else if (auto* size = deco->As<ast::StructMemberSizeDecoration>()) {
out_ << "size(" << size->size() << ")"; out_ << "size(" << size->size() << ")";
} else if (auto* align = deco->As<ast::StructMemberAlignDecoration>()) { } else if (auto* align = deco->As<ast::StructMemberAlignDecoration>()) {

View File

@ -129,6 +129,21 @@ TEST_F(WgslGeneratorImplTest, Emit_Global_Texture) {
" [[group(0), binding(0)]] var t : [[access(read)]] texture_1d<f32>;\n"); " [[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
} // namespace wgsl } // namespace wgsl
} // namespace writer } // namespace writer