diff --git a/examples/RenderTest/main.cpp b/examples/RenderTest/main.cpp index b3b19ebcc..c076d8c3f 100644 --- a/examples/RenderTest/main.cpp +++ b/examples/RenderTest/main.cpp @@ -9,6 +9,9 @@ #include const char shaderSource[] = R"( + +option red: bool; + [layout(std140)] struct Data { @@ -49,7 +52,7 @@ fn main(fragIn: VertOut) -> FragOut let lightFactor = dot(fragIn.normal, lightDir); let fragOut: FragOut; - fragOut.color = lightFactor * tex.Sample(fragIn.uv); + fragOut.color = lightFactor * tex.Sample(fragIn.uv) * select_opt(red, vec4(1.0, 0.0, 0.0, 1.0), vec4(1.0, 1.0, 1.0, 1.0)); return fragOut; } @@ -92,7 +95,10 @@ int main() std::shared_ptr device = window.GetRenderDevice(); - auto fragVertShader = device->InstantiateShaderModule(Nz::ShaderStageType::Fragment | Nz::ShaderStageType::Vertex, Nz::ShaderLanguage::NazaraShader, shaderSource, sizeof(shaderSource)); + Nz::ShaderWriter::States states; + states.enabledOptions = 0; + + auto fragVertShader = device->InstantiateShaderModule(Nz::ShaderStageType::Fragment | Nz::ShaderStageType::Vertex, Nz::ShaderLanguage::NazaraShader, shaderSource, sizeof(shaderSource), states); if (!fragVertShader) { std::cout << "Failed to instantiate shader" << std::endl; diff --git a/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp b/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp index 2597b3f91..b897ef728 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp @@ -39,7 +39,7 @@ namespace Nz std::shared_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override; std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override; std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states) override; - std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize) override; + std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states) override; std::shared_ptr InstantiateTexture(const TextureInfo& params) override; std::shared_ptr InstantiateTextureSampler(const TextureSamplerInfo& params) override; diff --git a/include/Nazara/OpenGLRenderer/OpenGLShaderModule.hpp b/include/Nazara/OpenGLRenderer/OpenGLShaderModule.hpp index 6e0426702..c93f2e277 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLShaderModule.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLShaderModule.hpp @@ -21,7 +21,7 @@ namespace Nz { public: OpenGLShaderModule(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states); - OpenGLShaderModule(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize); + OpenGLShaderModule(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states); OpenGLShaderModule(const OpenGLShaderModule&) = delete; OpenGLShaderModule(OpenGLShaderModule&&) noexcept = default; ~OpenGLShaderModule() = default; diff --git a/include/Nazara/Renderer/RenderDevice.hpp b/include/Nazara/Renderer/RenderDevice.hpp index fd2531794..8132eb118 100644 --- a/include/Nazara/Renderer/RenderDevice.hpp +++ b/include/Nazara/Renderer/RenderDevice.hpp @@ -40,8 +40,8 @@ namespace Nz virtual std::shared_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) = 0; virtual std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) = 0; virtual std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states) = 0; - virtual std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize) = 0; - std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const std::filesystem::path& sourcePath); + virtual std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states) = 0; + std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const std::filesystem::path& sourcePath, const ShaderWriter::States& states); virtual std::shared_ptr InstantiateTexture(const TextureInfo& params) = 0; virtual std::shared_ptr InstantiateTextureSampler(const TextureSamplerInfo& params) = 0; }; diff --git a/include/Nazara/Shader/Ast/AstCloner.hpp b/include/Nazara/Shader/Ast/AstCloner.hpp index 6feedc689..35bd3b6ed 100644 --- a/include/Nazara/Shader/Ast/AstCloner.hpp +++ b/include/Nazara/Shader/Ast/AstCloner.hpp @@ -45,6 +45,7 @@ namespace Nz::ShaderAst virtual ExpressionPtr Clone(ConstantExpression& node); virtual ExpressionPtr Clone(IdentifierExpression& node); virtual ExpressionPtr Clone(IntrinsicExpression& node); + virtual ExpressionPtr Clone(SelectOptionExpression& node); virtual ExpressionPtr Clone(SwizzleExpression& node); virtual ExpressionPtr Clone(VariableExpression& node); @@ -52,6 +53,7 @@ namespace Nz::ShaderAst virtual StatementPtr Clone(ConditionalStatement& node); virtual StatementPtr Clone(DeclareExternalStatement& node); virtual StatementPtr Clone(DeclareFunctionStatement& node); + virtual StatementPtr Clone(DeclareOptionStatement& node); virtual StatementPtr Clone(DeclareStructStatement& node); virtual StatementPtr Clone(DeclareVariableStatement& node); virtual StatementPtr Clone(DiscardStatement& node); diff --git a/include/Nazara/Shader/Ast/AstNodeList.hpp b/include/Nazara/Shader/Ast/AstNodeList.hpp index 0bd48175c..f16cdd9b5 100644 --- a/include/Nazara/Shader/Ast/AstNodeList.hpp +++ b/include/Nazara/Shader/Ast/AstNodeList.hpp @@ -35,12 +35,14 @@ NAZARA_SHADERAST_EXPRESSION(ConditionalExpression) NAZARA_SHADERAST_EXPRESSION(ConstantExpression) NAZARA_SHADERAST_EXPRESSION(IdentifierExpression) NAZARA_SHADERAST_EXPRESSION(IntrinsicExpression) +NAZARA_SHADERAST_EXPRESSION(SelectOptionExpression) NAZARA_SHADERAST_EXPRESSION(SwizzleExpression) NAZARA_SHADERAST_EXPRESSION(VariableExpression) NAZARA_SHADERAST_STATEMENT(BranchStatement) NAZARA_SHADERAST_STATEMENT(ConditionalStatement) NAZARA_SHADERAST_STATEMENT(DeclareExternalStatement) NAZARA_SHADERAST_STATEMENT(DeclareFunctionStatement) +NAZARA_SHADERAST_STATEMENT(DeclareOptionStatement) NAZARA_SHADERAST_STATEMENT(DeclareStructStatement) NAZARA_SHADERAST_STATEMENT(DeclareVariableStatement) NAZARA_SHADERAST_STATEMENT(DiscardStatement) diff --git a/include/Nazara/Shader/Ast/AstOptimizer.hpp b/include/Nazara/Shader/Ast/AstOptimizer.hpp index 354fe86ba..c52e41ad9 100644 --- a/include/Nazara/Shader/Ast/AstOptimizer.hpp +++ b/include/Nazara/Shader/Ast/AstOptimizer.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include namespace Nz::ShaderAst @@ -29,16 +30,15 @@ namespace Nz::ShaderAst AstOptimizer& operator=(AstOptimizer&&) = delete; protected: - using AstCloner::Visit; - void Visit(BinaryExpression& node) override; - void Visit(ConditionalExpression& node) override; - void Visit(BranchStatement& node) override; - void Visit(ConditionalStatement& node) override; + ExpressionPtr Clone(BinaryExpression& node) override; + ExpressionPtr Clone(ConditionalExpression& node) override; + StatementPtr Clone(BranchStatement& node) override; + StatementPtr Clone(ConditionalStatement& node) override; - template void PropagateConstant(std::unique_ptr&& lhs, std::unique_ptr&& rhs); + template ExpressionPtr PropagateConstant(std::unique_ptr&& lhs, std::unique_ptr&& rhs); private: - UInt64 m_enabledConditions; + std::optional m_enabledOptions; }; } diff --git a/include/Nazara/Shader/Ast/AstRecursiveVisitor.hpp b/include/Nazara/Shader/Ast/AstRecursiveVisitor.hpp index d131931d6..ea605ff6a 100644 --- a/include/Nazara/Shader/Ast/AstRecursiveVisitor.hpp +++ b/include/Nazara/Shader/Ast/AstRecursiveVisitor.hpp @@ -29,6 +29,7 @@ namespace Nz::ShaderAst void Visit(ConstantExpression& node) override; void Visit(IdentifierExpression& node) override; void Visit(IntrinsicExpression& node) override; + void Visit(SelectOptionExpression& node) override; void Visit(SwizzleExpression& node) override; void Visit(VariableExpression& node) override; @@ -36,6 +37,7 @@ namespace Nz::ShaderAst void Visit(ConditionalStatement& node) override; void Visit(DeclareExternalStatement& node) override; void Visit(DeclareFunctionStatement& node) override; + void Visit(DeclareOptionStatement& node) override; void Visit(DeclareStructStatement& node) override; void Visit(DeclareVariableStatement& node) override; void Visit(DiscardStatement& node) override; diff --git a/include/Nazara/Shader/Ast/AstSerializer.hpp b/include/Nazara/Shader/Ast/AstSerializer.hpp index 8b726d19d..193f2f971 100644 --- a/include/Nazara/Shader/Ast/AstSerializer.hpp +++ b/include/Nazara/Shader/Ast/AstSerializer.hpp @@ -32,6 +32,7 @@ namespace Nz::ShaderAst void Serialize(ConstantExpression& node); void Serialize(IdentifierExpression& node); void Serialize(IntrinsicExpression& node); + void Serialize(SelectOptionExpression& node); void Serialize(SwizzleExpression& node); void Serialize(VariableExpression& node); @@ -39,6 +40,7 @@ namespace Nz::ShaderAst void Serialize(ConditionalStatement& node); void Serialize(DeclareExternalStatement& node); void Serialize(DeclareFunctionStatement& node); + void Serialize(DeclareOptionStatement& node); void Serialize(DeclareStructStatement& node); void Serialize(DeclareVariableStatement& node); void Serialize(DiscardStatement& node); diff --git a/include/Nazara/Shader/Ast/AstUtils.hpp b/include/Nazara/Shader/Ast/AstUtils.hpp index d27c41d49..42d7254ab 100644 --- a/include/Nazara/Shader/Ast/AstUtils.hpp +++ b/include/Nazara/Shader/Ast/AstUtils.hpp @@ -40,6 +40,7 @@ namespace Nz::ShaderAst void Visit(ConstantExpression& node) override; void Visit(IdentifierExpression& node) override; void Visit(IntrinsicExpression& node) override; + void Visit(SelectOptionExpression& node) override; void Visit(SwizzleExpression& node) override; void Visit(VariableExpression& node) override; diff --git a/include/Nazara/Shader/Ast/Enums.hpp b/include/Nazara/Shader/Ast/Enums.hpp index 21b1e91a0..90d229000 100644 --- a/include/Nazara/Shader/Ast/Enums.hpp +++ b/include/Nazara/Shader/Ast/Enums.hpp @@ -22,7 +22,8 @@ namespace Nz::ShaderAst Builtin, //< Builtin (struct member only) - has argument type Entry, //< Entry point (function only) - has argument type Layout, //< Struct layout (struct only) - has argument style - Location //< Location (struct member only) - has argument index + Location, //< Location (struct member only) - has argument index + Option, //< Conditional compilation option - has argument expr }; enum class BinaryType diff --git a/include/Nazara/Shader/Ast/Nodes.hpp b/include/Nazara/Shader/Ast/Nodes.hpp index 0d9f67067..8ac4942b3 100644 --- a/include/Nazara/Shader/Ast/Nodes.hpp +++ b/include/Nazara/Shader/Ast/Nodes.hpp @@ -116,7 +116,7 @@ namespace Nz::ShaderAst NodeType GetType() const override; void Visit(AstExpressionVisitor& visitor) override; - std::string conditionName; + std::size_t optionIndex; ExpressionPtr falsePath; ExpressionPtr truePath; }; @@ -146,6 +146,16 @@ namespace Nz::ShaderAst std::vector parameters; }; + struct NAZARA_SHADER_API SelectOptionExpression : public Expression + { + NodeType GetType() const override; + void Visit(AstExpressionVisitor& visitor) override; + + std::string optionName; + ExpressionPtr falsePath; + ExpressionPtr truePath; + }; + struct NAZARA_SHADER_API SwizzleExpression : public Expression { NodeType GetType() const override; @@ -203,7 +213,7 @@ namespace Nz::ShaderAst NodeType GetType() const override; void Visit(AstStatementVisitor& visitor) override; - std::string conditionName; + std::size_t optionIndex; StatementPtr statement; }; @@ -237,12 +247,24 @@ namespace Nz::ShaderAst std::optional entryStage; std::optional funcIndex; std::optional varIndex; + std::string optionName; std::string name; std::vector parameters; std::vector statements; ExpressionType returnType; }; + struct NAZARA_SHADER_API DeclareOptionStatement : Statement + { + NodeType GetType() const override; + void Visit(AstStatementVisitor& visitor) override; + + std::optional optIndex; + std::string optName; + ExpressionPtr initialValue; + ExpressionType optType; + }; + struct NAZARA_SHADER_API DeclareStructStatement : Statement { NodeType GetType() const override; diff --git a/include/Nazara/Shader/Ast/SanitizeVisitor.hpp b/include/Nazara/Shader/Ast/SanitizeVisitor.hpp index e3e541ba5..8016e13d7 100644 --- a/include/Nazara/Shader/Ast/SanitizeVisitor.hpp +++ b/include/Nazara/Shader/Ast/SanitizeVisitor.hpp @@ -17,16 +17,24 @@ namespace Nz::ShaderAst class NAZARA_SHADER_API SanitizeVisitor final : AstCloner { public: + struct Options; + inline SanitizeVisitor(); SanitizeVisitor(const SanitizeVisitor&) = delete; SanitizeVisitor(SanitizeVisitor&&) = delete; ~SanitizeVisitor() = default; - StatementPtr Sanitize(StatementPtr& statement, std::string* error = nullptr); + inline StatementPtr Sanitize(StatementPtr& statement, std::string* error = nullptr); + StatementPtr Sanitize(StatementPtr& statement, const Options& options, std::string* error = nullptr); SanitizeVisitor& operator=(const SanitizeVisitor&) = delete; SanitizeVisitor& operator=(SanitizeVisitor&&) = delete; + struct Options + { + bool removeOptionDeclaration = true; + }; + private: struct Identifier; @@ -42,12 +50,14 @@ namespace Nz::ShaderAst ExpressionPtr Clone(ConstantExpression& node) override; ExpressionPtr Clone(IdentifierExpression& node) override; ExpressionPtr Clone(IntrinsicExpression& node) override; + ExpressionPtr Clone(SelectOptionExpression& node) override; ExpressionPtr Clone(SwizzleExpression& node) override; StatementPtr Clone(BranchStatement& node) override; StatementPtr Clone(ConditionalStatement& node) override; StatementPtr Clone(DeclareExternalStatement& node) override; StatementPtr Clone(DeclareFunctionStatement& node) override; + StatementPtr Clone(DeclareOptionStatement& node) override; StatementPtr Clone(DeclareStructStatement& node) override; StatementPtr Clone(DeclareVariableStatement& node) override; StatementPtr Clone(ExpressionStatement& node) override; @@ -64,6 +74,7 @@ namespace Nz::ShaderAst void PopScope(); inline std::size_t RegisterFunction(std::string name); + inline std::size_t RegisterOption(std::string name, ExpressionType type); inline std::size_t RegisterStruct(std::string name, StructDescription description); inline std::size_t RegisterVariable(std::string name, ExpressionType type); @@ -78,6 +89,11 @@ namespace Nz::ShaderAst std::variant value; }; + struct Option + { + std::size_t optionIndex; + }; + struct Struct { std::size_t structIndex; @@ -91,11 +107,12 @@ namespace Nz::ShaderAst struct Identifier { std::string name; - std::variant value; + std::variant value; }; std::size_t m_nextFuncIndex; std::vector m_identifiersInScope; + std::vector m_options; std::vector m_structs; std::vector m_variables; std::vector m_scopeSizes; @@ -105,6 +122,7 @@ namespace Nz::ShaderAst }; inline StatementPtr Sanitize(StatementPtr& ast, std::string* error = nullptr); + inline StatementPtr Sanitize(StatementPtr& ast, const SanitizeVisitor::Options& options, std::string* error = nullptr); } #include diff --git a/include/Nazara/Shader/Ast/SanitizeVisitor.inl b/include/Nazara/Shader/Ast/SanitizeVisitor.inl index 29a902b8a..5c1c32f93 100644 --- a/include/Nazara/Shader/Ast/SanitizeVisitor.inl +++ b/include/Nazara/Shader/Ast/SanitizeVisitor.inl @@ -12,6 +12,11 @@ namespace Nz::ShaderAst { } + inline StatementPtr SanitizeVisitor::Sanitize(StatementPtr& statement, std::string* error) + { + return Sanitize(statement, {}, error); + } + inline auto SanitizeVisitor::FindIdentifier(const std::string_view& identifierName) const -> const Identifier* { auto it = std::find_if(m_identifiersInScope.rbegin(), m_identifiersInScope.rend(), [&](const Identifier& identifier) { return identifier.name == identifierName; }); @@ -23,10 +28,23 @@ namespace Nz::ShaderAst inline std::size_t SanitizeVisitor::RegisterFunction(std::string name) { - std::size_t funcIndex = m_nextFuncIndex++; - return funcIndex; + return m_nextFuncIndex++; } + inline std::size_t SanitizeVisitor::RegisterOption(std::string name, ExpressionType type) + { + std::size_t optionIndex = m_options.size(); + m_options.emplace_back(std::move(type)); + + m_identifiersInScope.push_back({ + std::move(name), + Option { + optionIndex + } + }); + + return optionIndex; + } inline std::size_t SanitizeVisitor::RegisterStruct(std::string name, StructDescription description) { @@ -63,6 +81,12 @@ namespace Nz::ShaderAst SanitizeVisitor sanitizer; return sanitizer.Sanitize(ast, error); } + + StatementPtr Sanitize(StatementPtr& ast, const SanitizeVisitor::Options& options, std::string* error) + { + SanitizeVisitor sanitizer; + return sanitizer.Sanitize(ast, options, error); + } } #include diff --git a/include/Nazara/Shader/GlslWriter.hpp b/include/Nazara/Shader/GlslWriter.hpp index a0530230c..582af602a 100644 --- a/include/Nazara/Shader/GlslWriter.hpp +++ b/include/Nazara/Shader/GlslWriter.hpp @@ -29,8 +29,8 @@ namespace Nz GlslWriter(GlslWriter&&) = delete; ~GlslWriter() = default; - inline std::string Generate(ShaderAst::StatementPtr& shader, const States& conditions = {}); - std::string Generate(std::optional shaderStage, ShaderAst::StatementPtr& shader, const States& conditions = {}); + inline std::string Generate(ShaderAst::StatementPtr& shader, const States& states = {}); + std::string Generate(std::optional shaderStage, ShaderAst::StatementPtr& shader, const States& states = {}); void SetEnv(Environment environment); @@ -60,7 +60,6 @@ namespace Nz template void Append(const T& param); template void Append(const T1& firstParam, const T2& secondParam, Args&&... params); void AppendCommentSection(const std::string& section); - void AppendEntryPoint(ShaderStageType shaderStage, ShaderAst::StatementPtr& shader); void AppendField(std::size_t structIndex, const std::size_t* memberIndices, std::size_t remainingMembers); void AppendHeader(); void AppendLine(const std::string& txt = {}); diff --git a/include/Nazara/Shader/GlslWriter.inl b/include/Nazara/Shader/GlslWriter.inl index e8c4d052c..dc736e182 100644 --- a/include/Nazara/Shader/GlslWriter.inl +++ b/include/Nazara/Shader/GlslWriter.inl @@ -12,9 +12,9 @@ namespace Nz { } - inline std::string GlslWriter::Generate(ShaderAst::StatementPtr& shader, const States& conditions) + inline std::string GlslWriter::Generate(ShaderAst::StatementPtr& shader, const States& states) { - return Generate(std::nullopt, shader, conditions); + return Generate(std::nullopt, shader, states); } } diff --git a/include/Nazara/Shader/LangWriter.hpp b/include/Nazara/Shader/LangWriter.hpp new file mode 100644 index 000000000..2a111f47b --- /dev/null +++ b/include/Nazara/Shader/LangWriter.hpp @@ -0,0 +1,111 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_LANGWRITER_HPP +#define NAZARA_LANGWRITER_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class NAZARA_SHADER_API LangWriter : public ShaderWriter, public ShaderAst::ExpressionVisitorExcept, public ShaderAst::StatementVisitorExcept + { + public: + struct Environment; + + inline LangWriter(); + LangWriter(const LangWriter&) = delete; + LangWriter(LangWriter&&) = delete; + ~LangWriter() = default; + + std::string Generate(ShaderAst::StatementPtr& shader, const States& conditions = {}); + + void SetEnv(Environment environment); + + struct Environment + { + }; + + private: + struct BindingAttribute; + struct BuiltinAttribute; + struct EntryAttribute; + struct LayoutAttribute; + struct LocationAttribute; + + void Append(const ShaderAst::ExpressionType& type); + void Append(const ShaderAst::IdentifierType& identifierType); + void Append(const ShaderAst::MatrixType& matrixType); + void Append(ShaderAst::NoType); + void Append(ShaderAst::PrimitiveType type); + void Append(const ShaderAst::SamplerType& samplerType); + void Append(const ShaderAst::StructType& structType); + void Append(const ShaderAst::UniformType& uniformType); + void Append(const ShaderAst::VectorType& vecType); + template void Append(const T& param); + template void Append(const T1& firstParam, const T2& secondParam, Args&&... params); + template void AppendAttributes(bool appendLine, Args&&... params); + void AppendAttribute(BindingAttribute builtin); + void AppendAttribute(BuiltinAttribute builtin); + void AppendAttribute(EntryAttribute entry); + void AppendAttribute(LayoutAttribute layout); + void AppendAttribute(LocationAttribute location); + void AppendCommentSection(const std::string& section); + void AppendField(std::size_t structIndex, const std::size_t* memberIndices, std::size_t remainingMembers); + void AppendHeader(); + void AppendLine(const std::string& txt = {}); + template void AppendLine(Args&&... params); + void AppendStatementList(std::vector& statements); + + void EnterScope(); + void LeaveScope(bool skipLine = true); + + void RegisterOption(std::size_t optionIndex, std::string optionName); + void RegisterStruct(std::size_t structIndex, ShaderAst::StructDescription desc); + void RegisterVariable(std::size_t varIndex, std::string varName); + + void Visit(ShaderAst::ExpressionPtr& expr, bool encloseIfRequired = false); + + void Visit(ShaderAst::AccessMemberIndexExpression& node) override; + void Visit(ShaderAst::AssignExpression& node) override; + void Visit(ShaderAst::BinaryExpression& node) override; + void Visit(ShaderAst::CastExpression& node) override; + void Visit(ShaderAst::ConditionalExpression& node) override; + void Visit(ShaderAst::ConstantExpression& node) override; + void Visit(ShaderAst::IntrinsicExpression& node) override; + void Visit(ShaderAst::SwizzleExpression& node) override; + void Visit(ShaderAst::VariableExpression& node) override; + + void Visit(ShaderAst::BranchStatement& node) override; + void Visit(ShaderAst::ConditionalStatement& node) override; + void Visit(ShaderAst::DeclareExternalStatement& node) override; + void Visit(ShaderAst::DeclareFunctionStatement& node) override; + void Visit(ShaderAst::DeclareOptionStatement& node) override; + void Visit(ShaderAst::DeclareStructStatement& node) override; + void Visit(ShaderAst::DeclareVariableStatement& node) override; + void Visit(ShaderAst::DiscardStatement& node) override; + void Visit(ShaderAst::ExpressionStatement& node) override; + void Visit(ShaderAst::MultiStatement& node) override; + void Visit(ShaderAst::NoOpStatement& node) override; + void Visit(ShaderAst::ReturnStatement& node) override; + + struct State; + + Environment m_environment; + State* m_currentState; + }; +} + +#include + +#endif diff --git a/include/Nazara/Shader/LangWriter.inl b/include/Nazara/Shader/LangWriter.inl new file mode 100644 index 000000000..adc74afe4 --- /dev/null +++ b/include/Nazara/Shader/LangWriter.inl @@ -0,0 +1,16 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - Shader generator" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + inline LangWriter::LangWriter() : + m_currentState(nullptr) + { + } +} + +#include diff --git a/include/Nazara/Shader/ShaderBuilder.hpp b/include/Nazara/Shader/ShaderBuilder.hpp index 0d5e44021..434e05cfe 100644 --- a/include/Nazara/Shader/ShaderBuilder.hpp +++ b/include/Nazara/Shader/ShaderBuilder.hpp @@ -44,12 +44,12 @@ namespace Nz::ShaderBuilder struct ConditionalExpression { - inline std::unique_ptr operator()(std::string conditionName, ShaderAst::ExpressionPtr truePath, ShaderAst::ExpressionPtr falsePath) const; + inline std::unique_ptr operator()(std::size_t optionIndex, ShaderAst::ExpressionPtr truePath, ShaderAst::ExpressionPtr falsePath) const; }; struct ConditionalStatement { - inline std::unique_ptr operator()(std::string conditionName, ShaderAst::StatementPtr statement) const; + inline std::unique_ptr operator()(std::size_t optionIndex, ShaderAst::StatementPtr statement) const; }; struct Constant @@ -64,6 +64,11 @@ namespace Nz::ShaderBuilder inline std::unique_ptr operator()(std::optional entryStage, std::string name, std::vector parameters, std::vector statements, ShaderAst::ExpressionType returnType = ShaderAst::NoType{}) const; }; + struct DeclareOption + { + inline std::unique_ptr operator()(std::string name, ShaderAst::ExpressionType type, ShaderAst::ExpressionPtr initialValue = nullptr) const; + }; + struct DeclareStruct { inline std::unique_ptr operator()(ShaderAst::StructDescription description) const; @@ -106,6 +111,11 @@ namespace Nz::ShaderBuilder inline std::unique_ptr operator()(ShaderAst::ExpressionPtr expr = nullptr) const; }; + struct SelectOption + { + inline std::unique_ptr operator()(std::string optionName, ShaderAst::ExpressionPtr truePath, ShaderAst::ExpressionPtr falsePath) const; + }; + struct Swizzle { inline std::unique_ptr operator()(ShaderAst::ExpressionPtr expression, std::vector swizzleComponents) const; @@ -121,6 +131,7 @@ namespace Nz::ShaderBuilder constexpr Impl::ConditionalStatement ConditionalStatement; constexpr Impl::Constant Constant; constexpr Impl::DeclareFunction DeclareFunction; + constexpr Impl::DeclareOption DeclareOption; constexpr Impl::DeclareStruct DeclareStruct; constexpr Impl::DeclareVariable DeclareVariable; constexpr Impl::ExpressionStatement ExpressionStatement; @@ -130,6 +141,7 @@ namespace Nz::ShaderBuilder constexpr Impl::Multi MultiStatement; constexpr Impl::NoParam NoOp; constexpr Impl::Return Return; + constexpr Impl::SelectOption SelectOption; constexpr Impl::Swizzle Swizzle; } diff --git a/include/Nazara/Shader/ShaderBuilder.inl b/include/Nazara/Shader/ShaderBuilder.inl index d48263e01..93287e2b6 100644 --- a/include/Nazara/Shader/ShaderBuilder.inl +++ b/include/Nazara/Shader/ShaderBuilder.inl @@ -70,20 +70,20 @@ namespace Nz::ShaderBuilder return castNode; } - inline std::unique_ptr Impl::ConditionalExpression::operator()(std::string conditionName, ShaderAst::ExpressionPtr truePath, ShaderAst::ExpressionPtr falsePath) const + inline std::unique_ptr Impl::ConditionalExpression::operator()(std::size_t optionIndex, ShaderAst::ExpressionPtr truePath, ShaderAst::ExpressionPtr falsePath) const { auto condExprNode = std::make_unique(); - condExprNode->conditionName = std::move(conditionName); + condExprNode->optionIndex = optionIndex; condExprNode->falsePath = std::move(falsePath); condExprNode->truePath = std::move(truePath); return condExprNode; } - inline std::unique_ptr Impl::ConditionalStatement::operator()(std::string conditionName, ShaderAst::StatementPtr statement) const + inline std::unique_ptr Impl::ConditionalStatement::operator()(std::size_t optionIndex, ShaderAst::StatementPtr statement) const { auto condStatementNode = std::make_unique(); - condStatementNode->conditionName = std::move(conditionName); + condStatementNode->optionIndex = optionIndex; condStatementNode->statement = std::move(statement); return condStatementNode; @@ -129,6 +129,16 @@ namespace Nz::ShaderBuilder return declareFunctionNode; } + inline std::unique_ptr Nz::ShaderBuilder::Impl::DeclareOption::operator()(std::string name, ShaderAst::ExpressionType type, ShaderAst::ExpressionPtr initialValue) const + { + auto declareOptionNode = std::make_unique(); + declareOptionNode->optName = std::move(name); + declareOptionNode->optType = std::move(type); + declareOptionNode->initialValue = std::move(initialValue); + + return declareOptionNode; + } + inline std::unique_ptr Impl::DeclareStruct::operator()(ShaderAst::StructDescription description) const { auto declareStructNode = std::make_unique(); @@ -203,6 +213,16 @@ namespace Nz::ShaderBuilder return returnNode; } + inline std::unique_ptr Impl::SelectOption::operator()(std::string optionName, ShaderAst::ExpressionPtr truePath, ShaderAst::ExpressionPtr falsePath) const + { + auto selectOptNode = std::make_unique(); + selectOptNode->optionName = std::move(optionName); + selectOptNode->falsePath = std::move(falsePath); + selectOptNode->truePath = std::move(truePath); + + return selectOptNode; + } + inline std::unique_ptr Impl::Swizzle::operator()(ShaderAst::ExpressionPtr expression, std::vector swizzleComponents) const { auto swizzleNode = std::make_unique(); diff --git a/include/Nazara/Shader/ShaderLangParser.hpp b/include/Nazara/Shader/ShaderLangParser.hpp index 4780a022c..24f6ca085 100644 --- a/include/Nazara/Shader/ShaderLangParser.hpp +++ b/include/Nazara/Shader/ShaderLangParser.hpp @@ -85,6 +85,7 @@ namespace Nz::ShaderLang std::vector ParseFunctionBody(); ShaderAst::StatementPtr ParseFunctionDeclaration(std::vector attributes = {}); ShaderAst::DeclareFunctionStatement::Parameter ParseFunctionParameter(); + ShaderAst::StatementPtr ParseOptionDeclaration(); ShaderAst::StatementPtr ParseStructDeclaration(std::vector attributes = {}); ShaderAst::StatementPtr ParseReturnStatement(); ShaderAst::StatementPtr ParseStatement(); @@ -100,6 +101,7 @@ namespace Nz::ShaderLang std::vector ParseParameters(); ShaderAst::ExpressionPtr ParseParenthesisExpression(); ShaderAst::ExpressionPtr ParsePrimaryExpression(); + ShaderAst::ExpressionPtr ParseSelectOptExpression(); ShaderAst::ExpressionPtr ParseVariableAssignation(); ShaderAst::AttributeType ParseIdentifierAsAttributeType(); diff --git a/include/Nazara/Shader/ShaderLangTokenList.hpp b/include/Nazara/Shader/ShaderLangTokenList.hpp index 183a16062..a7b8c50f7 100644 --- a/include/Nazara/Shader/ShaderLangTokenList.hpp +++ b/include/Nazara/Shader/ShaderLangTokenList.hpp @@ -40,8 +40,10 @@ NAZARA_SHADERLANG_TOKEN(Plus) NAZARA_SHADERLANG_TOKEN(OpenCurlyBracket) NAZARA_SHADERLANG_TOKEN(OpenSquareBracket) NAZARA_SHADERLANG_TOKEN(OpenParenthesis) +NAZARA_SHADERLANG_TOKEN(Option) NAZARA_SHADERLANG_TOKEN(Semicolon) NAZARA_SHADERLANG_TOKEN(Return) +NAZARA_SHADERLANG_TOKEN(SelectOpt) NAZARA_SHADERLANG_TOKEN(Struct) #undef NAZARA_SHADERLANG_TOKEN diff --git a/include/Nazara/Shader/ShaderWriter.hpp b/include/Nazara/Shader/ShaderWriter.hpp index 47fb04a6f..e955c8535 100644 --- a/include/Nazara/Shader/ShaderWriter.hpp +++ b/include/Nazara/Shader/ShaderWriter.hpp @@ -26,7 +26,7 @@ namespace Nz struct States { - Nz::UInt64 enabledConditions = 0; + Nz::UInt64 enabledOptions = 0; }; }; } diff --git a/include/Nazara/Shader/SpirvWriter.hpp b/include/Nazara/Shader/SpirvWriter.hpp index 284e76a94..52695d2c2 100644 --- a/include/Nazara/Shader/SpirvWriter.hpp +++ b/include/Nazara/Shader/SpirvWriter.hpp @@ -36,7 +36,7 @@ namespace Nz SpirvWriter(SpirvWriter&&) = delete; ~SpirvWriter() = default; - std::vector Generate(ShaderAst::StatementPtr& shader, const States& conditions = {}); + std::vector Generate(ShaderAst::StatementPtr& shader, const States& states = {}); void SetEnv(Environment environment); @@ -62,7 +62,7 @@ namespace Nz UInt32 GetPointerTypeId(const ShaderAst::ExpressionType& type, SpirvStorageClass storageClass) const; UInt32 GetTypeId(const ShaderAst::ExpressionType& type) const; - inline bool IsConditionEnabled(const std::string& condition) const; + bool IsOptionEnabled(std::size_t optionIndex) const; UInt32 RegisterConstant(const ShaderAst::ConstantValue& value); UInt32 RegisterFunctionType(const ShaderAst::DeclareFunctionStatement& functionNode); diff --git a/include/Nazara/Shader/SpirvWriter.inl b/include/Nazara/Shader/SpirvWriter.inl index 903d6265b..0be50bead 100644 --- a/include/Nazara/Shader/SpirvWriter.inl +++ b/include/Nazara/Shader/SpirvWriter.inl @@ -8,14 +8,6 @@ namespace Nz { - inline bool SpirvWriter::IsConditionEnabled(const std::string& condition) const - { - /*std::size_t conditionIndex = m_context.shader->FindConditionByName(condition); - assert(conditionIndex != ShaderAst::InvalidCondition); - - return TestBit(m_context.states->enabledConditions, conditionIndex);*/ - return false; - } } #include diff --git a/include/Nazara/VulkanRenderer/VulkanDevice.hpp b/include/Nazara/VulkanRenderer/VulkanDevice.hpp index d8dc546b6..603532e18 100644 --- a/include/Nazara/VulkanRenderer/VulkanDevice.hpp +++ b/include/Nazara/VulkanRenderer/VulkanDevice.hpp @@ -30,7 +30,7 @@ namespace Nz std::shared_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override; std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override; std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags stages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states) override; - std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags stages, ShaderLanguage lang, const void* source, std::size_t sourceSize) override; + std::shared_ptr InstantiateShaderModule(ShaderStageTypeFlags stages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states) override; std::shared_ptr InstantiateTexture(const TextureInfo& params) override; std::shared_ptr InstantiateTextureSampler(const TextureSamplerInfo& params) override; diff --git a/include/Nazara/VulkanRenderer/VulkanShaderModule.hpp b/include/Nazara/VulkanRenderer/VulkanShaderModule.hpp index 4017cbfe3..c3bc405f0 100644 --- a/include/Nazara/VulkanRenderer/VulkanShaderModule.hpp +++ b/include/Nazara/VulkanRenderer/VulkanShaderModule.hpp @@ -28,7 +28,7 @@ namespace Nz ~VulkanShaderModule() = default; bool Create(Vk::Device& device, ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states); - bool Create(Vk::Device& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize); + bool Create(Vk::Device& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states); inline const Vk::ShaderModule& GetHandle() const; inline const std::vector& GetStages() const; diff --git a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp index a6425aa9f..902bfda5f 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp @@ -85,9 +85,9 @@ namespace Nz return std::make_shared(*this, shaderStages, shaderAst, states); } - std::shared_ptr OpenGLDevice::InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize) + std::shared_ptr OpenGLDevice::InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states) { - return std::make_shared(*this, shaderStages, lang, source, sourceSize); + return std::make_shared(*this, shaderStages, lang, source, sourceSize, states); } std::shared_ptr OpenGLDevice::InstantiateTexture(const TextureInfo& params) diff --git a/src/Nazara/OpenGLRenderer/OpenGLShaderModule.cpp b/src/Nazara/OpenGLRenderer/OpenGLShaderModule.cpp index 4486a07e6..4eb1154f2 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLShaderModule.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLShaderModule.cpp @@ -21,7 +21,7 @@ namespace Nz Create(device, shaderStages, shaderAst, states); } - OpenGLShaderModule::OpenGLShaderModule(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize) + OpenGLShaderModule::OpenGLShaderModule(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states) { NazaraAssert(shaderStages != 0, "at least one shader stage must be specified"); @@ -65,7 +65,7 @@ namespace Nz Nz::ShaderLang::Parser parser; Nz::ShaderAst::StatementPtr shaderAst = parser.Parse(tokens); - Create(device, shaderStages, shaderAst, {}); + Create(device, shaderStages, shaderAst, states); break; } diff --git a/src/Nazara/Renderer/RenderDevice.cpp b/src/Nazara/Renderer/RenderDevice.cpp index 0d71e5e66..19582f718 100644 --- a/src/Nazara/Renderer/RenderDevice.cpp +++ b/src/Nazara/Renderer/RenderDevice.cpp @@ -11,7 +11,7 @@ namespace Nz { RenderDevice::~RenderDevice() = default; - std::shared_ptr RenderDevice::InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const std::filesystem::path& sourcePath) + std::shared_ptr RenderDevice::InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const std::filesystem::path& sourcePath, const ShaderWriter::States& states) { File file(sourcePath); if (!file.Open(OpenMode_ReadOnly | OpenMode_Text)) @@ -29,6 +29,6 @@ namespace Nz return {}; } - return InstantiateShaderModule(shaderStages, lang, source.data(), source.size()); + return InstantiateShaderModule(shaderStages, lang, source.data(), source.size(), states); } } diff --git a/src/Nazara/Shader/Ast/AstCloner.cpp b/src/Nazara/Shader/Ast/AstCloner.cpp index 602ddcd94..2571b86e5 100644 --- a/src/Nazara/Shader/Ast/AstCloner.cpp +++ b/src/Nazara/Shader/Ast/AstCloner.cpp @@ -56,7 +56,7 @@ namespace Nz::ShaderAst StatementPtr AstCloner::Clone(ConditionalStatement& node) { auto clone = std::make_unique(); - clone->conditionName = node.conditionName; + clone->optionIndex = node.optionIndex; clone->statement = CloneStatement(node.statement); return clone; @@ -77,6 +77,7 @@ namespace Nz::ShaderAst clone->entryStage = node.entryStage; clone->funcIndex = node.funcIndex; clone->name = node.name; + clone->optionName = node.optionName; clone->parameters = node.parameters; clone->returnType = node.returnType; clone->varIndex = node.varIndex; @@ -88,6 +89,17 @@ namespace Nz::ShaderAst return clone; } + StatementPtr AstCloner::Clone(DeclareOptionStatement& node) + { + auto clone = std::make_unique(); + clone->initialValue = CloneExpression(node.initialValue); + clone->optIndex = node.optIndex; + clone->optName = node.optName; + clone->optType = node.optType; + + return clone; + } + StatementPtr AstCloner::Clone(DeclareStructStatement& node) { auto clone = std::make_unique(); @@ -212,7 +224,7 @@ namespace Nz::ShaderAst ExpressionPtr AstCloner::Clone(ConditionalExpression& node) { auto clone = std::make_unique(); - clone->conditionName = node.conditionName; + clone->optionIndex = node.optionIndex; clone->falsePath = CloneExpression(node.falsePath); clone->truePath = CloneExpression(node.truePath); @@ -255,6 +267,18 @@ namespace Nz::ShaderAst return clone; } + ExpressionPtr AstCloner::Clone(SelectOptionExpression& node) + { + auto clone = std::make_unique(); + clone->optionName = node.optionName; + clone->falsePath = CloneExpression(node.falsePath); + clone->truePath = CloneExpression(node.truePath); + + clone->cachedExpressionType = node.cachedExpressionType; + + return clone; + } + ExpressionPtr AstCloner::Clone(SwizzleExpression& node) { auto clone = std::make_unique(); diff --git a/src/Nazara/Shader/Ast/AstRecursiveVisitor.cpp b/src/Nazara/Shader/Ast/AstRecursiveVisitor.cpp index 7e33c9590..85e8b2507 100644 --- a/src/Nazara/Shader/Ast/AstRecursiveVisitor.cpp +++ b/src/Nazara/Shader/Ast/AstRecursiveVisitor.cpp @@ -62,6 +62,12 @@ namespace Nz::ShaderAst param->Visit(*this); } + void AstRecursiveVisitor::Visit(SelectOptionExpression& node) + { + node.truePath->Visit(*this); + node.falsePath->Visit(*this); + } + void AstRecursiveVisitor::Visit(SwizzleExpression& node) { node.expression->Visit(*this); @@ -100,6 +106,12 @@ namespace Nz::ShaderAst statement->Visit(*this); } + void AstRecursiveVisitor::Visit(DeclareOptionStatement& node) + { + if (node.initialValue) + node.initialValue->Visit(*this); + } + void AstRecursiveVisitor::Visit(DeclareStructStatement& /*node*/) { /* Nothing to do */ diff --git a/src/Nazara/Shader/Ast/AstSerializer.cpp b/src/Nazara/Shader/Ast/AstSerializer.cpp index 1c79e7600..fee7d53fd 100644 --- a/src/Nazara/Shader/Ast/AstSerializer.cpp +++ b/src/Nazara/Shader/Ast/AstSerializer.cpp @@ -74,7 +74,7 @@ namespace Nz::ShaderAst void AstSerializerBase::Serialize(ConditionalExpression& node) { - Value(node.conditionName); + SizeT(node.optionIndex); Node(node.truePath); Node(node.falsePath); } @@ -113,14 +113,6 @@ namespace Nz::ShaderAst } } - void AstSerializerBase::Serialize(DeclareVariableStatement& node) - { - OptVal(node.varIndex); - Value(node.varName); - Type(node.varType); - Node(node.initialExpression); - } - void AstSerializerBase::Serialize(IdentifierExpression& node) { Value(node.identifier); @@ -134,6 +126,13 @@ namespace Nz::ShaderAst Node(param); } + void AstSerializerBase::Serialize(SelectOptionExpression& node) + { + Value(node.optionName); + Node(node.truePath); + Node(node.falsePath); + } + void AstSerializerBase::Serialize(SwizzleExpression& node) { SizeT(node.componentCount); @@ -163,7 +162,7 @@ namespace Nz::ShaderAst void AstSerializerBase::Serialize(ConditionalStatement& node) { - Value(node.conditionName); + SizeT(node.optionIndex); Node(node.statement); } @@ -186,6 +185,7 @@ namespace Nz::ShaderAst Type(node.returnType); OptEnum(node.entryStage); OptVal(node.funcIndex); + Value(node.optionName); OptVal(node.varIndex); Container(node.parameters); @@ -200,6 +200,14 @@ namespace Nz::ShaderAst Node(statement); } + void AstSerializerBase::Serialize(DeclareOptionStatement& node) + { + OptVal(node.optIndex); + Value(node.optName); + Type(node.optType); + Node(node.initialValue); + } + void AstSerializerBase::Serialize(DeclareStructStatement& node) { OptVal(node.structIndex); @@ -216,6 +224,14 @@ namespace Nz::ShaderAst OptVal(member.locationIndex); } } + + void AstSerializerBase::Serialize(DeclareVariableStatement& node) + { + OptVal(node.varIndex); + Value(node.varName); + Type(node.varType); + Node(node.initialExpression); + } void AstSerializerBase::Serialize(DiscardStatement& /*node*/) { diff --git a/src/Nazara/Shader/Ast/AstUtils.cpp b/src/Nazara/Shader/Ast/AstUtils.cpp index a6895177a..76496ddf0 100644 --- a/src/Nazara/Shader/Ast/AstUtils.cpp +++ b/src/Nazara/Shader/Ast/AstUtils.cpp @@ -67,6 +67,20 @@ namespace Nz::ShaderAst m_expressionCategory = ExpressionCategory::RValue; } + void ShaderAstValueCategory::Visit(SelectOptionExpression& node) + { + node.truePath->Visit(*this); + ExpressionCategory trueExprCategory = m_expressionCategory; + + node.falsePath->Visit(*this); + ExpressionCategory falseExprCategory = m_expressionCategory; + + if (trueExprCategory == ExpressionCategory::RValue || falseExprCategory == ExpressionCategory::RValue) + m_expressionCategory = ExpressionCategory::RValue; + else + m_expressionCategory = ExpressionCategory::LValue; + } + void ShaderAstValueCategory::Visit(SwizzleExpression& node) { node.expression->Visit(*this); diff --git a/src/Nazara/Shader/Ast/Nodes.cpp b/src/Nazara/Shader/Ast/Nodes.cpp index aed845fc5..b334d76ec 100644 --- a/src/Nazara/Shader/Ast/Nodes.cpp +++ b/src/Nazara/Shader/Ast/Nodes.cpp @@ -29,4 +29,35 @@ namespace Nz::ShaderAst } #include + + ExpressionType ConstantExpression::GetExpressionType() const + { + return std::visit([&](auto&& arg) -> ShaderAst::ExpressionType + { + using T = std::decay_t; + + if constexpr (std::is_same_v) + return PrimitiveType::Boolean; + else if constexpr (std::is_same_v) + return PrimitiveType::Float32; + else if constexpr (std::is_same_v) + return PrimitiveType::Int32; + else if constexpr (std::is_same_v) + return PrimitiveType::UInt32; + else if constexpr (std::is_same_v) + return VectorType{ 2, PrimitiveType::Float32 }; + else if constexpr (std::is_same_v) + return VectorType{ 3, PrimitiveType::Float32 }; + else if constexpr (std::is_same_v) + return VectorType{ 4, PrimitiveType::Float32 }; + else if constexpr (std::is_same_v) + return VectorType{ 2, PrimitiveType::Int32 }; + else if constexpr (std::is_same_v) + return VectorType{ 3, PrimitiveType::Int32 }; + else if constexpr (std::is_same_v) + return VectorType{ 4, PrimitiveType::Int32 }; + else + static_assert(AlwaysFalse::value, "non-exhaustive visitor"); + }, value); + } } diff --git a/src/Nazara/Shader/Ast/SanitizeVisitor.cpp b/src/Nazara/Shader/Ast/SanitizeVisitor.cpp index 57a3cd8cd..b05194a82 100644 --- a/src/Nazara/Shader/Ast/SanitizeVisitor.cpp +++ b/src/Nazara/Shader/Ast/SanitizeVisitor.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -28,16 +29,18 @@ namespace Nz::ShaderAst struct SanitizeVisitor::Context { + Options options; std::array entryFunctions = {}; std::unordered_set declaredExternalVar; std::unordered_set usedBindingIndexes; }; - StatementPtr SanitizeVisitor::Sanitize(StatementPtr& nodePtr, std::string* error) + StatementPtr SanitizeVisitor::Sanitize(StatementPtr& nodePtr, const Options& options, std::string* error) { StatementPtr clone; Context currentContext; + currentContext.options = options; m_context = ¤tContext; CallOnExit resetContext([&] { m_context = nullptr; }); @@ -483,6 +486,33 @@ namespace Nz::ShaderAst return clone; } + ExpressionPtr SanitizeVisitor::Clone(SelectOptionExpression& node) + { + MandatoryExpr(node.truePath); + MandatoryExpr(node.falsePath); + + auto condExpr = std::make_unique(); + condExpr->truePath = CloneExpression(node.truePath); + condExpr->falsePath = CloneExpression(node.falsePath); + + const Identifier* identifier = FindIdentifier(node.optionName); + if (!identifier) + throw AstError{ "unknown option " + node.optionName }; + + if (!std::holds_alternative