diff --git a/include/Nazara/Shader/Ast/AstCloner.hpp b/include/Nazara/Shader/Ast/AstCloner.hpp index a81acfdff..fabe55e86 100644 --- a/include/Nazara/Shader/Ast/AstCloner.hpp +++ b/include/Nazara/Shader/Ast/AstCloner.hpp @@ -57,6 +57,7 @@ namespace Nz::ShaderAst virtual StatementPtr Clone(BranchStatement& node); virtual StatementPtr Clone(ConditionalStatement& node); + virtual StatementPtr Clone(DeclareConstStatement& node); virtual StatementPtr Clone(DeclareExternalStatement& node); virtual StatementPtr Clone(DeclareFunctionStatement& node); virtual StatementPtr Clone(DeclareOptionStatement& node); diff --git a/include/Nazara/Shader/Ast/AstNodeList.hpp b/include/Nazara/Shader/Ast/AstNodeList.hpp index 60978d8bd..56063107f 100644 --- a/include/Nazara/Shader/Ast/AstNodeList.hpp +++ b/include/Nazara/Shader/Ast/AstNodeList.hpp @@ -44,6 +44,7 @@ NAZARA_SHADERAST_EXPRESSION(VariableExpression) NAZARA_SHADERAST_EXPRESSION(UnaryExpression) NAZARA_SHADERAST_STATEMENT(BranchStatement) NAZARA_SHADERAST_STATEMENT(ConditionalStatement) +NAZARA_SHADERAST_STATEMENT(DeclareConstStatement) NAZARA_SHADERAST_STATEMENT(DeclareExternalStatement) NAZARA_SHADERAST_STATEMENT(DeclareFunctionStatement) NAZARA_SHADERAST_STATEMENT(DeclareOptionStatement) diff --git a/include/Nazara/Shader/Ast/AstRecursiveVisitor.hpp b/include/Nazara/Shader/Ast/AstRecursiveVisitor.hpp index 9410b4cb6..cc5d0d19e 100644 --- a/include/Nazara/Shader/Ast/AstRecursiveVisitor.hpp +++ b/include/Nazara/Shader/Ast/AstRecursiveVisitor.hpp @@ -39,6 +39,7 @@ namespace Nz::ShaderAst void Visit(BranchStatement& node) override; void Visit(ConditionalStatement& node) override; + void Visit(DeclareConstStatement& node) override; void Visit(DeclareExternalStatement& node) override; void Visit(DeclareFunctionStatement& node) override; void Visit(DeclareOptionStatement& node) override; diff --git a/include/Nazara/Shader/Ast/AstSerializer.hpp b/include/Nazara/Shader/Ast/AstSerializer.hpp index 9756fcfca..7c90ead4d 100644 --- a/include/Nazara/Shader/Ast/AstSerializer.hpp +++ b/include/Nazara/Shader/Ast/AstSerializer.hpp @@ -42,6 +42,7 @@ namespace Nz::ShaderAst void Serialize(BranchStatement& node); void Serialize(ConditionalStatement& node); + void Serialize(DeclareConstStatement& node); void Serialize(DeclareExternalStatement& node); void Serialize(DeclareFunctionStatement& node); void Serialize(DeclareOptionStatement& node); diff --git a/include/Nazara/Shader/Ast/Nodes.hpp b/include/Nazara/Shader/Ast/Nodes.hpp index c1b8d4de8..3c12e60de 100644 --- a/include/Nazara/Shader/Ast/Nodes.hpp +++ b/include/Nazara/Shader/Ast/Nodes.hpp @@ -242,6 +242,7 @@ namespace Nz::ShaderAst std::vector condStatements; StatementPtr elseStatement; + bool isConst = false; }; struct NAZARA_SHADER_API ConditionalStatement : Statement @@ -253,6 +254,17 @@ namespace Nz::ShaderAst StatementPtr statement; }; + struct NAZARA_SHADER_API DeclareConstStatement : Statement + { + NodeType GetType() const override; + void Visit(AstStatementVisitor& visitor) override; + + std::optional constIndex; + std::string name; + ExpressionPtr expression; + ExpressionType type; + }; + struct NAZARA_SHADER_API DeclareExternalStatement : Statement { NodeType GetType() const override; diff --git a/include/Nazara/Shader/Ast/SanitizeVisitor.hpp b/include/Nazara/Shader/Ast/SanitizeVisitor.hpp index 1fbb305e0..067fd340e 100644 --- a/include/Nazara/Shader/Ast/SanitizeVisitor.hpp +++ b/include/Nazara/Shader/Ast/SanitizeVisitor.hpp @@ -55,14 +55,17 @@ namespace Nz::ShaderAst ExpressionPtr Clone(CastExpression& node) override; ExpressionPtr Clone(ConditionalExpression& node) override; ExpressionPtr Clone(ConstantExpression& node) override; + ExpressionPtr Clone(ConstantIndexExpression& node) override; ExpressionPtr Clone(IdentifierExpression& node) override; ExpressionPtr Clone(IntrinsicExpression& node) override; ExpressionPtr Clone(SelectOptionExpression& node) override; ExpressionPtr Clone(SwizzleExpression& node) override; ExpressionPtr Clone(UnaryExpression& node) override; + ExpressionPtr Clone(VariableExpression& node) override; StatementPtr Clone(BranchStatement& node) override; StatementPtr Clone(ConditionalStatement& node) override; + StatementPtr Clone(DeclareConstStatement& node) override; StatementPtr Clone(DeclareExternalStatement& node) override; StatementPtr Clone(DeclareFunctionStatement& node) override; StatementPtr Clone(DeclareOptionStatement& node) override; @@ -84,6 +87,7 @@ namespace Nz::ShaderAst template const T& ComputeAttributeValue(AttributeValue& attribute); ConstantValue ComputeConstantValue(Expression& expr); + template std::unique_ptr Optimize(T& node); std::size_t DeclareFunction(DeclareFunctionStatement& funcDecl); diff --git a/include/Nazara/Shader/GlslWriter.hpp b/include/Nazara/Shader/GlslWriter.hpp index 5bb96e34c..7481d2857 100644 --- a/include/Nazara/Shader/GlslWriter.hpp +++ b/include/Nazara/Shader/GlslWriter.hpp @@ -93,6 +93,7 @@ namespace Nz void Visit(ShaderAst::UnaryExpression& node) override; void Visit(ShaderAst::BranchStatement& node) override; + void Visit(ShaderAst::DeclareConstStatement& node) override; void Visit(ShaderAst::DeclareExternalStatement& node) override; void Visit(ShaderAst::DeclareFunctionStatement& node) override; void Visit(ShaderAst::DeclareOptionStatement& node) override; diff --git a/include/Nazara/Shader/ShaderBuilder.hpp b/include/Nazara/Shader/ShaderBuilder.hpp index 945f3f725..1fb4f2b3f 100644 --- a/include/Nazara/Shader/ShaderBuilder.hpp +++ b/include/Nazara/Shader/ShaderBuilder.hpp @@ -38,6 +38,7 @@ namespace Nz::ShaderBuilder inline std::unique_ptr operator()(ShaderAst::BinaryType op, ShaderAst::ExpressionPtr left, ShaderAst::ExpressionPtr right) const; }; + template struct Branch { inline std::unique_ptr operator()(ShaderAst::ExpressionPtr condition, ShaderAst::StatementPtr truePath, ShaderAst::StatementPtr falsePath = nullptr) const; @@ -70,6 +71,12 @@ namespace Nz::ShaderBuilder inline std::unique_ptr operator()(ShaderAst::ConstantValue value) const; }; + struct DeclareConst + { + inline std::unique_ptr operator()(std::string name, ShaderAst::ExpressionPtr initialValue) const; + inline std::unique_ptr operator()(std::string name, ShaderAst::ExpressionType type, ShaderAst::ExpressionPtr initialValue = nullptr) const; + }; + struct DeclareFunction { inline std::unique_ptr operator()(std::string name, ShaderAst::StatementPtr statement) const; @@ -144,12 +151,14 @@ namespace Nz::ShaderBuilder constexpr Impl::AccessMember AccessMember; constexpr Impl::Assign Assign; constexpr Impl::Binary Binary; - constexpr Impl::Branch Branch; + constexpr Impl::Branch Branch; constexpr Impl::CallFunction CallFunction; constexpr Impl::Cast Cast; constexpr Impl::ConditionalExpression ConditionalExpression; constexpr Impl::ConditionalStatement ConditionalStatement; constexpr Impl::Constant Constant; + constexpr Impl::Branch ConstBranch; + constexpr Impl::DeclareConst DeclareConst; constexpr Impl::DeclareFunction DeclareFunction; constexpr Impl::DeclareOption DeclareOption; constexpr Impl::DeclareStruct DeclareStruct; diff --git a/include/Nazara/Shader/ShaderBuilder.inl b/include/Nazara/Shader/ShaderBuilder.inl index 912edd345..897cf51e3 100644 --- a/include/Nazara/Shader/ShaderBuilder.inl +++ b/include/Nazara/Shader/ShaderBuilder.inl @@ -57,7 +57,8 @@ namespace Nz::ShaderBuilder return binaryNode; } - inline std::unique_ptr Impl::Branch::operator()(ShaderAst::ExpressionPtr condition, ShaderAst::StatementPtr truePath, ShaderAst::StatementPtr falsePath) const + template + std::unique_ptr Impl::Branch::operator()(ShaderAst::ExpressionPtr condition, ShaderAst::StatementPtr truePath, ShaderAst::StatementPtr falsePath) const { auto branchNode = std::make_unique(); @@ -66,15 +67,18 @@ namespace Nz::ShaderBuilder condStatement.statement = std::move(truePath); branchNode->elseStatement = std::move(falsePath); + branchNode->isConst = Const; return branchNode; } - inline std::unique_ptr Impl::Branch::operator()(std::vector condStatements, ShaderAst::StatementPtr elseStatement) const + template + std::unique_ptr Impl::Branch::operator()(std::vector condStatements, ShaderAst::StatementPtr elseStatement) const { auto branchNode = std::make_unique(); branchNode->condStatements = std::move(condStatements); branchNode->elseStatement = std::move(elseStatement); + branchNode->isConst = Const; return branchNode; } @@ -136,6 +140,25 @@ namespace Nz::ShaderBuilder return constantNode; } + inline std::unique_ptr Impl::DeclareConst::operator()(std::string name, ShaderAst::ExpressionPtr initialValue) const + { + auto declareConstNode = std::make_unique(); + declareConstNode->name = std::move(name); + declareConstNode->expression = std::move(initialValue); + + return declareConstNode; + } + + inline std::unique_ptr Impl::DeclareConst::operator()(std::string name, ShaderAst::ExpressionType type, ShaderAst::ExpressionPtr initialValue) const + { + auto declareConstNode = std::make_unique(); + declareConstNode->name = std::move(name); + declareConstNode->type = std::move(type); + declareConstNode->expression = std::move(initialValue); + + return declareConstNode; + } + inline std::unique_ptr Impl::DeclareFunction::operator()(std::string name, ShaderAst::StatementPtr statement) const { auto declareFunctionNode = std::make_unique(); diff --git a/include/Nazara/Shader/ShaderLangParser.hpp b/include/Nazara/Shader/ShaderLangParser.hpp index b8b43257e..ac78d986f 100644 --- a/include/Nazara/Shader/ShaderLangParser.hpp +++ b/include/Nazara/Shader/ShaderLangParser.hpp @@ -81,9 +81,11 @@ namespace Nz::ShaderLang const Token& Peek(std::size_t advance = 0); std::vector ParseAttributes(); + void ParseVariableDeclaration(std::string& name, ShaderAst::ExpressionType& type, ShaderAst::ExpressionPtr& initialValue); // Statements ShaderAst::StatementPtr ParseBranchStatement(); + ShaderAst::StatementPtr ParseConstStatement(); ShaderAst::StatementPtr ParseDiscardStatement(); ShaderAst::StatementPtr ParseExternalBlock(std::vector attributes = {}); std::vector ParseFunctionBody(); diff --git a/include/Nazara/Shader/ShaderLangTokenList.hpp b/include/Nazara/Shader/ShaderLangTokenList.hpp index 1bb6a3898..4137ed391 100644 --- a/include/Nazara/Shader/ShaderLangTokenList.hpp +++ b/include/Nazara/Shader/ShaderLangTokenList.hpp @@ -18,6 +18,7 @@ NAZARA_SHADERLANG_TOKEN(ClosingCurlyBracket) NAZARA_SHADERLANG_TOKEN(ClosingSquareBracket) NAZARA_SHADERLANG_TOKEN(Colon) NAZARA_SHADERLANG_TOKEN(Comma) +NAZARA_SHADERLANG_TOKEN(Const) NAZARA_SHADERLANG_TOKEN(Discard) NAZARA_SHADERLANG_TOKEN(Divide) NAZARA_SHADERLANG_TOKEN(Dot) diff --git a/include/Nazara/Shader/SpirvAstVisitor.hpp b/include/Nazara/Shader/SpirvAstVisitor.hpp index bc17eed57..41e305b7e 100644 --- a/include/Nazara/Shader/SpirvAstVisitor.hpp +++ b/include/Nazara/Shader/SpirvAstVisitor.hpp @@ -48,6 +48,7 @@ namespace Nz void Visit(ShaderAst::CallFunctionExpression& node) override; void Visit(ShaderAst::CastExpression& node) override; void Visit(ShaderAst::ConstantExpression& node) override; + void Visit(ShaderAst::DeclareConstStatement& node) override; void Visit(ShaderAst::DeclareExternalStatement& node) override; void Visit(ShaderAst::DeclareFunctionStatement& node) override; void Visit(ShaderAst::DeclareOptionStatement& node) override; diff --git a/src/Nazara/Graphics/BasicMaterial.cpp b/src/Nazara/Graphics/BasicMaterial.cpp index 059af323c..eedc49434 100644 --- a/src/Nazara/Graphics/BasicMaterial.cpp +++ b/src/Nazara/Graphics/BasicMaterial.cpp @@ -161,6 +161,7 @@ namespace Nz std::array shaderConditions; shaderConditions.fill(0); shaderConditions[UnderlyingCast(ShaderStageType::Fragment)] = fragmentShader->GetOptionFlagByName("HAS_DIFFUSE_TEXTURE"); + shaderConditions[UnderlyingCast(ShaderStageType::Vertex)] = vertexShader->GetOptionFlagByName("HAS_DIFFUSE_TEXTURE"); s_conditionIndexes.hasDiffuseMap = settings.conditions.size(); settings.conditions.push_back({ @@ -174,6 +175,7 @@ namespace Nz std::array shaderConditions; shaderConditions.fill(0); shaderConditions[UnderlyingCast(ShaderStageType::Fragment)] = fragmentShader->GetOptionFlagByName("HAS_ALPHA_TEXTURE"); + shaderConditions[UnderlyingCast(ShaderStageType::Vertex)] = vertexShader->GetOptionFlagByName("HAS_ALPHA_TEXTURE"); s_conditionIndexes.hasAlphaMap = settings.conditions.size(); settings.conditions.push_back({ diff --git a/src/Nazara/Graphics/Resources/Shaders/basicmaterial.nzsl b/src/Nazara/Graphics/Resources/Shaders/basicmaterial.nzsl index b49934b8a..201d5bf83 100644 --- a/src/Nazara/Graphics/Resources/Shaders/basicmaterial.nzsl +++ b/src/Nazara/Graphics/Resources/Shaders/basicmaterial.nzsl @@ -2,6 +2,8 @@ option HAS_DIFFUSE_TEXTURE: bool; option HAS_ALPHA_TEXTURE: bool; option ALPHA_TEST: bool; +const HasUV = HAS_DIFFUSE_TEXTURE || HAS_ALPHA_TEXTURE; + [layout(std140)] struct BasicSettings { @@ -42,7 +44,7 @@ external // Fragment stage struct FragIn { - [location(0)] uv: vec2 + [location(0), cond(HasUV)] uv: vec2 } struct FragOut @@ -68,12 +70,12 @@ fn main(input: FragIn) -> FragOut struct VertIn { [location(0)] pos: vec3, - [location(1)] uv: vec2 + [location(1), cond(HasUV)] uv: vec2 } struct VertOut { - [location(0)] uv: vec2, + [location(0), cond(HasUV)] uv: vec2, [builtin(position)] position: vec4 } @@ -81,8 +83,10 @@ struct VertOut fn main(input: VertIn) -> VertOut { let output: VertOut; - output.uv = input.uv; output.position = viewerData.projectionMatrix * viewerData.viewMatrix * instanceData.worldMatrix * vec4(input.pos, 1.0); + const if (HasUV) + output.uv = input.uv; + return output; } diff --git a/src/Nazara/Graphics/Resources/Shaders/basicmaterial.nzsl.h b/src/Nazara/Graphics/Resources/Shaders/basicmaterial.nzsl.h index a69cedd84..f98fc1b21 100644 --- a/src/Nazara/Graphics/Resources/Shaders/basicmaterial.nzsl.h +++ b/src/Nazara/Graphics/Resources/Shaders/basicmaterial.nzsl.h @@ -1 +1 @@ -111,112,116,105,111,110,32,72,65,83,95,68,73,70,70,85,83,69,95,84,69,88,84,85,82,69,58,32,98,111,111,108,59,10,111,112,116,105,111,110,32,72,65,83,95,65,76,80,72,65,95,84,69,88,84,85,82,69,58,32,98,111,111,108,59,10,111,112,116,105,111,110,32,65,76,80,72,65,95,84,69,83,84,58,32,98,111,111,108,59,10,10,91,108,97,121,111,117,116,40,115,116,100,49,52,48,41,93,10,115,116,114,117,99,116,32,66,97,115,105,99,83,101,116,116,105,110,103,115,10,123,10,9,65,108,112,104,97,84,104,114,101,115,104,111,108,100,58,32,102,51,50,44,10,9,68,105,102,102,117,115,101,67,111,108,111,114,58,32,118,101,99,52,60,102,51,50,62,10,125,10,10,91,108,97,121,111,117,116,40,115,116,100,49,52,48,41,93,10,115,116,114,117,99,116,32,73,110,115,116,97,110,99,101,68,97,116,97,10,123,10,9,119,111,114,108,100,77,97,116,114,105,120,58,32,109,97,116,52,60,102,51,50,62,44,10,9,105,110,118,87,111,114,108,100,77,97,116,114,105,120,58,32,109,97,116,52,60,102,51,50,62,10,125,10,10,91,108,97,121,111,117,116,40,115,116,100,49,52,48,41,93,10,115,116,114,117,99,116,32,86,105,101,119,101,114,68,97,116,97,10,123,10,9,112,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,58,32,109,97,116,52,60,102,51,50,62,44,10,9,105,110,118,80,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,58,32,109,97,116,52,60,102,51,50,62,44,10,9,118,105,101,119,77,97,116,114,105,120,58,32,109,97,116,52,60,102,51,50,62,44,10,9,105,110,118,86,105,101,119,77,97,116,114,105,120,58,32,109,97,116,52,60,102,51,50,62,44,10,9,118,105,101,119,80,114,111,106,77,97,116,114,105,120,58,32,109,97,116,52,60,102,51,50,62,44,10,9,105,110,118,86,105,101,119,80,114,111,106,77,97,116,114,105,120,58,32,109,97,116,52,60,102,51,50,62,44,10,9,114,101,110,100,101,114,84,97,114,103,101,116,83,105,122,101,58,32,118,101,99,50,60,102,51,50,62,44,10,9,105,110,118,82,101,110,100,101,114,84,97,114,103,101,116,83,105,122,101,58,32,118,101,99,50,60,102,51,50,62,44,10,9,101,121,101,80,111,115,105,116,105,111,110,58,32,118,101,99,51,60,102,51,50,62,10,125,10,10,101,120,116,101,114,110,97,108,10,123,10,9,91,115,101,116,40,48,41,44,32,98,105,110,100,105,110,103,40,48,41,93,32,118,105,101,119,101,114,68,97,116,97,58,32,117,110,105,102,111,114,109,60,86,105,101,119,101,114,68,97,116,97,62,44,10,9,91,115,101,116,40,49,41,44,32,98,105,110,100,105,110,103,40,48,41,93,32,105,110,115,116,97,110,99,101,68,97,116,97,58,32,117,110,105,102,111,114,109,60,73,110,115,116,97,110,99,101,68,97,116,97,62,44,10,9,91,115,101,116,40,50,41,44,32,98,105,110,100,105,110,103,40,48,41,93,32,115,101,116,116,105,110,103,115,58,32,117,110,105,102,111,114,109,60,66,97,115,105,99,83,101,116,116,105,110,103,115,62,44,10,9,91,115,101,116,40,50,41,44,32,98,105,110,100,105,110,103,40,50,41,93,32,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,58,32,115,97,109,112,108,101,114,50,68,60,102,51,50,62,44,10,9,91,115,101,116,40,50,41,44,32,98,105,110,100,105,110,103,40,49,41,93,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,58,32,115,97,109,112,108,101,114,50,68,60,102,51,50,62,10,125,10,10,47,47,32,70,114,97,103,109,101,110,116,32,115,116,97,103,101,10,115,116,114,117,99,116,32,70,114,97,103,73,110,10,123,10,9,91,108,111,99,97,116,105,111,110,40,48,41,93,32,117,118,58,32,118,101,99,50,60,102,51,50,62,10,125,10,10,115,116,114,117,99,116,32,70,114,97,103,79,117,116,10,123,10,9,91,108,111,99,97,116,105,111,110,40,48,41,93,32,82,101,110,100,101,114,84,97,114,103,101,116,48,58,32,118,101,99,52,60,102,51,50,62,10,125,10,10,91,101,110,116,114,121,40,102,114,97,103,41,93,10,102,110,32,109,97,105,110,40,105,110,112,117,116,58,32,70,114,97,103,73,110,41,32,45,62,32,70,114,97,103,79,117,116,10,123,10,9,108,101,116,32,111,117,116,112,117,116,58,32,70,114,97,103,79,117,116,59,10,9,108,101,116,32,100,105,102,102,117,115,101,67,111,108,111,114,32,61,32,115,101,108,101,99,116,95,111,112,116,40,72,65,83,95,68,73,70,70,85,83,69,95,84,69,88,84,85,82,69,44,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,46,83,97,109,112,108,101,40,105,110,112,117,116,46,117,118,41,32,42,32,115,101,116,116,105,110,103,115,46,68,105,102,102,117,115,101,67,111,108,111,114,44,32,115,101,116,116,105,110,103,115,46,68,105,102,102,117,115,101,67,111,108,111,114,41,59,10,9,108,101,116,32,100,105,102,102,117,115,101,67,111,108,111,114,32,61,32,115,101,108,101,99,116,95,111,112,116,40,72,65,83,95,65,76,80,72,65,95,84,69,88,84,85,82,69,44,32,118,101,99,52,60,102,51,50,62,40,100,105,102,102,117,115,101,67,111,108,111,114,46,120,44,32,100,105,102,102,117,115,101,67,111,108,111,114,46,121,44,32,100,105,102,102,117,115,101,67,111,108,111,114,46,122,44,32,40,40,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,46,83,97,109,112,108,101,40,105,110,112,117,116,46,117,118,41,41,46,120,41,32,42,32,100,105,102,102,117,115,101,67,111,108,111,114,46,119,41,44,32,100,105,102,102,117,115,101,67,111,108,111,114,41,59,10,10,9,105,102,32,40,115,101,108,101,99,116,95,111,112,116,40,65,76,80,72,65,95,84,69,83,84,44,32,100,105,102,102,117,115,101,67,111,108,111,114,46,119,32,60,32,115,101,116,116,105,110,103,115,46,65,108,112,104,97,84,104,114,101,115,104,111,108,100,44,32,102,97,108,115,101,41,41,10,9,9,100,105,115,99,97,114,100,59,10,10,9,111,117,116,112,117,116,46,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,100,105,102,102,117,115,101,67,111,108,111,114,59,10,9,114,101,116,117,114,110,32,111,117,116,112,117,116,59,10,125,10,10,47,47,32,86,101,114,116,101,120,32,115,116,97,103,101,10,115,116,114,117,99,116,32,86,101,114,116,73,110,10,123,10,9,91,108,111,99,97,116,105,111,110,40,48,41,93,32,112,111,115,58,32,118,101,99,51,60,102,51,50,62,44,10,9,91,108,111,99,97,116,105,111,110,40,49,41,93,32,117,118,58,32,118,101,99,50,60,102,51,50,62,10,125,10,10,115,116,114,117,99,116,32,86,101,114,116,79,117,116,10,123,10,9,91,108,111,99,97,116,105,111,110,40,48,41,93,32,117,118,58,32,118,101,99,50,60,102,51,50,62,44,10,9,91,98,117,105,108,116,105,110,40,112,111,115,105,116,105,111,110,41,93,32,112,111,115,105,116,105,111,110,58,32,118,101,99,52,60,102,51,50,62,10,125,10,10,91,101,110,116,114,121,40,118,101,114,116,41,93,10,102,110,32,109,97,105,110,40,105,110,112,117,116,58,32,86,101,114,116,73,110,41,32,45,62,32,86,101,114,116,79,117,116,10,123,10,9,108,101,116,32,111,117,116,112,117,116,58,32,86,101,114,116,79,117,116,59,10,9,111,117,116,112,117,116,46,117,118,32,61,32,105,110,112,117,116,46,117,118,59,10,9,111,117,116,112,117,116,46,112,111,115,105,116,105,111,110,32,61,32,118,105,101,119,101,114,68,97,116,97,46,112,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,32,42,32,118,105,101,119,101,114,68,97,116,97,46,118,105,101,119,77,97,116,114,105,120,32,42,32,105,110,115,116,97,110,99,101,68,97,116,97,46,119,111,114,108,100,77,97,116,114,105,120,32,42,32,118,101,99,52,60,102,51,50,62,40,105,110,112,117,116,46,112,111,115,44,32,49,46,48,41,59,10,10,9,114,101,116,117,114,110,32,111,117,116,112,117,116,59,10,125,10, \ No newline at end of file +111,112,116,105,111,110,32,72,65,83,95,68,73,70,70,85,83,69,95,84,69,88,84,85,82,69,58,32,98,111,111,108,59,10,111,112,116,105,111,110,32,72,65,83,95,65,76,80,72,65,95,84,69,88,84,85,82,69,58,32,98,111,111,108,59,10,111,112,116,105,111,110,32,65,76,80,72,65,95,84,69,83,84,58,32,98,111,111,108,59,10,10,99,111,110,115,116,32,72,97,115,85,86,32,61,32,72,65,83,95,68,73,70,70,85,83,69,95,84,69,88,84,85,82,69,32,124,124,32,72,65,83,95,65,76,80,72,65,95,84,69,88,84,85,82,69,59,10,10,91,108,97,121,111,117,116,40,115,116,100,49,52,48,41,93,10,115,116,114,117,99,116,32,66,97,115,105,99,83,101,116,116,105,110,103,115,10,123,10,9,65,108,112,104,97,84,104,114,101,115,104,111,108,100,58,32,102,51,50,44,10,9,68,105,102,102,117,115,101,67,111,108,111,114,58,32,118,101,99,52,60,102,51,50,62,10,125,10,10,91,108,97,121,111,117,116,40,115,116,100,49,52,48,41,93,10,115,116,114,117,99,116,32,73,110,115,116,97,110,99,101,68,97,116,97,10,123,10,9,119,111,114,108,100,77,97,116,114,105,120,58,32,109,97,116,52,60,102,51,50,62,44,10,9,105,110,118,87,111,114,108,100,77,97,116,114,105,120,58,32,109,97,116,52,60,102,51,50,62,10,125,10,10,91,108,97,121,111,117,116,40,115,116,100,49,52,48,41,93,10,115,116,114,117,99,116,32,86,105,101,119,101,114,68,97,116,97,10,123,10,9,112,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,58,32,109,97,116,52,60,102,51,50,62,44,10,9,105,110,118,80,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,58,32,109,97,116,52,60,102,51,50,62,44,10,9,118,105,101,119,77,97,116,114,105,120,58,32,109,97,116,52,60,102,51,50,62,44,10,9,105,110,118,86,105,101,119,77,97,116,114,105,120,58,32,109,97,116,52,60,102,51,50,62,44,10,9,118,105,101,119,80,114,111,106,77,97,116,114,105,120,58,32,109,97,116,52,60,102,51,50,62,44,10,9,105,110,118,86,105,101,119,80,114,111,106,77,97,116,114,105,120,58,32,109,97,116,52,60,102,51,50,62,44,10,9,114,101,110,100,101,114,84,97,114,103,101,116,83,105,122,101,58,32,118,101,99,50,60,102,51,50,62,44,10,9,105,110,118,82,101,110,100,101,114,84,97,114,103,101,116,83,105,122,101,58,32,118,101,99,50,60,102,51,50,62,44,10,9,101,121,101,80,111,115,105,116,105,111,110,58,32,118,101,99,51,60,102,51,50,62,10,125,10,10,101,120,116,101,114,110,97,108,10,123,10,9,91,115,101,116,40,48,41,44,32,98,105,110,100,105,110,103,40,48,41,93,32,118,105,101,119,101,114,68,97,116,97,58,32,117,110,105,102,111,114,109,60,86,105,101,119,101,114,68,97,116,97,62,44,10,9,91,115,101,116,40,49,41,44,32,98,105,110,100,105,110,103,40,48,41,93,32,105,110,115,116,97,110,99,101,68,97,116,97,58,32,117,110,105,102,111,114,109,60,73,110,115,116,97,110,99,101,68,97,116,97,62,44,10,9,91,115,101,116,40,50,41,44,32,98,105,110,100,105,110,103,40,48,41,93,32,115,101,116,116,105,110,103,115,58,32,117,110,105,102,111,114,109,60,66,97,115,105,99,83,101,116,116,105,110,103,115,62,44,10,9,91,115,101,116,40,50,41,44,32,98,105,110,100,105,110,103,40,50,41,93,32,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,58,32,115,97,109,112,108,101,114,50,68,60,102,51,50,62,44,10,9,91,115,101,116,40,50,41,44,32,98,105,110,100,105,110,103,40,49,41,93,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,58,32,115,97,109,112,108,101,114,50,68,60,102,51,50,62,10,125,10,10,47,47,32,70,114,97,103,109,101,110,116,32,115,116,97,103,101,10,115,116,114,117,99,116,32,70,114,97,103,73,110,10,123,10,9,91,108,111,99,97,116,105,111,110,40,48,41,44,32,99,111,110,100,40,72,97,115,85,86,41,93,32,117,118,58,32,118,101,99,50,60,102,51,50,62,10,125,10,10,115,116,114,117,99,116,32,70,114,97,103,79,117,116,10,123,10,9,91,108,111,99,97,116,105,111,110,40,48,41,93,32,82,101,110,100,101,114,84,97,114,103,101,116,48,58,32,118,101,99,52,60,102,51,50,62,10,125,10,10,91,101,110,116,114,121,40,102,114,97,103,41,93,10,102,110,32,109,97,105,110,40,105,110,112,117,116,58,32,70,114,97,103,73,110,41,32,45,62,32,70,114,97,103,79,117,116,10,123,10,9,108,101,116,32,111,117,116,112,117,116,58,32,70,114,97,103,79,117,116,59,10,9,108,101,116,32,100,105,102,102,117,115,101,67,111,108,111,114,32,61,32,115,101,108,101,99,116,95,111,112,116,40,72,65,83,95,68,73,70,70,85,83,69,95,84,69,88,84,85,82,69,44,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,46,83,97,109,112,108,101,40,105,110,112,117,116,46,117,118,41,32,42,32,115,101,116,116,105,110,103,115,46,68,105,102,102,117,115,101,67,111,108,111,114,44,32,115,101,116,116,105,110,103,115,46,68,105,102,102,117,115,101,67,111,108,111,114,41,59,10,9,108,101,116,32,100,105,102,102,117,115,101,67,111,108,111,114,32,61,32,115,101,108,101,99,116,95,111,112,116,40,72,65,83,95,65,76,80,72,65,95,84,69,88,84,85,82,69,44,32,118,101,99,52,60,102,51,50,62,40,100,105,102,102,117,115,101,67,111,108,111,114,46,120,44,32,100,105,102,102,117,115,101,67,111,108,111,114,46,121,44,32,100,105,102,102,117,115,101,67,111,108,111,114,46,122,44,32,40,40,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,46,83,97,109,112,108,101,40,105,110,112,117,116,46,117,118,41,41,46,120,41,32,42,32,100,105,102,102,117,115,101,67,111,108,111,114,46,119,41,44,32,100,105,102,102,117,115,101,67,111,108,111,114,41,59,10,10,9,105,102,32,40,115,101,108,101,99,116,95,111,112,116,40,65,76,80,72,65,95,84,69,83,84,44,32,100,105,102,102,117,115,101,67,111,108,111,114,46,119,32,60,32,115,101,116,116,105,110,103,115,46,65,108,112,104,97,84,104,114,101,115,104,111,108,100,44,32,102,97,108,115,101,41,41,10,9,9,100,105,115,99,97,114,100,59,10,10,9,111,117,116,112,117,116,46,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,100,105,102,102,117,115,101,67,111,108,111,114,59,10,9,114,101,116,117,114,110,32,111,117,116,112,117,116,59,10,125,10,10,47,47,32,86,101,114,116,101,120,32,115,116,97,103,101,10,115,116,114,117,99,116,32,86,101,114,116,73,110,10,123,10,9,91,108,111,99,97,116,105,111,110,40,48,41,93,32,112,111,115,58,32,118,101,99,51,60,102,51,50,62,44,10,9,91,108,111,99,97,116,105,111,110,40,49,41,44,32,99,111,110,100,40,72,97,115,85,86,41,93,32,117,118,58,32,118,101,99,50,60,102,51,50,62,10,125,10,10,115,116,114,117,99,116,32,86,101,114,116,79,117,116,10,123,10,9,91,108,111,99,97,116,105,111,110,40,48,41,44,32,99,111,110,100,40,72,97,115,85,86,41,93,32,117,118,58,32,118,101,99,50,60,102,51,50,62,44,10,9,91,98,117,105,108,116,105,110,40,112,111,115,105,116,105,111,110,41,93,32,112,111,115,105,116,105,111,110,58,32,118,101,99,52,60,102,51,50,62,10,125,10,10,91,101,110,116,114,121,40,118,101,114,116,41,93,10,102,110,32,109,97,105,110,40,105,110,112,117,116,58,32,86,101,114,116,73,110,41,32,45,62,32,86,101,114,116,79,117,116,10,123,10,9,108,101,116,32,111,117,116,112,117,116,58,32,86,101,114,116,79,117,116,59,10,9,111,117,116,112,117,116,46,112,111,115,105,116,105,111,110,32,61,32,118,105,101,119,101,114,68,97,116,97,46,112,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,32,42,32,118,105,101,119,101,114,68,97,116,97,46,118,105,101,119,77,97,116,114,105,120,32,42,32,105,110,115,116,97,110,99,101,68,97,116,97,46,119,111,114,108,100,77,97,116,114,105,120,32,42,32,118,101,99,52,60,102,51,50,62,40,105,110,112,117,116,46,112,111,115,44,32,49,46,48,41,59,10,10,9,99,111,110,115,116,32,105,102,32,40,72,97,115,85,86,41,10,9,9,111,117,116,112,117,116,46,117,118,32,61,32,105,110,112,117,116,46,117,118,59,10,10,9,114,101,116,117,114,110,32,111,117,116,112,117,116,59,10,125,10, \ No newline at end of file diff --git a/src/Nazara/Shader/Ast/AstCloner.cpp b/src/Nazara/Shader/Ast/AstCloner.cpp index f4a37efff..76c91d97e 100644 --- a/src/Nazara/Shader/Ast/AstCloner.cpp +++ b/src/Nazara/Shader/Ast/AstCloner.cpp @@ -40,6 +40,7 @@ namespace Nz::ShaderAst { auto clone = std::make_unique(); clone->condStatements.reserve(node.condStatements.size()); + clone->isConst = node.isConst; for (auto& cond : node.condStatements) { @@ -62,6 +63,17 @@ namespace Nz::ShaderAst return clone; } + StatementPtr AstCloner::Clone(DeclareConstStatement& node) + { + auto clone = std::make_unique(); + clone->constIndex = node.constIndex; + clone->name = node.name; + clone->type = node.type; + clone->expression = CloneExpression(node.expression); + + return clone; + } + StatementPtr AstCloner::Clone(DeclareExternalStatement& node) { auto clone = std::make_unique(); diff --git a/src/Nazara/Shader/Ast/AstOptimizer.cpp b/src/Nazara/Shader/Ast/AstOptimizer.cpp index 766090ba9..d1bcc0c76 100644 --- a/src/Nazara/Shader/Ast/AstOptimizer.cpp +++ b/src/Nazara/Shader/Ast/AstOptimizer.cpp @@ -844,7 +844,10 @@ namespace Nz::ShaderAst if (!m_options.constantQueryCallback) return AstCloner::Clone(node); - return ShaderBuilder::Constant(m_options.constantQueryCallback(node.constantId)); + auto constant = ShaderBuilder::Constant(m_options.constantQueryCallback(node.constantId)); + constant->cachedExpressionType = GetExpressionType(constant->value); + + return constant; } ExpressionPtr AstOptimizer::Clone(UnaryExpression& node) diff --git a/src/Nazara/Shader/Ast/AstRecursiveVisitor.cpp b/src/Nazara/Shader/Ast/AstRecursiveVisitor.cpp index 52d8fdc8d..355f03220 100644 --- a/src/Nazara/Shader/Ast/AstRecursiveVisitor.cpp +++ b/src/Nazara/Shader/Ast/AstRecursiveVisitor.cpp @@ -122,6 +122,12 @@ namespace Nz::ShaderAst node.statement->Visit(*this); } + void AstRecursiveVisitor::Visit(DeclareConstStatement& node) + { + if (node.expression) + node.expression->Visit(*this); + } + void AstRecursiveVisitor::Visit(DeclareExternalStatement& /*node*/) { /* Nothing to do */ diff --git a/src/Nazara/Shader/Ast/AstSerializer.cpp b/src/Nazara/Shader/Ast/AstSerializer.cpp index 0b5024415..bc426a133 100644 --- a/src/Nazara/Shader/Ast/AstSerializer.cpp +++ b/src/Nazara/Shader/Ast/AstSerializer.cpp @@ -208,6 +208,7 @@ namespace Nz::ShaderAst } Node(node.elseStatement); + Value(node.isConst); } void AstSerializerBase::Serialize(ConditionalStatement& node) @@ -232,6 +233,14 @@ namespace Nz::ShaderAst } } + void AstSerializerBase::Serialize(DeclareConstStatement& node) + { + OptVal(node.constIndex); + Value(node.name); + Type(node.type); + Node(node.expression); + } + void AstSerializerBase::Serialize(DeclareFunctionStatement& node) { Value(node.name); diff --git a/src/Nazara/Shader/Ast/SanitizeVisitor.cpp b/src/Nazara/Shader/Ast/SanitizeVisitor.cpp index 84a4d8ec4..4d548de10 100644 --- a/src/Nazara/Shader/Ast/SanitizeVisitor.cpp +++ b/src/Nazara/Shader/Ast/SanitizeVisitor.cpp @@ -577,6 +577,18 @@ namespace Nz::ShaderAst return clone; } + ExpressionPtr SanitizeVisitor::Clone(ConstantIndexExpression& node) + { + if (node.constantId >= m_context->constantValues.size()) + throw AstError{ "invalid constant index " + std::to_string(node.constantId) }; + + // Replace by constant value + auto constant = ShaderBuilder::Constant(m_context->constantValues[node.constantId]); + constant->cachedExpressionType = GetExpressionType(constant->value); + + return constant; + } + ExpressionPtr SanitizeVisitor::Clone(IdentifierExpression& node) { assert(m_context); @@ -712,11 +724,46 @@ namespace Nz::ShaderAst return clone; } + ExpressionPtr SanitizeVisitor::Clone(VariableExpression& node) + { + if (node.variableId >= m_context->variableTypes.size()) + throw AstError{ "invalid constant index " + std::to_string(node.variableId) }; + + node.cachedExpressionType = m_context->variableTypes[node.variableId]; + + return AstCloner::Clone(node); + } + StatementPtr SanitizeVisitor::Clone(BranchStatement& node) { + if (node.isConst) + { + // Evaluate every condition at compilation and select the right statement + for (auto& cond : node.condStatements) + { + MandatoryExpr(cond.condition); + + ConstantValue conditionValue = ComputeConstantValue(*AstCloner::Clone(*cond.condition)); + if (GetExpressionType(conditionValue) != ExpressionType{ PrimitiveType::Boolean }) + throw AstError{ "expected a boolean value" }; + + if (std::get(conditionValue)) + return AstCloner::Clone(*cond.statement); + } + + // Every condition failed, fallback to else if any + if (node.elseStatement) + return AstCloner::Clone(*node.elseStatement); + else + return ShaderBuilder::NoOp(); + } + auto clone = std::make_unique(); clone->condStatements.reserve(node.condStatements.size()); + if (!m_context->currentFunction) + throw AstError{ "non-const branching statements can only exist inside a function" }; + for (auto& cond : node.condStatements) { PushScope(); @@ -758,6 +805,31 @@ namespace Nz::ShaderAst return ShaderBuilder::NoOp(); } + StatementPtr SanitizeVisitor::Clone(DeclareConstStatement& node) + { + auto clone = static_unique_pointer_cast(AstCloner::Clone(node)); + + if (!clone->expression) + throw AstError{ "const variables must have an expression" }; + + clone->expression = Optimize(*clone->expression); + if (clone->expression->GetType() != NodeType::ConstantExpression) + throw AstError{ "const variable must have constant expressions " }; + + const ConstantValue& value = static_cast(*clone->expression).value; + + ExpressionType expressionType = ResolveType(GetExpressionType(value)); + + if (!IsNoType(clone->type) && ResolveType(clone->type) != expressionType) + throw AstError{ "constant expression doesn't match type" }; + + clone->type = expressionType; + + clone->constIndex = RegisterConstant(clone->name, value); + + return clone; + } + StatementPtr SanitizeVisitor::Clone(DeclareExternalStatement& node) { assert(m_context); @@ -815,6 +887,9 @@ namespace Nz::ShaderAst StatementPtr SanitizeVisitor::Clone(DeclareFunctionStatement& node) { + if (m_context->currentFunction) + throw AstError{ "a function cannot be defined inside another function" }; + auto clone = std::make_unique(); clone->name = node.name; clone->parameters = node.parameters; @@ -908,6 +983,9 @@ namespace Nz::ShaderAst StatementPtr SanitizeVisitor::Clone(DeclareOptionStatement& node) { + if (m_context->currentFunction) + throw AstError{ "options must be declared outside of functions" }; + auto clone = static_unique_pointer_cast(AstCloner::Clone(node)); clone->optType = ResolveType(clone->optType); @@ -926,6 +1004,9 @@ namespace Nz::ShaderAst StatementPtr SanitizeVisitor::Clone(DeclareStructStatement& node) { + if (m_context->currentFunction) + throw AstError{ "structs must be declared outside of functions" }; + auto clone = static_unique_pointer_cast(AstCloner::Clone(node)); std::unordered_set declaredMembers; @@ -961,6 +1042,9 @@ namespace Nz::ShaderAst StatementPtr SanitizeVisitor::Clone(DeclareVariableStatement& node) { + if (!m_context->currentFunction) + throw AstError{ "global variables outside of external blocks are forbidden" }; + auto clone = static_unique_pointer_cast(AstCloner::Clone(node)); if (IsNoType(clone->varType)) { @@ -1092,6 +1176,17 @@ namespace Nz::ShaderAst } ConstantValue SanitizeVisitor::ComputeConstantValue(Expression& expr) + { + // Run optimizer on constant value to hopefully retrieve a single constant value + ExpressionPtr optimizedExpr = Optimize(expr); + if (optimizedExpr->GetType() != NodeType::ConstantExpression) + throw AstError{"expected a constant expression"}; + + return static_cast(*optimizedExpr).value; + } + + template + std::unique_ptr SanitizeVisitor::Optimize(T& node) { AstOptimizer::Options optimizerOptions; optimizerOptions.constantQueryCallback = [this](std::size_t constantId) @@ -1103,11 +1198,7 @@ namespace Nz::ShaderAst optimizerOptions.enabledOptions = m_context->options.enabledOptions; // Run optimizer on constant value to hopefully retrieve a single constant value - ExpressionPtr optimizedExpr = Optimize(expr, optimizerOptions); - if (optimizedExpr->GetType() != NodeType::ConstantExpression) - throw AstError{"expected a constant expression"}; - - return static_cast(*optimizedExpr).value; + return static_unique_pointer_cast(ShaderAst::Optimize(node, optimizerOptions)); } std::size_t SanitizeVisitor::DeclareFunction(DeclareFunctionStatement& funcDecl) diff --git a/src/Nazara/Shader/GlslWriter.cpp b/src/Nazara/Shader/GlslWriter.cpp index 160c606c7..d098ce284 100644 --- a/src/Nazara/Shader/GlslWriter.cpp +++ b/src/Nazara/Shader/GlslWriter.cpp @@ -737,6 +737,8 @@ namespace Nz void GlslWriter::Visit(ShaderAst::BranchStatement& node) { + assert(!node.isConst); + bool first = true; for (const auto& statement : node.condStatements) { @@ -850,6 +852,11 @@ namespace Nz }, node.value); } + void GlslWriter::Visit(ShaderAst::DeclareConstStatement& /*node*/) + { + /* nothing to do */ + } + void GlslWriter::Visit(ShaderAst::DeclareExternalStatement& node) { assert(node.varIndex); @@ -1033,9 +1040,7 @@ namespace Nz assert(node.varIndex); RegisterVariable(*node.varIndex, node.varName); - Append(node.varType); - Append(" "); - Append(node.varName); + Append(node.varType, " ", node.varName); if (node.initialExpression) { Append(" = "); diff --git a/src/Nazara/Shader/LangWriter.cpp b/src/Nazara/Shader/LangWriter.cpp index d0fb77839..f4145f606 100644 --- a/src/Nazara/Shader/LangWriter.cpp +++ b/src/Nazara/Shader/LangWriter.cpp @@ -818,6 +818,10 @@ namespace Nz Append("min"); break; + case ShaderAst::IntrinsicType::Pow: + Append("pow"); + break; + case ShaderAst::IntrinsicType::SampleTexture: assert(!node.parameters.empty()); Visit(node.parameters.front(), true); diff --git a/src/Nazara/Shader/ShaderLangLexer.cpp b/src/Nazara/Shader/ShaderLangLexer.cpp index 2aed4846e..049d02ba9 100644 --- a/src/Nazara/Shader/ShaderLangLexer.cpp +++ b/src/Nazara/Shader/ShaderLangLexer.cpp @@ -40,6 +40,7 @@ namespace Nz::ShaderLang ForceCLocale forceCLocale; std::unordered_map reservedKeywords = { + { "const", TokenType::Const }, { "discard", TokenType::Discard }, { "else", TokenType::Else }, { "external", TokenType::External }, diff --git a/src/Nazara/Shader/ShaderLangParser.cpp b/src/Nazara/Shader/ShaderLangParser.cpp index 4a5cba701..c12ac590c 100644 --- a/src/Nazara/Shader/ShaderLangParser.cpp +++ b/src/Nazara/Shader/ShaderLangParser.cpp @@ -118,6 +118,13 @@ namespace Nz::ShaderLang const Token& nextToken = Peek(); switch (nextToken.type) { + case TokenType::Const: + if (!attributes.empty()) + throw UnexpectedToken{}; + + context.root->statements.push_back(ParseConstStatement()); + break; + case TokenType::EndOfStream: if (!attributes.empty()) throw UnexpectedToken{}; @@ -400,6 +407,28 @@ namespace Nz::ShaderLang return attributes; } + void Parser::ParseVariableDeclaration(std::string& name, ShaderAst::ExpressionType& type, ShaderAst::ExpressionPtr& initialValue) + { + name = ParseIdentifierAsName(); + + if (Peek().type == TokenType::Colon) + { + Expect(Advance(), TokenType::Colon); + + type = ParseType(); + } + else + type = ShaderAst::NoType{}; + + if (IsNoType(type) || Peek().type == TokenType::Assign) + { + Expect(Advance(), TokenType::Assign); + initialValue = ParseExpression(); + } + + Expect(Advance(), TokenType::Semicolon); + } + ShaderAst::StatementPtr Parser::ParseBranchStatement() { std::unique_ptr branch = std::make_unique(); @@ -434,9 +463,41 @@ namespace Nz::ShaderLang return branch; } + ShaderAst::StatementPtr Parser::ParseConstStatement() + { + Expect(Advance(), TokenType::Const); + + switch (Peek().type) + { + case TokenType::Identifier: + { + std::string constName; + ShaderAst::ExpressionType constType; + ShaderAst::ExpressionPtr initialValue; + + ParseVariableDeclaration(constName, constType, initialValue); + RegisterVariable(constName); + + return ShaderBuilder::DeclareConst(std::move(constName), std::move(constType), std::move(initialValue)); + } + + case TokenType::If: + { + auto branch = ParseBranchStatement(); + static_cast(*branch).isConst = true; + + return branch; + } + + default: + throw UnexpectedToken{}; + } + } + ShaderAst::StatementPtr Parser::ParseDiscardStatement() { Expect(Advance(), TokenType::Discard); + Expect(Advance(), TokenType::Semicolon); return ShaderBuilder::Discard(); } @@ -728,6 +789,8 @@ namespace Nz::ShaderLang if (Peek().type != TokenType::Semicolon) expr = ParseExpression(); + Expect(Advance(), TokenType::Semicolon); + return ShaderBuilder::Return(std::move(expr)); } @@ -738,14 +801,16 @@ namespace Nz::ShaderLang ShaderAst::StatementPtr statement; switch (token.type) { + case TokenType::Const: + statement = ParseConstStatement(); + break; + case TokenType::Discard: statement = ParseDiscardStatement(); - Expect(Advance(), TokenType::Semicolon); break; case TokenType::Let: statement = ParseVariableDeclaration(); - Expect(Advance(), TokenType::Semicolon); break; case TokenType::Identifier: @@ -759,7 +824,6 @@ namespace Nz::ShaderLang case TokenType::Return: statement = ParseReturnStatement(); - Expect(Advance(), TokenType::Semicolon); break; default: @@ -809,23 +873,12 @@ namespace Nz::ShaderLang { Expect(Advance(), TokenType::Let); - std::string variableName = ParseIdentifierAsName(); - RegisterVariable(variableName); - - ShaderAst::ExpressionType variableType = ShaderAst::NoType{}; - if (Peek().type == TokenType::Colon) - { - Expect(Advance(), TokenType::Colon); - - variableType = ParseType(); - } - + std::string variableName; + ShaderAst::ExpressionType variableType; ShaderAst::ExpressionPtr expression; - if (IsNoType(variableType) || Peek().type == TokenType::Assign) - { - Expect(Advance(), TokenType::Assign); - expression = ParseExpression(); - } + + ParseVariableDeclaration(variableName, variableType, expression); + RegisterVariable(variableName); return ShaderBuilder::DeclareVariable(std::move(variableName), std::move(variableType), std::move(expression)); } diff --git a/src/Nazara/Shader/SpirvAstVisitor.cpp b/src/Nazara/Shader/SpirvAstVisitor.cpp index d3aea9f3c..af9eb5873 100644 --- a/src/Nazara/Shader/SpirvAstVisitor.cpp +++ b/src/Nazara/Shader/SpirvAstVisitor.cpp @@ -584,6 +584,11 @@ namespace Nz }, node.value); } + void SpirvAstVisitor::Visit(ShaderAst::DeclareConstStatement& /*node*/) + { + /* nothing to do */ + } + void SpirvAstVisitor::Visit(ShaderAst::DeclareExternalStatement& node) { assert(node.varIndex); diff --git a/src/Nazara/Shader/SpirvWriter.cpp b/src/Nazara/Shader/SpirvWriter.cpp index 49fb35d7e..e25a11d37 100644 --- a/src/Nazara/Shader/SpirvWriter.cpp +++ b/src/Nazara/Shader/SpirvWriter.cpp @@ -86,6 +86,23 @@ namespace Nz m_constantCache.Register(*m_constantCache.BuildType(node.cachedExpressionType.value())); } + void Visit(ShaderAst::CallFunctionExpression& node) override + { + AstRecursiveVisitor::Visit(node); + + assert(m_funcIndex); + auto& func = m_funcs[*m_funcIndex]; + + auto& funcCall = func.funcCalls.emplace_back(); + funcCall.firstVarIndex = func.variables.size(); + + for (const auto& parameter : node.parameters) + { + auto& var = func.variables.emplace_back(); + var.typeId = m_constantCache.Register(*m_constantCache.BuildPointerType(GetExpressionType(*parameter), SpirvStorageClass::Function)); + } + } + void Visit(ShaderAst::ConditionalExpression& node) override { throw std::runtime_error("unexpected conditional expression, did you forget to sanitize the shader?"); @@ -126,23 +143,6 @@ namespace Nz } } - void Visit(ShaderAst::CallFunctionExpression& node) override - { - AstRecursiveVisitor::Visit(node); - - assert(m_funcIndex); - auto& func = m_funcs[*m_funcIndex]; - - auto& funcCall = func.funcCalls.emplace_back(); - funcCall.firstVarIndex = func.variables.size(); - - for (const auto& parameter : node.parameters) - { - auto& var = func.variables.emplace_back(); - var.typeId = m_constantCache.Register(*m_constantCache.BuildPointerType(GetExpressionType(*parameter), SpirvStorageClass::Function)); - } - } - void Visit(ShaderAst::DeclareFunctionStatement& node) override { std::optional entryPointType; diff --git a/src/ShaderNode/Widgets/CodeOutputWidget.cpp b/src/ShaderNode/Widgets/CodeOutputWidget.cpp index cf33d1945..0cea614ab 100644 --- a/src/ShaderNode/Widgets/CodeOutputWidget.cpp +++ b/src/ShaderNode/Widgets/CodeOutputWidget.cpp @@ -68,8 +68,11 @@ void CodeOutputWidget::Refresh() { shaderAst = Nz::ShaderAst::Sanitize(*shaderAst); + Nz::ShaderAst::AstOptimizer::Options optimOptions; + optimOptions.enabledOptions = enabledConditions; + Nz::ShaderAst::AstOptimizer optimiser; - shaderAst = optimiser.Optimise(*shaderAst, enabledConditions); + shaderAst = optimiser.Optimise(*shaderAst, optimOptions); } Nz::ShaderWriter::States states; diff --git a/tests/Engine/Shader/AccessMemberTest.cpp b/tests/Engine/Shader/AccessMemberTest.cpp index bdb40fff9..a3127e98d 100644 --- a/tests/Engine/Shader/AccessMemberTest.cpp +++ b/tests/Engine/Shader/AccessMemberTest.cpp @@ -63,12 +63,12 @@ SCENARIO("Shader generation", "[Shader]") statements.push_back(Nz::ShaderBuilder::DeclareStruct(std::move(outerStruct))); auto external = std::make_unique(); - external->externalVars.push_back({ - 0, - std::nullopt, - "ubo", - Nz::ShaderAst::UniformType{ Nz::ShaderAst::IdentifierType{ "outerStruct" } } - }); + + auto& externalVar = external->externalVars.emplace_back(); + externalVar.bindingIndex = 0; + externalVar.name = "ubo"; + externalVar.type = Nz::ShaderAst::UniformType{ Nz::ShaderAst::IdentifierType{ "outerStruct" } }; + statements.push_back(std::move(external)); SECTION("Nested AccessMember")