[hlsl-writer] Emit specialization variables This CL adds specialization to the HLSL backend. The specialization is emulated using defined preprocessor macros. Bug: tint:154 Change-Id: I73ab42360558967eee9a0da6bbe74d513fe4cc57 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/29720 Commit-Queue: David Neto <dneto@google.com> Reviewed-by: David Neto <dneto@google.com>
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc index 86eef79..1ed6c02 100644 --- a/src/writer/hlsl/generator_impl.cc +++ b/src/writer/hlsl/generator_impl.cc
@@ -2053,7 +2053,7 @@ const ast::Variable* var) { make_indent(out); - if (var->IsDecorated()) { + if (var->IsDecorated() && !var->AsDecorated()->HasConstantIdDecoration()) { error_ = "Decorated const values not valid"; return false; } @@ -2064,8 +2064,6 @@ std::ostringstream constructor_out; if (var->constructor() != nullptr) { - constructor_out << " = "; - std::ostringstream pre; if (!EmitExpression(pre, constructor_out, var->constructor())) { return false; @@ -2073,14 +2071,40 @@ out << pre.str(); } - out << "static const "; - if (!EmitType(out, var->type(), var->name())) { - return false; + if (var->IsDecorated() && var->AsDecorated()->HasConstantIdDecoration()) { + auto const_id = var->AsDecorated()->constant_id(); + + out << "#ifndef WGSL_SPEC_CONSTANT_" << const_id << std::endl; + + if (var->constructor() != nullptr) { + out << "#define WGSL_SPEC_CONSTANT_" << const_id << " " + << constructor_out.str() << std::endl; + } else { + out << "#error spec constant required for constant id " << const_id + << std::endl; + } + out << "#endif" << std::endl; + out << "static const "; + if (!EmitType(out, var->type(), var->name())) { + return false; + } + out << " " << var->name() << " = WGSL_SPEC_CONSTANT_" << const_id << ";" + << std::endl; + out << "#undef WGSL_SPEC_CONSTANT_" << const_id << std::endl; + } else { + out << "static const "; + if (!EmitType(out, var->type(), var->name())) { + return false; + } + if (!var->type()->IsArray()) { + out << " " << var->name(); + } + + if (var->constructor() != nullptr) { + out << " = " << constructor_out.str(); + } + out << ";" << std::endl; } - if (!var->type()->IsArray()) { - out << " " << var->name(); - } - out << constructor_out.str() << ";" << std::endl; return true; }
diff --git a/src/writer/hlsl/generator_impl_module_constant_test.cc b/src/writer/hlsl/generator_impl_module_constant_test.cc index abad8ea..94ffb8e 100644 --- a/src/writer/hlsl/generator_impl_module_constant_test.cc +++ b/src/writer/hlsl/generator_impl_module_constant_test.cc
@@ -15,6 +15,8 @@ #include <memory> #include <vector> +#include "src/ast/constant_id_decoration.h" +#include "src/ast/decorated_variable.h" #include "src/ast/float_literal.h" #include "src/ast/module.h" #include "src/ast/scalar_constructor_expression.h" @@ -56,6 +58,50 @@ "static const float pos[3] = {1.00000000f, 2.00000000f, 3.00000000f};\n"); } +TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant) { + ast::type::F32Type f32; + + ast::VariableDecorationList decos; + decos.push_back(std::make_unique<ast::ConstantIdDecoration>(23)); + + auto var = std::make_unique<ast::DecoratedVariable>( + std::make_unique<ast::Variable>("pos", ast::StorageClass::kNone, &f32)); + var->set_decorations(std::move(decos)); + var->set_is_const(true); + var->set_constructor(std::make_unique<ast::ScalarConstructorExpression>( + std::make_unique<ast::FloatLiteral>(&f32, 3.0f))); + + ASSERT_TRUE(gen().EmitProgramConstVariable(out(), var.get())) + << gen().error(); + EXPECT_EQ(result(), R"(#ifndef WGSL_SPEC_CONSTANT_23 +#define WGSL_SPEC_CONSTANT_23 3.00000000f +#endif +static const float pos = WGSL_SPEC_CONSTANT_23; +#undef WGSL_SPEC_CONSTANT_23 +)"); +} + +TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant_NoConstructor) { + ast::type::F32Type f32; + + ast::VariableDecorationList decos; + decos.push_back(std::make_unique<ast::ConstantIdDecoration>(23)); + + auto var = std::make_unique<ast::DecoratedVariable>( + std::make_unique<ast::Variable>("pos", ast::StorageClass::kNone, &f32)); + var->set_decorations(std::move(decos)); + var->set_is_const(true); + + ASSERT_TRUE(gen().EmitProgramConstVariable(out(), var.get())) + << gen().error(); + EXPECT_EQ(result(), R"(#ifndef WGSL_SPEC_CONSTANT_23 +#error spec constant required for constant id 23 +#endif +static const float pos = WGSL_SPEC_CONSTANT_23; +#undef WGSL_SPEC_CONSTANT_23 +)"); +} + } // namespace } // namespace hlsl } // namespace writer