From fc5c5ab60b22e9d04fe4e2ab3594cd0205fd15a3 Mon Sep 17 00:00:00 2001 From: dan sinclair Date: Thu, 8 Oct 2020 16:22:45 +0000 Subject: [PATCH] [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 Reviewed-by: David Neto --- src/writer/hlsl/generator_impl.cc | 44 ++++++++++++++---- .../generator_impl_module_constant_test.cc | 46 +++++++++++++++++++ 2 files changed, 80 insertions(+), 10 deletions(-) diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc index 86eef79907..1ed6c02b10 100644 --- a/src/writer/hlsl/generator_impl.cc +++ b/src/writer/hlsl/generator_impl.cc @@ -2053,7 +2053,7 @@ bool GeneratorImpl::EmitProgramConstVariable(std::ostream& out, 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 @@ bool GeneratorImpl::EmitProgramConstVariable(std::ostream& out, 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 @@ bool GeneratorImpl::EmitProgramConstVariable(std::ostream& out, 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 abad8ea211..94ffb8e91f 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 #include +#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 @@ TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_ModuleConstant) { "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(23)); + + auto var = std::make_unique( + std::make_unique("pos", ast::StorageClass::kNone, &f32)); + var->set_decorations(std::move(decos)); + var->set_is_const(true); + var->set_constructor(std::make_unique( + std::make_unique(&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(23)); + + auto var = std::make_unique( + std::make_unique("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