diff --git a/src/ast/variable.cc b/src/ast/variable.cc index 54d15d7dc2..67447a5954 100644 --- a/src/ast/variable.cc +++ b/src/ast/variable.cc @@ -41,6 +41,11 @@ DecoratedVariable* Variable::AsDecorated() { return static_cast(this); } +const DecoratedVariable* Variable::AsDecorated() const { + assert(IsDecorated()); + return static_cast(this); +} + bool Variable::IsDecorated() const { return false; } diff --git a/src/ast/variable.h b/src/ast/variable.h index f94036375c..f2df3456a5 100644 --- a/src/ast/variable.h +++ b/src/ast/variable.h @@ -141,6 +141,8 @@ class Variable : public Node { /// @returns the expression as a decorated variable DecoratedVariable* AsDecorated(); + /// @returns the expression as a decorated variable + const DecoratedVariable* AsDecorated() const; /// @returns true if the name and path are both present bool IsValid() const override; diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc index be20cdfb67..092a4873fd 100644 --- a/src/writer/msl/generator_impl.cc +++ b/src/writer/msl/generator_impl.cc @@ -1829,7 +1829,7 @@ bool GeneratorImpl::EmitVariable(ast::Variable* var, bool skip_constructor) { bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) { make_indent(); - if (var->IsDecorated()) { + if (var->IsDecorated() && !var->AsDecorated()->HasConstantIdDecoration()) { error_ = "Decorated const values not valid"; return false; } @@ -1846,7 +1846,10 @@ bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) { out_ << " " << var->name(); } - if (var->constructor() != nullptr) { + if (var->IsDecorated() && var->AsDecorated()->HasConstantIdDecoration()) { + out_ << " [[function_constant(" << var->AsDecorated()->constant_id() + << ")]]"; + } else if (var->constructor() != nullptr) { out_ << " = "; if (!EmitExpression(var->constructor())) { return false; diff --git a/src/writer/msl/generator_impl_module_constant_test.cc b/src/writer/msl/generator_impl_module_constant_test.cc index 875f279c21..f20aad6d2f 100644 --- a/src/writer/msl/generator_impl_module_constant_test.cc +++ b/src/writer/msl/generator_impl_module_constant_test.cc @@ -16,6 +16,8 @@ #include #include "gtest/gtest.h" +#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" @@ -58,6 +60,25 @@ TEST_F(MslGeneratorImplTest, Emit_ModuleConstant) { "constant float pos[3] = {1.00000000f, 2.00000000f, 3.00000000f};\n"); } +TEST_F(MslGeneratorImplTest, 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))); + + ast::Module m; + GeneratorImpl g(&m); + ASSERT_TRUE(g.EmitProgramConstVariable(var.get())) << g.error(); + EXPECT_EQ(g.result(), "constant float pos [[function_constant(23)]];\n"); +} + } // namespace } // namespace msl } // namespace writer