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:
parent
f2f3bfc677
commit
26e0312de2
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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())) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>()) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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>()) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue