From f38bfdde8a0a43de8a3ba47f153e00111a798f7f Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 17 Jun 2020 16:00:03 +0200 Subject: [PATCH] ShaderAst: Big refactor + add binding/location support --- SDK/include/NDK/Components.hpp | 9 + SDK/include/NDK/Systems.hpp | 9 + SDK/include/NDK/Widgets.hpp | 9 + include/Nazara/Renderer/GlslWriter.hpp | 86 +-- include/Nazara/Renderer/GlslWriter.inl | 65 +++ include/Nazara/Renderer/ShaderAst.hpp | 434 +++------------ include/Nazara/Renderer/ShaderAst.inl | 369 +++---------- include/Nazara/Renderer/ShaderBuilder.hpp | 70 ++- include/Nazara/Renderer/ShaderBuilder.inl | 37 +- include/Nazara/Renderer/ShaderEnums.hpp | 99 ++++ include/Nazara/Renderer/ShaderNodes.hpp | 272 ++++++++++ include/Nazara/Renderer/ShaderNodes.inl | 300 +++++++++++ include/Nazara/Renderer/ShaderSerializer.hpp | 19 +- include/Nazara/Renderer/ShaderSerializer.inl | 18 +- include/Nazara/Renderer/ShaderValidator.hpp | 47 +- include/Nazara/Renderer/ShaderValidator.inl | 6 +- include/Nazara/Renderer/ShaderVarVisitor.hpp | 34 ++ include/Nazara/Renderer/ShaderVariables.hpp | 127 +++++ include/Nazara/Renderer/ShaderVariables.inl | 65 +++ include/Nazara/Renderer/ShaderVisitor.hpp | 37 +- include/Nazara/Renderer/ShaderWriter.hpp | 14 +- src/Nazara/Renderer/GlslWriter.cpp | 529 +++++++++---------- src/Nazara/Renderer/ShaderAst.cpp | 279 +--------- src/Nazara/Renderer/ShaderNodes.cpp | 179 +++++++ src/Nazara/Renderer/ShaderSerializer.cpp | 149 ++++-- src/Nazara/Renderer/ShaderValidator.cpp | 303 ++++++++--- src/Nazara/Renderer/ShaderVarVisitor.cpp | 16 + src/Nazara/Renderer/ShaderVariables.cpp | 77 +++ src/Nazara/Renderer/ShaderVisitor.cpp | 6 +- src/Nazara/Renderer/ShaderWriter.cpp | 1 + src/ShaderNode/DataModels/Cast.hpp | 2 +- src/ShaderNode/DataModels/Cast.inl | 10 +- src/ShaderNode/DataModels/FloatValue.cpp | 2 +- src/ShaderNode/DataModels/FloatValue.hpp | 2 +- src/ShaderNode/DataModels/InputValue.cpp | 18 +- src/ShaderNode/DataModels/InputValue.hpp | 2 +- src/ShaderNode/DataModels/OutputValue.cpp | 22 +- src/ShaderNode/DataModels/OutputValue.hpp | 2 +- src/ShaderNode/DataModels/SampleTexture.cpp | 2 +- src/ShaderNode/DataModels/SampleTexture.hpp | 2 +- src/ShaderNode/DataModels/ShaderNode.hpp | 4 +- src/ShaderNode/DataModels/TextureValue.cpp | 8 +- src/ShaderNode/DataModels/TextureValue.hpp | 2 +- src/ShaderNode/DataModels/VecBinOp.hpp | 20 +- src/ShaderNode/DataModels/VecBinOp.inl | 22 +- src/ShaderNode/DataModels/VecDot.cpp | 8 +- src/ShaderNode/DataModels/VecDot.hpp | 2 +- src/ShaderNode/DataModels/VecFloatMul.cpp | 6 +- src/ShaderNode/DataModels/VecFloatMul.hpp | 2 +- src/ShaderNode/DataModels/VecValue.hpp | 2 +- src/ShaderNode/DataModels/VecValue.inl | 2 +- src/ShaderNode/DataTypes/TextureData.hpp | 2 +- src/ShaderNode/DataTypes/VecData.cpp | 8 +- src/ShaderNode/DataTypes/VecData.hpp | 14 +- src/ShaderNode/ShaderGraph.cpp | 49 +- src/ShaderNode/ShaderGraph.hpp | 17 +- src/ShaderNode/Widgets/InputEditDialog.cpp | 5 + src/ShaderNode/Widgets/InputEditDialog.hpp | 2 + src/ShaderNode/Widgets/InputEditor.cpp | 4 +- src/ShaderNode/Widgets/MainWindow.cpp | 50 +- src/ShaderNode/Widgets/OutputEditDialog.cpp | 12 +- src/ShaderNode/Widgets/OutputEditDialog.hpp | 5 +- src/ShaderNode/Widgets/OutputEditor.cpp | 8 +- 63 files changed, 2380 insertions(+), 1603 deletions(-) create mode 100644 SDK/include/NDK/Components.hpp create mode 100644 SDK/include/NDK/Systems.hpp create mode 100644 SDK/include/NDK/Widgets.hpp create mode 100644 include/Nazara/Renderer/GlslWriter.inl create mode 100644 include/Nazara/Renderer/ShaderEnums.hpp create mode 100644 include/Nazara/Renderer/ShaderNodes.hpp create mode 100644 include/Nazara/Renderer/ShaderNodes.inl create mode 100644 include/Nazara/Renderer/ShaderVarVisitor.hpp create mode 100644 include/Nazara/Renderer/ShaderVariables.hpp create mode 100644 include/Nazara/Renderer/ShaderVariables.inl create mode 100644 src/Nazara/Renderer/ShaderNodes.cpp create mode 100644 src/Nazara/Renderer/ShaderVarVisitor.cpp create mode 100644 src/Nazara/Renderer/ShaderVariables.cpp diff --git a/SDK/include/NDK/Components.hpp b/SDK/include/NDK/Components.hpp new file mode 100644 index 000000000..97f597990 --- /dev/null +++ b/SDK/include/NDK/Components.hpp @@ -0,0 +1,9 @@ +// This file was automatically generated + +#pragma once + +#ifndef NDK_COMPONENTS_GLOBAL_HPP +#define NDK_COMPONENTS_GLOBAL_HPP + + +#endif // NDK_COMPONENTS_GLOBAL_HPP diff --git a/SDK/include/NDK/Systems.hpp b/SDK/include/NDK/Systems.hpp new file mode 100644 index 000000000..33edfc17a --- /dev/null +++ b/SDK/include/NDK/Systems.hpp @@ -0,0 +1,9 @@ +// This file was automatically generated + +#pragma once + +#ifndef NDK_SYSTEMS_GLOBAL_HPP +#define NDK_SYSTEMS_GLOBAL_HPP + + +#endif // NDK_SYSTEMS_GLOBAL_HPP diff --git a/SDK/include/NDK/Widgets.hpp b/SDK/include/NDK/Widgets.hpp new file mode 100644 index 000000000..b009f3a17 --- /dev/null +++ b/SDK/include/NDK/Widgets.hpp @@ -0,0 +1,9 @@ +// This file was automatically generated + +#pragma once + +#ifndef NDK_WIDGETS_GLOBAL_HPP +#define NDK_WIDGETS_GLOBAL_HPP + + +#endif // NDK_WIDGETS_GLOBAL_HPP diff --git a/include/Nazara/Renderer/GlslWriter.hpp b/include/Nazara/Renderer/GlslWriter.hpp index 2caaa6a75..22d6544f2 100644 --- a/include/Nazara/Renderer/GlslWriter.hpp +++ b/include/Nazara/Renderer/GlslWriter.hpp @@ -8,15 +8,19 @@ #define NAZARA_GLSLWRITER_HPP #include -#include #include +#include +#include +#include #include #include +#include +#include #include namespace Nz { - class NAZARA_RENDERER_API GlslWriter : public ShaderWriter + class NAZARA_RENDERER_API GlslWriter : public ShaderWriter, public ShaderVarVisitor, public ShaderVisitor { public: GlslWriter(); @@ -24,67 +28,65 @@ namespace Nz GlslWriter(GlslWriter&&) = delete; ~GlslWriter() = default; - Nz::String Generate(const ShaderAst::StatementPtr& node) override; - - void RegisterFunction(const String& name, ShaderAst::StatementPtr statement, std::initializer_list parameters, ShaderAst::ExpressionType ret) override; - void RegisterVariable(ShaderAst::VariableType kind, const String& name, ShaderAst::ExpressionType type) override; + std::string Generate(const ShaderAst& shader) override; void SetGlslVersion(unsigned int version); - using ShaderWriter::Visit; - void Visit(const ShaderAst::AssignOp& node) override; - void Visit(const ShaderAst::Branch& node) override; - void Visit(const ShaderAst::BinaryFunc& node) override; - void Visit(const ShaderAst::BinaryOp& node) override; - void Visit(const ShaderAst::BuiltinVariable& node) override; - void Visit(const ShaderAst::Cast& node) override; - void Visit(const ShaderAst::Constant& node) override; - void Visit(const ShaderAst::DeclareVariable& node) override; - void Visit(const ShaderAst::ExpressionStatement& node) override; - void Visit(const ShaderAst::NamedVariable& node) override; - void Visit(const ShaderAst::Sample2D& node) override; - void Visit(const ShaderAst::StatementBlock& node) override; - void Visit(const ShaderAst::SwizzleOp& node) override; - private: - struct Function; - using VariableContainer = std::set>; + void Append(ShaderNodes::BuiltinEntry builtin); + void Append(ShaderNodes::ExpressionType type); + template void Append(const T& param); + void AppendCommentSection(const std::string& section); + void AppendFunction(const ShaderAst::Function& func); + void AppendFunctionPrototype(const ShaderAst::Function& func); + void AppendLine(const std::string& txt = {}); - void Append(ShaderAst::BuiltinEntry builtin); - void Append(ShaderAst::ExpressionType type); - void Append(const String& txt); - void AppendCommentSection(const String& section); - void AppendFunction(Function& func); - void AppendLine(const String& txt = String()); - - void DeclareVariables(const VariableContainer& variables, const String& keyword = String(), const String& section = String()); + template void DeclareVariables(const std::vector& variables, const std::string& keyword = {}, const std::string& section = {}); void EnterScope(); void LeaveScope(); + using ShaderVarVisitor::Visit; + using ShaderVisitor::Visit; + void Visit(const ShaderNodes::AssignOp& node) override; + void Visit(const ShaderNodes::Branch& node) override; + void Visit(const ShaderNodes::BinaryOp& node) override; + void Visit(const ShaderNodes::BuiltinVariable& var) override; + void Visit(const ShaderNodes::Cast& node) override; + void Visit(const ShaderNodes::Constant& node) override; + void Visit(const ShaderNodes::DeclareVariable& node) override; + void Visit(const ShaderNodes::ExpressionStatement& node) override; + void Visit(const ShaderNodes::Identifier& node) override; + void Visit(const ShaderNodes::InputVariable& var) override; + void Visit(const ShaderNodes::IntrinsicCall& node) override; + void Visit(const ShaderNodes::LocalVariable& var) override; + void Visit(const ShaderNodes::ParameterVariable& var) override; + void Visit(const ShaderNodes::OutputVariable& var) override; + void Visit(const ShaderNodes::Sample2D& node) override; + void Visit(const ShaderNodes::StatementBlock& node) override; + void Visit(const ShaderNodes::SwizzleOp& node) override; + void Visit(const ShaderNodes::UniformVariable& var) override; - struct Function + static bool HasExplicitBinding(const ShaderAst& shader); + static bool HasExplicitLocation(const ShaderAst& shader); + + struct Context { - std::vector parameters; - ShaderAst::ExpressionType retType; - ShaderAst::StatementPtr node; - String name; + const ShaderAst::Function* currentFunction = nullptr; }; struct State { - VariableContainer inputs; - VariableContainer outputs; - VariableContainer uniforms; - StringStream stream; + std::stringstream stream; unsigned int indentLevel = 0; }; - std::unordered_map m_functions; - Function* m_currentFunction; + Context m_context; State* m_currentState; unsigned int m_glslVersion; }; } +#include + #endif // NAZARA_GLSLWRITER_HPP diff --git a/include/Nazara/Renderer/GlslWriter.inl b/include/Nazara/Renderer/GlslWriter.inl new file mode 100644 index 000000000..fcaca4b98 --- /dev/null +++ b/include/Nazara/Renderer/GlslWriter.inl @@ -0,0 +1,65 @@ +// 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 + +#include +#include +#include + +namespace Nz +{ + template + void GlslWriter::Append(const T& param) + { + NazaraAssert(m_currentState, "This function should only be called while processing an AST"); + + m_currentState->stream << param; + } + + template + void GlslWriter::DeclareVariables(const std::vector& variables, const std::string& keyword, const std::string& section) + { + if (!variables.empty()) + { + if (!section.empty()) + AppendCommentSection(section); + + for (const auto& var : variables) + { + if constexpr (std::is_same_v) + { + if (var.locationIndex) + { + Append("layout(location = "); + Append(*var.locationIndex); + Append(") "); + } + } + else if constexpr (std::is_same_v) + { + if (var.bindingIndex) + { + Append("layout(binding = "); + Append(*var.bindingIndex); + Append(") "); + } + } + + if (!keyword.empty()) + { + Append(keyword); + Append(" "); + } + + Append(var.type); + Append(" "); + Append(var.name); + AppendLine(";"); + } + + AppendLine(); + } + } +} + +#include diff --git a/include/Nazara/Renderer/ShaderAst.hpp b/include/Nazara/Renderer/ShaderAst.hpp index 0bbaec9f3..0aa094a10 100644 --- a/include/Nazara/Renderer/ShaderAst.hpp +++ b/include/Nazara/Renderer/ShaderAst.hpp @@ -8,393 +8,77 @@ #define NAZARA_SHADER_AST_HPP #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include namespace Nz { - class ByteStream; - class ShaderVisitor; - class ShaderWriter; - - namespace ShaderAst + class NAZARA_RENDERER_API ShaderAst { - enum class AssignType - { - Simple //< = - }; - - enum class BinaryIntrinsic - { - CrossProduct, - DotProduct - }; - - enum class BinaryType - { - Add, //< + - Substract, //< - - Multiply, //< * - Divide, //< / - - Equality //< == - }; - - enum class BuiltinEntry - { - VertexPosition, // gl_Position - }; - - enum class ExpressionCategory - { - LValue, - RValue - }; - - enum class ExpressionType - { - Boolean, // bool - Float1, // float - Float2, // vec2 - Float3, // vec3 - Float4, // vec4 - Mat4x4, // mat4 - Sampler2D, // sampler2D - - Void // void - }; - - enum class NodeType - { - None = -1, - - AssignOp, - BinaryFunc, - BinaryOp, - Branch, - BuiltinVariable, - Cast, - Constant, - ConditionalStatement, - DeclareVariable, - ExpressionStatement, - NamedVariable, - Sample2D, - SwizzleOp, - StatementBlock - }; - - enum class SwizzleComponent - { - First, - Second, - Third, - Fourth - }; - - enum class VariableType - { - Builtin, - Input, - Output, - Parameter, - Uniform, - Variable - }; - - ////////////////////////////////////////////////////////////////////////// - - class Node; - - using NodePtr = std::shared_ptr; - - class NAZARA_RENDERER_API Node - { - public: - virtual ~Node(); - - inline NodeType GetType() const; - - virtual void Register(ShaderWriter& visitor) = 0; - virtual void Visit(ShaderVisitor& visitor) = 0; - - static inline unsigned int GetComponentCount(ExpressionType type); - static inline ExpressionType GetComponentType(ExpressionType type); - - protected: - inline Node(NodeType type); - - private: - NodeType m_type; - }; - - class Statement; - - using StatementPtr = std::shared_ptr; - - class NAZARA_RENDERER_API Statement : public Node - { - public: - using Node::Node; - }; - - class Expression; - - using ExpressionPtr = std::shared_ptr; - - class NAZARA_RENDERER_API Expression : public Node - { - public: - using Node::Node; - - virtual ExpressionCategory GetExpressionCategory() const; - virtual ExpressionType GetExpressionType() const = 0; - }; - - struct NAZARA_RENDERER_API ExpressionStatement : public Statement - { - inline ExpressionStatement(); - - void Register(ShaderWriter& visitor) override; - void Visit(ShaderVisitor& visitor) override; - - ExpressionPtr expression; - - static inline std::shared_ptr Build(ExpressionPtr expr); - }; - - ////////////////////////////////////////////////////////////////////////// - - struct NAZARA_RENDERER_API ConditionalStatement : public Statement - { - inline ConditionalStatement(); - - void Register(ShaderWriter& visitor) override; - void Visit(ShaderVisitor& visitor) override; - - std::string conditionName; - StatementPtr statement; - - static inline std::shared_ptr Build(std::string condition, StatementPtr statementPtr); - }; - - struct NAZARA_RENDERER_API StatementBlock : public Statement - { - inline StatementBlock(); - - void Register(ShaderWriter& visitor) override; - void Visit(ShaderVisitor& visitor) override; - - std::vector statements; - - template static std::shared_ptr Build(Args&&... args); - }; - - struct Variable; - - using VariablePtr = std::shared_ptr; - - struct NAZARA_RENDERER_API Variable : public Expression - { - using Expression::Expression; - - ExpressionCategory GetExpressionCategory() const override; - ExpressionType GetExpressionType() const override; - - ExpressionType type; - VariableType kind; - }; - - - struct NAZARA_RENDERER_API BuiltinVariable : public Variable - { - inline BuiltinVariable(); - - void Register(ShaderWriter& visitor) override; - void Visit(ShaderVisitor& visitor) override; - - BuiltinEntry var; - - static inline std::shared_ptr Build(BuiltinEntry variable, ExpressionType varType); - }; - - - struct NamedVariable; - - using NamedVariablePtr = std::shared_ptr; - - struct NAZARA_RENDERER_API NamedVariable : public Variable - { - inline NamedVariable(); - - void Register(ShaderWriter& visitor) override; - void Visit(ShaderVisitor& visitor) override; - - std::string name; - - static inline std::shared_ptr Build(VariableType varType, std::string varName, ExpressionType expressionType); - }; - - struct NAZARA_RENDERER_API DeclareVariable : public Statement - { - inline DeclareVariable(); - - void Register(ShaderWriter& visitor) override; - void Visit(ShaderVisitor& visitor) override; - - NamedVariablePtr variable; - ExpressionPtr expression; - - static inline std::shared_ptr Build(NamedVariablePtr variable, ExpressionPtr expression = nullptr); - }; - - ////////////////////////////////////////////////////////////////////////// - - struct NAZARA_RENDERER_API AssignOp : public Expression - { - inline AssignOp(); - - ExpressionType GetExpressionType() const override; - void Register(ShaderWriter& visitor) override; - void Visit(ShaderVisitor& visitor) override; - - AssignType op; - ExpressionPtr left; - ExpressionPtr right; - - static inline std::shared_ptr Build(AssignType op, ExpressionPtr left, ExpressionPtr right); - }; - - struct NAZARA_RENDERER_API BinaryOp : public Expression - { - inline BinaryOp(); - - ExpressionType GetExpressionType() const override; - void Register(ShaderWriter& visitor) override; - void Visit(ShaderVisitor& visitor) override; - - BinaryType op; - ExpressionPtr left; - ExpressionPtr right; - - static inline std::shared_ptr Build(BinaryType op, ExpressionPtr left, ExpressionPtr right); - }; - - struct NAZARA_RENDERER_API Branch : public Statement - { - struct ConditionalStatement; - - inline Branch(); - - void Register(ShaderWriter& visitor) override; - void Visit(ShaderVisitor& visitor) override; - - std::vector condStatements; - StatementPtr elseStatement; - - struct ConditionalStatement + public: + struct Function; + struct FunctionParameter; + struct InputOutput; + struct VariableBase; + struct Uniform; + + ShaderAst() = default; + ~ShaderAst() = default; + + void AddFunction(std::string name, ShaderNodes::StatementPtr statement, std::vector parameters = {}, ShaderNodes::ExpressionType returnType = ShaderNodes::ExpressionType::Void); + void AddInput(std::string name, ShaderNodes::ExpressionType type, std::optional locationIndex); + void AddOutput(std::string name, ShaderNodes::ExpressionType type, std::optional locationIndex); + void AddUniform(std::string name, ShaderNodes::ExpressionType type, std::optional bindingIndex); + + inline const Function& GetFunction(std::size_t i) const; + inline std::size_t GetFunctionCount() const; + inline const std::vector& GetFunctions() const; + inline const InputOutput& GetInput(std::size_t i) const; + inline std::size_t GetInputCount() const; + inline const std::vector& GetInputs() const; + inline const InputOutput& GetOutput(std::size_t i) const; + inline std::size_t GetOutputCount() const; + inline const std::vector& GetOutputs() const; + inline const Uniform& GetUniform(std::size_t i) const; + inline std::size_t GetUniformCount() const; + inline const std::vector& GetUniforms() const; + + struct VariableBase { - ExpressionPtr condition; - StatementPtr statement; + std::string name; + ShaderNodes::ExpressionType type; }; - inline std::shared_ptr Build(ExpressionPtr condition, StatementPtr trueStatement, StatementPtr falseStatement = nullptr); - }; - - struct NAZARA_RENDERER_API Cast : public Expression - { - inline Cast(); - - ExpressionType GetExpressionType() const override; - void Register(ShaderWriter& visitor) override; - void Visit(ShaderVisitor& visitor) override; - - ExpressionType exprType; - std::array expressions; - - static inline std::shared_ptr Build(ExpressionType castTo, ExpressionPtr first, ExpressionPtr second = nullptr, ExpressionPtr third = nullptr, ExpressionPtr fourth = nullptr); - static inline std::shared_ptr Build(ExpressionType castTo, ExpressionPtr* expressions, std::size_t expressionCount); - }; - - struct NAZARA_RENDERER_API Constant : public Expression - { - inline Constant(); - - ExpressionType GetExpressionType() const override; - void Register(ShaderWriter& visitor) override; - void Visit(ShaderVisitor& visitor) override; - - ExpressionType exprType; - - union + struct FunctionParameter : VariableBase { - bool bool1; - float vec1; - Vector2f vec2; - Vector3f vec3; - Vector4f vec4; - } values; + }; - static inline std::shared_ptr Build(bool value); - static inline std::shared_ptr Build(float value); - static inline std::shared_ptr Build(const Vector2f& value); - static inline std::shared_ptr Build(const Vector3f& value); - static inline std::shared_ptr Build(const Vector4f& value); - }; + struct Function + { + std::string name; + std::vector parameters; + ShaderNodes::ExpressionType returnType; + ShaderNodes::StatementPtr statement; + }; - struct NAZARA_RENDERER_API SwizzleOp : public Expression - { - inline SwizzleOp(); + struct InputOutput : VariableBase + { + std::optional locationIndex; + }; - ExpressionCategory GetExpressionCategory() const override; - ExpressionType GetExpressionType() const override; - void Register(ShaderWriter& visitor) override; - void Visit(ShaderVisitor& visitor) override; + struct Uniform : VariableBase + { + std::optional bindingIndex; + }; - std::array components; - std::size_t componentCount; - ExpressionPtr expression; - - static inline std::shared_ptr Build(ExpressionPtr expressionPtr, std::initializer_list swizzleComponents); - }; - - ////////////////////////////////////////////////////////////////////////// - - struct NAZARA_RENDERER_API Sample2D : public Expression - { - inline Sample2D(); - - ExpressionType GetExpressionType() const override; - void Register(ShaderWriter& visitor) override; - void Visit(ShaderVisitor& visitor) override; - - ExpressionPtr sampler; - ExpressionPtr coordinates; - - static inline std::shared_ptr Build(ExpressionPtr samplerPtr, ExpressionPtr coordinatesPtr); - }; - - ////////////////////////////////////////////////////////////////////////// - - struct NAZARA_RENDERER_API BinaryFunc : public Expression - { - inline BinaryFunc(); - - ExpressionType GetExpressionType() const override; - void Register(ShaderWriter& visitor) override; - void Visit(ShaderVisitor& visitor) override; - - BinaryIntrinsic intrinsic; - ExpressionPtr left; - ExpressionPtr right; - - static inline std::shared_ptr Build(BinaryIntrinsic intrinsic, ExpressionPtr left, ExpressionPtr right); - }; - } + private: + std::vector m_functions; + std::vector m_inputs; + std::vector m_outputs; + std::vector m_uniforms; + }; } #include diff --git a/include/Nazara/Renderer/ShaderAst.inl b/include/Nazara/Renderer/ShaderAst.inl index 536758832..d9f8f88aa 100644 --- a/include/Nazara/Renderer/ShaderAst.inl +++ b/include/Nazara/Renderer/ShaderAst.inl @@ -7,315 +7,68 @@ namespace Nz { - namespace ShaderAst + inline auto ShaderAst::GetFunction(std::size_t i) const -> const Function& { - inline Node::Node(NodeType type) : - m_type(type) - { - } - - inline NodeType ShaderAst::Node::GetType() const - { - return m_type; - } - - inline unsigned int Node::GetComponentCount(ExpressionType type) - { - switch (type) - { - case ExpressionType::Float2: - return 2; - - case ExpressionType::Float3: - return 3; - - case ExpressionType::Float4: - return 4; - - case ExpressionType::Mat4x4: - return 4; - - default: - return 1; - } - } - - inline ExpressionType Node::GetComponentType(ExpressionType type) - { - switch (type) - { - case ExpressionType::Float2: - case ExpressionType::Float3: - case ExpressionType::Float4: - return ExpressionType::Float1; - - case ExpressionType::Mat4x4: - return ExpressionType::Float4; - - default: - return type; - } - } - - inline ExpressionStatement::ExpressionStatement() : - Statement(NodeType::ExpressionStatement) - { - } - - inline std::shared_ptr ExpressionStatement::Build(ExpressionPtr expr) - { - auto node = std::make_shared(); - node->expression = std::move(expr); - - return node; - } - - inline ConditionalStatement::ConditionalStatement() : - Statement(NodeType::ConditionalStatement) - { - } - - inline std::shared_ptr ConditionalStatement::Build(std::string condition, StatementPtr statementPtr) - { - auto node = std::make_shared(); - node->conditionName = std::move(condition); - node->statement = std::move(statementPtr); - - return node; - } - - - inline StatementBlock::StatementBlock() : - Statement(NodeType::StatementBlock) - { - } - - template - std::shared_ptr StatementBlock::Build(Args&&... args) - { - auto node = std::make_shared(); - node->statements = std::vector({ std::forward(args)... }); - - return node; - } - - - inline BuiltinVariable::BuiltinVariable() : - Variable(NodeType::BuiltinVariable) - { - kind = VariableType::Builtin; - } - - inline std::shared_ptr BuiltinVariable::Build(BuiltinEntry variable, ExpressionType varType) - { - auto node = std::make_shared(); - node->type = varType; - node->var = variable; - - return node; - } - - - inline NamedVariable::NamedVariable() : - Variable(NodeType::NamedVariable) - { - } - - inline std::shared_ptr NamedVariable::Build(VariableType type, std::string varName, ExpressionType expressionType) - { - auto node = std::make_shared(); - node->kind = type; - node->name = std::move(varName); - node->type = expressionType; - - return node; - } - - - inline DeclareVariable::DeclareVariable() : - Statement(NodeType::DeclareVariable) - { - } - - inline std::shared_ptr DeclareVariable::Build(NamedVariablePtr variable, ExpressionPtr expression) - { - auto node = std::make_shared(); - node->expression = std::move(expression); - node->variable = std::move(variable); - - return node; - } - - - inline AssignOp::AssignOp() : - Expression(NodeType::AssignOp) - { - } - - inline std::shared_ptr AssignOp::Build(AssignType op, ExpressionPtr left, ExpressionPtr right) - { - auto node = std::make_shared(); - node->op = op; - node->left = std::move(left); - node->right = std::move(right); - - return node; - } - - - inline BinaryOp::BinaryOp() : - Expression(NodeType::BinaryOp) - { - } - - inline std::shared_ptr BinaryOp::Build(BinaryType op, ExpressionPtr left, ExpressionPtr right) - { - auto node = std::make_shared(); - node->op = op; - node->left = std::move(left); - node->right = std::move(right); - - return node; - } - - - inline Branch::Branch() : - Statement(NodeType::Branch) - { - } - - inline std::shared_ptr Branch::Build(ExpressionPtr condition, StatementPtr trueStatement, StatementPtr falseStatement) - { - auto node = std::make_shared(); - node->condStatements.emplace_back(ConditionalStatement{ std::move(condition), std::move(trueStatement) }); - node->elseStatement = std::move(falseStatement); - - return node; - } - - - inline Cast::Cast() : - Expression(NodeType::Cast) - { - } - - inline std::shared_ptr Cast::Build(ExpressionType castTo, ExpressionPtr first, ExpressionPtr second, ExpressionPtr third, ExpressionPtr fourth) - { - auto node = std::make_shared(); - node->exprType = castTo; - node->expressions = { {first, second, third, fourth} }; - - return node; - } - - inline std::shared_ptr Cast::Build(ExpressionType castTo, ExpressionPtr* Expressions, std::size_t expressionCount) - { - auto node = std::make_shared(); - node->exprType = castTo; - for (std::size_t i = 0; i < expressionCount; ++i) - node->expressions[i] = Expressions[i]; - - return node; - } - - - inline Constant::Constant() : - Expression(NodeType::Constant) - { - } - - inline std::shared_ptr Constant::Build(bool value) - { - auto node = std::make_shared(); - node->exprType = ExpressionType::Boolean; - node->values.bool1 = value; - - return node; - } - - inline std::shared_ptr Constant::Build(float value) - { - auto node = std::make_shared(); - node->exprType = ExpressionType::Float1; - node->values.vec1 = value; - - return node; - } - - inline std::shared_ptr Constant::Build(const Vector2f& value) - { - auto node = std::make_shared(); - node->exprType = ExpressionType::Float2; - node->values.vec2 = value; - - return node; - } - - inline std::shared_ptr Constant::Build(const Vector3f& value) - { - auto node = std::make_shared(); - node->exprType = ExpressionType::Float3; - node->values.vec3 = value; - - return node; - } - - inline std::shared_ptr Constant::Build(const Vector4f& value) - { - auto node = std::make_shared(); - node->exprType = ExpressionType::Float4; - node->values.vec4 = value; - - return node; - } - - - inline SwizzleOp::SwizzleOp() : - Expression(NodeType::SwizzleOp) - { - } - - inline std::shared_ptr SwizzleOp::Build(ExpressionPtr expressionPtr, std::initializer_list swizzleComponents) - { - auto node = std::make_shared(); - node->componentCount = swizzleComponents.size(); - node->expression = std::move(expressionPtr); - - std::copy(swizzleComponents.begin(), swizzleComponents.end(), node->components.begin()); - - return node; - } - - - inline Sample2D::Sample2D() : - Expression(NodeType::Sample2D) - { - } - - inline std::shared_ptr Sample2D::Build(ExpressionPtr samplerPtr, ExpressionPtr coordinatesPtr) - { - auto node = std::make_shared(); - node->coordinates = std::move(coordinatesPtr); - node->sampler = std::move(samplerPtr); - - return node; - } - - - inline BinaryFunc::BinaryFunc() : - Expression(NodeType::BinaryFunc) - { - } - - inline std::shared_ptr BinaryFunc::Build(BinaryIntrinsic intrinsic, ExpressionPtr left, ExpressionPtr right) - { - auto node = std::make_shared(); - node->intrinsic = intrinsic; - node->left = std::move(left); - node->right = std::move(right); - - return node; - } + assert(i < m_functions.size()); + return m_functions[i]; + } + + inline std::size_t ShaderAst::GetFunctionCount() const + { + return m_functions.size(); + } + + inline auto ShaderAst::GetFunctions() const -> const std::vector& + { + return m_functions; + } + + inline auto ShaderAst::GetInput(std::size_t i) const -> const InputOutput& + { + assert(i < m_inputs.size()); + return m_inputs[i]; + } + + inline std::size_t ShaderAst::GetInputCount() const + { + return m_inputs.size(); + } + + inline auto ShaderAst::GetInputs() const -> const std::vector& + { + return m_inputs; + } + + inline auto ShaderAst::GetOutput(std::size_t i) const -> const InputOutput& + { + assert(i < m_outputs.size()); + return m_outputs[i]; + } + + inline std::size_t ShaderAst::GetOutputCount() const + { + return m_outputs.size(); + } + + inline auto ShaderAst::GetOutputs() const -> const std::vector& + { + return m_outputs; + } + + inline auto ShaderAst::GetUniform(std::size_t i) const -> const Uniform& + { + assert(i < m_uniforms.size()); + return m_uniforms[i]; + } + + inline std::size_t ShaderAst::GetUniformCount() const + { + return m_uniforms.size(); + } + + inline auto ShaderAst::GetUniforms() const -> const std::vector& + { + return m_uniforms; } } diff --git a/include/Nazara/Renderer/ShaderBuilder.hpp b/include/Nazara/Renderer/ShaderBuilder.hpp index f8140ab42..cc437f45f 100644 --- a/include/Nazara/Renderer/ShaderBuilder.hpp +++ b/include/Nazara/Renderer/ShaderBuilder.hpp @@ -8,72 +8,66 @@ #define NAZARA_SHADER_BUILDER_HPP #include -#include +#include #include namespace Nz::ShaderBuilder { - template + template struct AssignOpBuilder { - constexpr AssignOpBuilder() {} + constexpr AssignOpBuilder() = default; - std::shared_ptr operator()(const ShaderAst::ExpressionPtr& left, const ShaderAst::ExpressionPtr& right) const; + std::shared_ptr operator()(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right) const; }; - template + template struct BinOpBuilder { - constexpr BinOpBuilder() {} + constexpr BinOpBuilder() = default; - std::shared_ptr operator()(const ShaderAst::ExpressionPtr& left, const ShaderAst::ExpressionPtr& right) const; + std::shared_ptr operator()(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right) const; }; struct BuiltinBuilder { - constexpr BuiltinBuilder() {} + constexpr BuiltinBuilder() = default; - inline std::shared_ptr operator()(ShaderAst::BuiltinEntry builtin) const; + inline std::shared_ptr operator()(ShaderNodes::BuiltinEntry builtin) const; }; template struct GenBuilder { - constexpr GenBuilder() {} + constexpr GenBuilder() = default; template std::shared_ptr operator()(Args&&... args) const; }; - template - struct VarBuilder - { - constexpr VarBuilder() {} - - template ShaderAst::NamedVariablePtr operator()(Args&&... args) const; - }; - - constexpr BinOpBuilder Add; - constexpr AssignOpBuilder Assign; + constexpr BinOpBuilder Add; + constexpr AssignOpBuilder Assign; constexpr BuiltinBuilder Builtin; - constexpr GenBuilder Block; - constexpr GenBuilder Branch; - constexpr GenBuilder ConditionalStatement; - constexpr GenBuilder Constant; - constexpr GenBuilder DeclareVariable; - constexpr BinOpBuilder Divide; - constexpr BinOpBuilder Equal; - constexpr GenBuilder ExprStatement; - constexpr VarBuilder Input; - constexpr BinOpBuilder Multiply; - constexpr VarBuilder Output; - constexpr VarBuilder Parameter; - constexpr GenBuilder Sample2D; - constexpr GenBuilder Swizzle; - constexpr BinOpBuilder Substract; - constexpr VarBuilder Uniform; - constexpr VarBuilder Variable; + constexpr GenBuilder Block; + constexpr GenBuilder Branch; + constexpr GenBuilder ConditionalStatement; + constexpr GenBuilder Constant; + constexpr GenBuilder DeclareVariable; + constexpr BinOpBuilder Divide; + constexpr BinOpBuilder Equal; + constexpr GenBuilder ExprStatement; + constexpr GenBuilder Identifier; + constexpr GenBuilder IntrinsicCall; + constexpr GenBuilder Input; + constexpr GenBuilder Local; + constexpr BinOpBuilder Multiply; + constexpr GenBuilder Output; + constexpr GenBuilder Parameter; + constexpr GenBuilder Sample2D; + constexpr GenBuilder Swizzle; + constexpr BinOpBuilder Substract; + constexpr GenBuilder Uniform; - template std::shared_ptr Cast(Args&&... args); + template std::shared_ptr Cast(Args&&... args); } #include diff --git a/include/Nazara/Renderer/ShaderBuilder.inl b/include/Nazara/Renderer/ShaderBuilder.inl index 7f9612a11..dda1d730b 100644 --- a/include/Nazara/Renderer/ShaderBuilder.inl +++ b/include/Nazara/Renderer/ShaderBuilder.inl @@ -14,45 +14,38 @@ namespace Nz::ShaderBuilder return T::Build(std::forward(args)...); } - template - std::shared_ptr AssignOpBuilder::operator()(const ShaderAst::ExpressionPtr& left, const ShaderAst::ExpressionPtr& right) const + template + std::shared_ptr AssignOpBuilder::operator()(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right) const { - return ShaderAst::AssignOp::Build(op, left, right); + return ShaderNodes::AssignOp::Build(op, left, right); } - template - std::shared_ptr BinOpBuilder::operator()(const ShaderAst::ExpressionPtr& left, const ShaderAst::ExpressionPtr& right) const + template + std::shared_ptr BinOpBuilder::operator()(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right) const { - return ShaderAst::BinaryOp::Build(op, left, right); + return ShaderNodes::BinaryOp::Build(op, left, right); } - inline std::shared_ptr BuiltinBuilder::operator()(ShaderAst::BuiltinEntry builtin) const + inline std::shared_ptr BuiltinBuilder::operator()(ShaderNodes::BuiltinEntry builtin) const { - ShaderAst::ExpressionType exprType = ShaderAst::ExpressionType::Void; + ShaderNodes::ExpressionType exprType = ShaderNodes::ExpressionType::Void; switch (builtin) { - case ShaderAst::BuiltinEntry::VertexPosition: - exprType = ShaderAst::ExpressionType::Float4; + case ShaderNodes::BuiltinEntry::VertexPosition: + exprType = ShaderNodes::ExpressionType::Float4; break; } - NazaraAssert(exprType != ShaderAst::ExpressionType::Void, "Unhandled builtin"); + NazaraAssert(exprType != ShaderNodes::ExpressionType::Void, "Unhandled builtin"); - return ShaderAst::BuiltinVariable::Build(builtin, exprType); + return ShaderNodes::BuiltinVariable::Build(builtin, exprType); } - template - template - ShaderAst::NamedVariablePtr VarBuilder::operator()(Args&&... args) const + template + std::shared_ptr Cast(Args&&... args) { - return ShaderAst::NamedVariable::Build(type, std::forward(args)...); - } - - template - std::shared_ptr Cast(Args&&... args) - { - return ShaderAst::Cast::Build(Type, std::forward(args)...); + return ShaderNodes::Cast::Build(Type, std::forward(args)...); } } diff --git a/include/Nazara/Renderer/ShaderEnums.hpp b/include/Nazara/Renderer/ShaderEnums.hpp new file mode 100644 index 000000000..f400c7516 --- /dev/null +++ b/include/Nazara/Renderer/ShaderEnums.hpp @@ -0,0 +1,99 @@ +// 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_SHADER_ENUMS_HPP +#define NAZARA_SHADER_ENUMS_HPP + +#include + +namespace Nz::ShaderNodes +{ + enum class AssignType + { + Simple //< = + }; + + enum class BinaryType + { + Add, //< + + Substract, //< - + Multiply, //< * + Divide, //< / + + Equality //< == + }; + + enum class BuiltinEntry + { + VertexPosition, // gl_Position + }; + + enum class ExpressionCategory + { + LValue, + RValue + }; + + enum class ExpressionType + { + Boolean, // bool + Float1, // float + Float2, // vec2 + Float3, // vec3 + Float4, // vec4 + Mat4x4, // mat4 + Sampler2D, // sampler2D + + Void // void + }; + + enum class IntrinsicType + { + CrossProduct, + DotProduct + }; + + enum class NodeType + { + None = -1, + + AssignOp, + BinaryOp, + Branch, + Cast, + Constant, + ConditionalStatement, + DeclareVariable, + ExpressionStatement, + Identifier, + IntrinsicCall, + Sample2D, + SwizzleOp, + StatementBlock + }; + + enum class SwizzleComponent + { + First, + Second, + Third, + Fourth + }; + + enum class VariableType + { + None = -1, + + BuiltinVariable, + InputVariable, + LocalVariable, + OutputVariable, + ParameterVariable, + UniformVariable + }; +} + +#endif // NAZARA_SHADER_ENUMS_HPP diff --git a/include/Nazara/Renderer/ShaderNodes.hpp b/include/Nazara/Renderer/ShaderNodes.hpp new file mode 100644 index 000000000..d6bafc911 --- /dev/null +++ b/include/Nazara/Renderer/ShaderNodes.hpp @@ -0,0 +1,272 @@ +// 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_SHADER_NODES_HPP +#define NAZARA_SHADER_NODES_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class ShaderVisitor; + + namespace ShaderNodes + { + class Node; + + using NodePtr = std::shared_ptr; + + class NAZARA_RENDERER_API Node + { + public: + virtual ~Node(); + + inline NodeType GetType() const; + + virtual void Visit(ShaderVisitor& visitor) = 0; + + static inline unsigned int GetComponentCount(ExpressionType type); + static inline ExpressionType GetComponentType(ExpressionType type); + + protected: + inline Node(NodeType type); + + private: + NodeType m_type; + }; + + class Statement; + + using StatementPtr = std::shared_ptr; + + class NAZARA_RENDERER_API Statement : public Node + { + public: + using Node::Node; + }; + + class Expression; + + using ExpressionPtr = std::shared_ptr; + + class NAZARA_RENDERER_API Expression : public Node + { + public: + using Node::Node; + + virtual ExpressionCategory GetExpressionCategory() const; + virtual ExpressionType GetExpressionType() const = 0; + }; + + struct NAZARA_RENDERER_API ExpressionStatement : public Statement + { + inline ExpressionStatement(); + + void Visit(ShaderVisitor& visitor) override; + + ExpressionPtr expression; + + static inline std::shared_ptr Build(ExpressionPtr expr); + }; + + ////////////////////////////////////////////////////////////////////////// + + struct NAZARA_RENDERER_API ConditionalStatement : public Statement + { + inline ConditionalStatement(); + + void Visit(ShaderVisitor& visitor) override; + + std::string conditionName; + StatementPtr statement; + + static inline std::shared_ptr Build(std::string condition, StatementPtr statementPtr); + }; + + struct NAZARA_RENDERER_API StatementBlock : public Statement + { + inline StatementBlock(); + + void Visit(ShaderVisitor& visitor) override; + + std::vector statements; + + template static std::shared_ptr Build(Args&&... args); + }; + + struct NAZARA_RENDERER_API DeclareVariable : public Statement + { + inline DeclareVariable(); + + void Visit(ShaderVisitor& visitor) override; + + LocalVariablePtr variable; + ExpressionPtr expression; + + static inline std::shared_ptr Build(LocalVariablePtr variable, ExpressionPtr expression = nullptr); + }; + + struct NAZARA_RENDERER_API Identifier : public Expression + { + inline Identifier(); + + ExpressionCategory GetExpressionCategory() const override; + ExpressionType GetExpressionType() const override; + void Visit(ShaderVisitor& visitor) override; + + VariablePtr var; + + static inline std::shared_ptr Build(VariablePtr variable); + }; + + ////////////////////////////////////////////////////////////////////////// + + struct NAZARA_RENDERER_API AssignOp : public Expression + { + inline AssignOp(); + + ExpressionType GetExpressionType() const override; + void Visit(ShaderVisitor& visitor) override; + + AssignType op; + ExpressionPtr left; + ExpressionPtr right; + + static inline std::shared_ptr Build(AssignType op, ExpressionPtr left, ExpressionPtr right); + }; + + struct NAZARA_RENDERER_API BinaryOp : public Expression + { + inline BinaryOp(); + + ExpressionType GetExpressionType() const override; + void Visit(ShaderVisitor& visitor) override; + + BinaryType op; + ExpressionPtr left; + ExpressionPtr right; + + static inline std::shared_ptr Build(BinaryType op, ExpressionPtr left, ExpressionPtr right); + }; + + struct NAZARA_RENDERER_API Branch : public Statement + { + struct ConditionalStatement; + + inline Branch(); + + void Visit(ShaderVisitor& visitor) override; + + std::vector condStatements; + StatementPtr elseStatement; + + struct ConditionalStatement + { + ExpressionPtr condition; + StatementPtr statement; + }; + + inline std::shared_ptr Build(ExpressionPtr condition, StatementPtr trueStatement, StatementPtr falseStatement = nullptr); + }; + + struct NAZARA_RENDERER_API Cast : public Expression + { + inline Cast(); + + ExpressionType GetExpressionType() const override; + void Visit(ShaderVisitor& visitor) override; + + ExpressionType exprType; + std::array expressions; + + static inline std::shared_ptr Build(ExpressionType castTo, ExpressionPtr first, ExpressionPtr second = nullptr, ExpressionPtr third = nullptr, ExpressionPtr fourth = nullptr); + static inline std::shared_ptr Build(ExpressionType castTo, ExpressionPtr* expressions, std::size_t expressionCount); + }; + + struct NAZARA_RENDERER_API Constant : public Expression + { + inline Constant(); + + ExpressionType GetExpressionType() const override; + void Visit(ShaderVisitor& visitor) override; + + ExpressionType exprType; + + union + { + bool bool1; + float vec1; + Vector2f vec2; + Vector3f vec3; + Vector4f vec4; + } values; + + static inline std::shared_ptr Build(bool value); + static inline std::shared_ptr Build(float value); + static inline std::shared_ptr Build(const Vector2f& value); + static inline std::shared_ptr Build(const Vector3f& value); + static inline std::shared_ptr Build(const Vector4f& value); + }; + + struct NAZARA_RENDERER_API SwizzleOp : public Expression + { + inline SwizzleOp(); + + ExpressionCategory GetExpressionCategory() const override; + ExpressionType GetExpressionType() const override; + void Visit(ShaderVisitor& visitor) override; + + std::array components; + std::size_t componentCount; + ExpressionPtr expression; + + static inline std::shared_ptr Build(ExpressionPtr expressionPtr, std::initializer_list swizzleComponents); + }; + + ////////////////////////////////////////////////////////////////////////// + + struct NAZARA_RENDERER_API Sample2D : public Expression + { + inline Sample2D(); + + ExpressionType GetExpressionType() const override; + void Visit(ShaderVisitor& visitor) override; + + ExpressionPtr sampler; + ExpressionPtr coordinates; + + static inline std::shared_ptr Build(ExpressionPtr samplerPtr, ExpressionPtr coordinatesPtr); + }; + + ////////////////////////////////////////////////////////////////////////// + + struct NAZARA_RENDERER_API IntrinsicCall : public Expression + { + inline IntrinsicCall(); + + ExpressionType GetExpressionType() const override; + void Visit(ShaderVisitor& visitor) override; + + IntrinsicType intrinsic; + std::vector parameters; + + static inline std::shared_ptr Build(IntrinsicType intrinsic, std::vector parameters); + }; + } +} + +#include + +#endif diff --git a/include/Nazara/Renderer/ShaderNodes.inl b/include/Nazara/Renderer/ShaderNodes.inl new file mode 100644 index 000000000..1bcf4effa --- /dev/null +++ b/include/Nazara/Renderer/ShaderNodes.inl @@ -0,0 +1,300 @@ +// 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 + +#include +#include + +namespace Nz::ShaderNodes +{ + inline Node::Node(NodeType type) : + m_type(type) + { + } + + inline NodeType ShaderNodes::Node::GetType() const + { + return m_type; + } + + inline unsigned int Node::GetComponentCount(ExpressionType type) + { + switch (type) + { + case ExpressionType::Float2: + return 2; + + case ExpressionType::Float3: + return 3; + + case ExpressionType::Float4: + return 4; + + case ExpressionType::Mat4x4: + return 4; + + default: + return 1; + } + } + + inline ExpressionType Node::GetComponentType(ExpressionType type) + { + switch (type) + { + case ExpressionType::Float2: + case ExpressionType::Float3: + case ExpressionType::Float4: + return ExpressionType::Float1; + + case ExpressionType::Mat4x4: + return ExpressionType::Float4; + + default: + return type; + } + } + + inline ExpressionStatement::ExpressionStatement() : + Statement(NodeType::ExpressionStatement) + { + } + + inline std::shared_ptr ExpressionStatement::Build(ExpressionPtr expr) + { + auto node = std::make_shared(); + node->expression = std::move(expr); + + return node; + } + + inline ConditionalStatement::ConditionalStatement() : + Statement(NodeType::ConditionalStatement) + { + } + + inline std::shared_ptr ConditionalStatement::Build(std::string condition, StatementPtr statementPtr) + { + auto node = std::make_shared(); + node->conditionName = std::move(condition); + node->statement = std::move(statementPtr); + + return node; + } + + + inline StatementBlock::StatementBlock() : + Statement(NodeType::StatementBlock) + { + } + + template + std::shared_ptr StatementBlock::Build(Args&&... args) + { + auto node = std::make_shared(); + node->statements = std::vector({ std::forward(args)... }); + + return node; + } + + + inline DeclareVariable::DeclareVariable() : + Statement(NodeType::DeclareVariable) + { + } + + inline std::shared_ptr DeclareVariable::Build(LocalVariablePtr variable, ExpressionPtr expression) + { + auto node = std::make_shared(); + node->expression = std::move(expression); + node->variable = std::move(variable); + + return node; + } + + + inline Identifier::Identifier() : + Expression(NodeType::Identifier) + { + } + + inline std::shared_ptr Identifier::Build(VariablePtr variable) + { + auto node = std::make_shared(); + node->var = std::move(variable); + + return node; + } + + + inline AssignOp::AssignOp() : + Expression(NodeType::AssignOp) + { + } + + inline std::shared_ptr AssignOp::Build(AssignType op, ExpressionPtr left, ExpressionPtr right) + { + auto node = std::make_shared(); + node->op = op; + node->left = std::move(left); + node->right = std::move(right); + + return node; + } + + + inline BinaryOp::BinaryOp() : + Expression(NodeType::BinaryOp) + { + } + + inline std::shared_ptr BinaryOp::Build(BinaryType op, ExpressionPtr left, ExpressionPtr right) + { + auto node = std::make_shared(); + node->op = op; + node->left = std::move(left); + node->right = std::move(right); + + return node; + } + + + inline Branch::Branch() : + Statement(NodeType::Branch) + { + } + + inline std::shared_ptr Branch::Build(ExpressionPtr condition, StatementPtr trueStatement, StatementPtr falseStatement) + { + auto node = std::make_shared(); + node->condStatements.emplace_back(ConditionalStatement{ std::move(condition), std::move(trueStatement) }); + node->elseStatement = std::move(falseStatement); + + return node; + } + + + inline Cast::Cast() : + Expression(NodeType::Cast) + { + } + + inline std::shared_ptr Cast::Build(ExpressionType castTo, ExpressionPtr first, ExpressionPtr second, ExpressionPtr third, ExpressionPtr fourth) + { + auto node = std::make_shared(); + node->exprType = castTo; + node->expressions = { {first, second, third, fourth} }; + + return node; + } + + inline std::shared_ptr Cast::Build(ExpressionType castTo, ExpressionPtr* Expressions, std::size_t expressionCount) + { + auto node = std::make_shared(); + node->exprType = castTo; + for (std::size_t i = 0; i < expressionCount; ++i) + node->expressions[i] = Expressions[i]; + + return node; + } + + + inline Constant::Constant() : + Expression(NodeType::Constant) + { + } + + inline std::shared_ptr Constant::Build(bool value) + { + auto node = std::make_shared(); + node->exprType = ExpressionType::Boolean; + node->values.bool1 = value; + + return node; + } + + inline std::shared_ptr Constant::Build(float value) + { + auto node = std::make_shared(); + node->exprType = ExpressionType::Float1; + node->values.vec1 = value; + + return node; + } + + inline std::shared_ptr Constant::Build(const Vector2f& value) + { + auto node = std::make_shared(); + node->exprType = ExpressionType::Float2; + node->values.vec2 = value; + + return node; + } + + inline std::shared_ptr Constant::Build(const Vector3f& value) + { + auto node = std::make_shared(); + node->exprType = ExpressionType::Float3; + node->values.vec3 = value; + + return node; + } + + inline std::shared_ptr Constant::Build(const Vector4f& value) + { + auto node = std::make_shared(); + node->exprType = ExpressionType::Float4; + node->values.vec4 = value; + + return node; + } + + + inline SwizzleOp::SwizzleOp() : + Expression(NodeType::SwizzleOp) + { + } + + inline std::shared_ptr SwizzleOp::Build(ExpressionPtr expressionPtr, std::initializer_list swizzleComponents) + { + auto node = std::make_shared(); + node->componentCount = swizzleComponents.size(); + node->expression = std::move(expressionPtr); + + std::copy(swizzleComponents.begin(), swizzleComponents.end(), node->components.begin()); + + return node; + } + + + inline Sample2D::Sample2D() : + Expression(NodeType::Sample2D) + { + } + + inline std::shared_ptr Sample2D::Build(ExpressionPtr samplerPtr, ExpressionPtr coordinatesPtr) + { + auto node = std::make_shared(); + node->coordinates = std::move(coordinatesPtr); + node->sampler = std::move(samplerPtr); + + return node; + } + + + inline IntrinsicCall::IntrinsicCall() : + Expression(NodeType::IntrinsicCall) + { + } + + inline std::shared_ptr IntrinsicCall::Build(IntrinsicType intrinsic, std::vector parameters) + { + auto node = std::make_shared(); + node->intrinsic = intrinsic; + node->parameters = std::move(parameters); + + return node; + } +} + +#include diff --git a/include/Nazara/Renderer/ShaderSerializer.hpp b/include/Nazara/Renderer/ShaderSerializer.hpp index 521284370..daeb13e73 100644 --- a/include/Nazara/Renderer/ShaderSerializer.hpp +++ b/include/Nazara/Renderer/ShaderSerializer.hpp @@ -11,9 +11,10 @@ #include #include #include -#include +#include +#include -namespace Nz::ShaderAst +namespace Nz::ShaderNodes { class NAZARA_RENDERER_API ShaderSerializerBase { @@ -24,15 +25,16 @@ namespace Nz::ShaderAst ~ShaderSerializerBase() = default; void Serialize(AssignOp& node); - void Serialize(BinaryFunc& node); void Serialize(BinaryOp& node); + void Serialize(BuiltinVariable& var); void Serialize(Branch& node); - void Serialize(BuiltinVariable& node); void Serialize(Cast& node); void Serialize(Constant& node); void Serialize(DeclareVariable& node); void Serialize(ExpressionStatement& node); - void Serialize(NamedVariable& node); + void Serialize(Identifier& node); + void Serialize(IntrinsicCall& node); + void Serialize(NamedVariable& var); void Serialize(Sample2D& node); void Serialize(StatementBlock& node); void Serialize(SwizzleOp& node); @@ -54,6 +56,9 @@ namespace Nz::ShaderAst virtual void Value(Vector4f& val) = 0; virtual void Value(UInt32& val) = 0; inline void Value(std::size_t& val); + + virtual void Variable(VariablePtr& var) = 0; + template void Variable(std::shared_ptr& var); }; class NAZARA_RENDERER_API ShaderSerializer final : public ShaderSerializerBase @@ -74,6 +79,7 @@ namespace Nz::ShaderAst void Value(Vector3f& val) override; void Value(Vector4f& val) override; void Value(UInt32& val) override; + void Variable(VariablePtr& var) override; ByteArray& m_byteArray; ByteStream m_stream; @@ -89,7 +95,7 @@ namespace Nz::ShaderAst private: bool IsWriting() const override; - void Node(NodePtr & node) override; + void Node(NodePtr& node) override; void Value(bool& val) override; void Value(float& val) override; void Value(std::string& val) override; @@ -97,6 +103,7 @@ namespace Nz::ShaderAst void Value(Vector3f& val) override; void Value(Vector4f& val) override; void Value(UInt32& val) override; + void Variable(VariablePtr& var) override; const ByteArray& m_byteArray; ByteStream m_stream; diff --git a/include/Nazara/Renderer/ShaderSerializer.inl b/include/Nazara/Renderer/ShaderSerializer.inl index 2d8f5bc85..354986bb1 100644 --- a/include/Nazara/Renderer/ShaderSerializer.inl +++ b/include/Nazara/Renderer/ShaderSerializer.inl @@ -5,7 +5,7 @@ #include #include -namespace Nz::ShaderAst +namespace Nz::ShaderNodes { template void ShaderSerializerBase::Container(T& container) @@ -37,7 +37,7 @@ namespace Nz::ShaderAst } template - inline void ShaderSerializerBase::Node(std::shared_ptr& node) + void ShaderSerializerBase::Node(std::shared_ptr& node) { bool isWriting = IsWriting(); @@ -50,6 +50,20 @@ namespace Nz::ShaderAst node = std::static_pointer_cast(value); } + template + void ShaderSerializerBase::Variable(std::shared_ptr& var) + { + bool isWriting = IsWriting(); + + VariablePtr value; + if (isWriting) + value = var; + + Variable(value); + if (!isWriting) + var = std::static_pointer_cast(value); + } + inline void ShaderSerializerBase::Value(std::size_t& val) { bool isWriting = IsWriting(); diff --git a/include/Nazara/Renderer/ShaderValidator.hpp b/include/Nazara/Renderer/ShaderValidator.hpp index 50075aaf0..bfdab9844 100644 --- a/include/Nazara/Renderer/ShaderValidator.hpp +++ b/include/Nazara/Renderer/ShaderValidator.hpp @@ -13,40 +13,47 @@ #include #include -namespace Nz::ShaderAst +namespace Nz { + class ShaderAst; + class NAZARA_RENDERER_API ShaderValidator : public ShaderVisitor { public: - ShaderValidator() = default; + inline ShaderValidator(const ShaderAst& shader); ShaderValidator(const ShaderValidator&) = delete; ShaderValidator(ShaderValidator&&) = delete; ~ShaderValidator() = default; - bool Validate(const StatementPtr& shader, std::string* error = nullptr); + bool Validate(std::string* error = nullptr); private: - const ExpressionPtr& MandatoryExpr(const ExpressionPtr& node); - const NodePtr& MandatoryNode(const NodePtr& node); - void TypeMustMatch(const ExpressionPtr& left, const ExpressionPtr& right); + const ShaderNodes::ExpressionPtr& MandatoryExpr(const ShaderNodes::ExpressionPtr& node); + const ShaderNodes::NodePtr& MandatoryNode(const ShaderNodes::NodePtr& node); + void TypeMustMatch(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right); + void TypeMustMatch(ShaderNodes::ExpressionType left, ShaderNodes::ExpressionType right); using ShaderVisitor::Visit; - void Visit(const AssignOp& node) override; - void Visit(const BinaryFunc& node) override; - void Visit(const BinaryOp& node) override; - void Visit(const Branch& node) override; - void Visit(const BuiltinVariable& node) override; - void Visit(const Cast& node) override; - void Visit(const Constant& node) override; - void Visit(const DeclareVariable& node) override; - void Visit(const ExpressionStatement& node) override; - void Visit(const NamedVariable& node) override; - void Visit(const Sample2D& node) override; - void Visit(const StatementBlock& node) override; - void Visit(const SwizzleOp& node) override; + void Visit(const ShaderNodes::AssignOp& node) override; + void Visit(const ShaderNodes::BinaryOp& node) override; + void Visit(const ShaderNodes::Branch& node) override; + void Visit(const ShaderNodes::Cast& node) override; + void Visit(const ShaderNodes::Constant& node) override; + void Visit(const ShaderNodes::DeclareVariable& node) override; + void Visit(const ShaderNodes::ExpressionStatement& node) override; + void Visit(const ShaderNodes::Identifier& node) override; + void Visit(const ShaderNodes::IntrinsicCall& node) override; + void Visit(const ShaderNodes::Sample2D& node) override; + void Visit(const ShaderNodes::StatementBlock& node) override; + void Visit(const ShaderNodes::SwizzleOp& node) override; + + struct Context; + + const ShaderAst& m_shader; + Context* m_context; }; - NAZARA_RENDERER_API bool Validate(const StatementPtr& shader, std::string* error = nullptr); + NAZARA_RENDERER_API bool ValidateShader(const ShaderAst& shader, std::string* error = nullptr); } #include diff --git a/include/Nazara/Renderer/ShaderValidator.inl b/include/Nazara/Renderer/ShaderValidator.inl index 2fb43d576..e609a144a 100644 --- a/include/Nazara/Renderer/ShaderValidator.inl +++ b/include/Nazara/Renderer/ShaderValidator.inl @@ -5,8 +5,12 @@ #include #include -namespace Nz::ShaderAst +namespace Nz { + ShaderValidator::ShaderValidator(const ShaderAst& shader) : + m_shader(shader) + { + } } #include diff --git a/include/Nazara/Renderer/ShaderVarVisitor.hpp b/include/Nazara/Renderer/ShaderVarVisitor.hpp new file mode 100644 index 000000000..6df035d74 --- /dev/null +++ b/include/Nazara/Renderer/ShaderVarVisitor.hpp @@ -0,0 +1,34 @@ +// Copyright (C) 2015 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_SHADERVARVISITOR_HPP +#define NAZARA_SHADERVARVISITOR_HPP + +#include +#include +#include + +namespace Nz +{ + class NAZARA_RENDERER_API ShaderVarVisitor + { + public: + ShaderVarVisitor() = default; + ShaderVarVisitor(const ShaderVarVisitor&) = delete; + ShaderVarVisitor(ShaderVarVisitor&&) = delete; + virtual ~ShaderVarVisitor(); + + virtual void Visit(const ShaderNodes::BuiltinVariable& var) = 0; + virtual void Visit(const ShaderNodes::InputVariable& var) = 0; + virtual void Visit(const ShaderNodes::LocalVariable& var) = 0; + virtual void Visit(const ShaderNodes::OutputVariable& var) = 0; + virtual void Visit(const ShaderNodes::ParameterVariable& var) = 0; + virtual void Visit(const ShaderNodes::UniformVariable& var) = 0; + void Visit(const ShaderNodes::VariablePtr& node); + }; +} + +#endif diff --git a/include/Nazara/Renderer/ShaderVariables.hpp b/include/Nazara/Renderer/ShaderVariables.hpp new file mode 100644 index 000000000..242f129db --- /dev/null +++ b/include/Nazara/Renderer/ShaderVariables.hpp @@ -0,0 +1,127 @@ +// 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_SHADER_VARIABLES_HPP +#define NAZARA_SHADER_VARIABLES_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class ShaderVarVisitor; + + namespace ShaderNodes + { + struct Variable; + + using VariablePtr = std::shared_ptr; + + struct NAZARA_RENDERER_API Variable + { + virtual ~Variable(); + + virtual VariableType GetType() const = 0; + virtual void Visit(ShaderVarVisitor& visitor) = 0; + + ExpressionType type; + }; + + struct BuiltinVariable; + + using BuiltinVariablePtr = std::shared_ptr; + + struct NAZARA_RENDERER_API BuiltinVariable : public Variable + { + BuiltinEntry entry; + + VariableType GetType() const override; + void Visit(ShaderVarVisitor& visitor) override; + + static inline std::shared_ptr Build(BuiltinEntry entry, ExpressionType varType); + }; + + struct NamedVariable; + + using NamedVariablePtr = std::shared_ptr; + + struct NAZARA_RENDERER_API NamedVariable : public Variable + { + std::string name; + }; + + struct InputVariable; + + using InputVariablePtr = std::shared_ptr; + + struct NAZARA_RENDERER_API InputVariable : public NamedVariable + { + VariableType GetType() const override; + void Visit(ShaderVarVisitor& visitor) override; + + static inline std::shared_ptr Build(std::string varName, ExpressionType varType); + }; + + struct LocalVariable; + + using LocalVariablePtr = std::shared_ptr; + + struct NAZARA_RENDERER_API LocalVariable : public NamedVariable + { + VariableType GetType() const override; + void Visit(ShaderVarVisitor& visitor) override; + + static inline std::shared_ptr Build(std::string varName, ExpressionType varType); + }; + + struct OutputVariable; + + using OutputVariablePtr = std::shared_ptr; + + struct NAZARA_RENDERER_API OutputVariable : public NamedVariable + { + VariableType GetType() const override; + void Visit(ShaderVarVisitor& visitor) override; + + static inline std::shared_ptr Build(std::string varName, ExpressionType varType); + }; + + struct ParameterVariable; + + using ParameterVariablePtr = std::shared_ptr; + + struct NAZARA_RENDERER_API ParameterVariable : public NamedVariable + { + VariableType GetType() const override; + void Visit(ShaderVarVisitor& visitor) override; + + static inline std::shared_ptr Build(std::string varName, ExpressionType varType); + }; + + struct UniformVariable; + + using UniformVariablePtr = std::shared_ptr; + + struct NAZARA_RENDERER_API UniformVariable : public NamedVariable + { + VariableType GetType() const override; + void Visit(ShaderVarVisitor& visitor) override; + + static inline std::shared_ptr Build(std::string varName, ExpressionType varType); + }; + } +} + +#include + +#endif diff --git a/include/Nazara/Renderer/ShaderVariables.inl b/include/Nazara/Renderer/ShaderVariables.inl new file mode 100644 index 000000000..d20c9d6ea --- /dev/null +++ b/include/Nazara/Renderer/ShaderVariables.inl @@ -0,0 +1,65 @@ +// 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 + +#include +#include + +namespace Nz::ShaderNodes +{ + inline std::shared_ptr BuiltinVariable::Build(BuiltinEntry variable, ExpressionType varType) + { + auto node = std::make_shared(); + node->entry = variable; + node->type = varType; + + return node; + } + + inline std::shared_ptr InputVariable::Build(std::string varName, ExpressionType varType) + { + auto node = std::make_shared(); + node->name = std::move(varName); + node->type = varType; + + return node; + } + + inline std::shared_ptr LocalVariable::Build(std::string varName, ExpressionType varType) + { + auto node = std::make_shared(); + node->name = std::move(varName); + node->type = varType; + + return node; + } + + inline std::shared_ptr OutputVariable::Build(std::string varName, ExpressionType varType) + { + auto node = std::make_shared(); + node->name = std::move(varName); + node->type = varType; + + return node; + } + + inline std::shared_ptr ParameterVariable::Build(std::string varName, ExpressionType varType) + { + auto node = std::make_shared(); + node->name = std::move(varName); + node->type = varType; + + return node; + } + + inline std::shared_ptr UniformVariable::Build(std::string varName, ExpressionType varType) + { + auto node = std::make_shared(); + node->name = std::move(varName); + node->type = varType; + + return node; + } +} + +#include diff --git a/include/Nazara/Renderer/ShaderVisitor.hpp b/include/Nazara/Renderer/ShaderVisitor.hpp index 47a5741f4..9db22882c 100644 --- a/include/Nazara/Renderer/ShaderVisitor.hpp +++ b/include/Nazara/Renderer/ShaderVisitor.hpp @@ -8,9 +8,9 @@ #define NAZARA_SHADERVISITOR_HPP #include -#include #include -#include +#include +#include #include namespace Nz @@ -23,27 +23,26 @@ namespace Nz ShaderVisitor(ShaderVisitor&&) = delete; virtual ~ShaderVisitor(); - void EnableCondition(const String& name, bool cond); + void EnableCondition(const std::string& name, bool cond); - bool IsConditionEnabled(const String& name) const; + bool IsConditionEnabled(const std::string& name) const; - virtual void Visit(const ShaderAst::AssignOp& node) = 0; - virtual void Visit(const ShaderAst::BinaryFunc& node) = 0; - virtual void Visit(const ShaderAst::BinaryOp& node) = 0; - virtual void Visit(const ShaderAst::Branch& node) = 0; - virtual void Visit(const ShaderAst::BuiltinVariable& node) = 0; - virtual void Visit(const ShaderAst::Cast& node) = 0; - virtual void Visit(const ShaderAst::Constant& node) = 0; - virtual void Visit(const ShaderAst::DeclareVariable& node) = 0; - virtual void Visit(const ShaderAst::ExpressionStatement& node) = 0; - virtual void Visit(const ShaderAst::NamedVariable& node) = 0; - void Visit(const ShaderAst::NodePtr& node); - virtual void Visit(const ShaderAst::Sample2D& node) = 0; - virtual void Visit(const ShaderAst::StatementBlock& node) = 0; - virtual void Visit(const ShaderAst::SwizzleOp& node) = 0; + virtual void Visit(const ShaderNodes::AssignOp& node) = 0; + virtual void Visit(const ShaderNodes::BinaryOp& node) = 0; + virtual void Visit(const ShaderNodes::Branch& node) = 0; + virtual void Visit(const ShaderNodes::Cast& node) = 0; + virtual void Visit(const ShaderNodes::Constant& node) = 0; + virtual void Visit(const ShaderNodes::DeclareVariable& node) = 0; + virtual void Visit(const ShaderNodes::ExpressionStatement& node) = 0; + virtual void Visit(const ShaderNodes::Identifier& node) = 0; + virtual void Visit(const ShaderNodes::IntrinsicCall& node) = 0; + void Visit(const ShaderNodes::NodePtr& node); + virtual void Visit(const ShaderNodes::Sample2D& node) = 0; + virtual void Visit(const ShaderNodes::StatementBlock& node) = 0; + virtual void Visit(const ShaderNodes::SwizzleOp& node) = 0; private: - std::unordered_set m_conditions; + std::unordered_set m_conditions; }; } diff --git a/include/Nazara/Renderer/ShaderWriter.hpp b/include/Nazara/Renderer/ShaderWriter.hpp index ae00f2fa5..6c2655226 100644 --- a/include/Nazara/Renderer/ShaderWriter.hpp +++ b/include/Nazara/Renderer/ShaderWriter.hpp @@ -8,24 +8,22 @@ #define NAZARA_SHADERWRITER_HPP #include -#include #include -#include +#include namespace Nz { - class NAZARA_RENDERER_API ShaderWriter : public ShaderVisitor + class ShaderAst; + + class NAZARA_RENDERER_API ShaderWriter { public: ShaderWriter() = default; ShaderWriter(const ShaderWriter&) = delete; ShaderWriter(ShaderWriter&&) = delete; - ~ShaderWriter() = default; + virtual ~ShaderWriter(); - virtual Nz::String Generate(const ShaderAst::StatementPtr& node) = 0; - - virtual void RegisterFunction(const String& name, ShaderAst::StatementPtr node, std::initializer_list parameters, ShaderAst::ExpressionType ret) = 0; - virtual void RegisterVariable(ShaderAst::VariableType kind, const String& name, ShaderAst::ExpressionType type) = 0; + virtual std::string Generate(const ShaderAst& shader) = 0; }; } diff --git a/src/Nazara/Renderer/GlslWriter.cpp b/src/Nazara/Renderer/GlslWriter.cpp index b982dab90..8d8e024e7 100644 --- a/src/Nazara/Renderer/GlslWriter.cpp +++ b/src/Nazara/Renderer/GlslWriter.cpp @@ -11,16 +11,15 @@ namespace Nz { GlslWriter::GlslWriter() : - m_currentFunction(nullptr), m_currentState(nullptr), m_glslVersion(110) { } - String GlslWriter::Generate(const ShaderAst::StatementPtr& node) + std::string GlslWriter::Generate(const ShaderAst& shader) { std::string error; - if (!ShaderAst::Validate(node, &error)) + if (!ValidateShader(shader, &error)) throw std::runtime_error("Invalid shader AST: " + error); State state; @@ -30,91 +29,54 @@ namespace Nz m_currentState = nullptr; }); - // Register global variables (uniforms, varying, ..) - node->Register(*this); - // Header Append("#version "); - AppendLine(String::Number(m_glslVersion)); + AppendLine(std::to_string(m_glslVersion)); AppendLine(); - // Global variables (uniforms, input and outputs) - DeclareVariables(state.uniforms, "uniform", "Uniforms"); - DeclareVariables(state.inputs, "in", "Inputs"); - DeclareVariables(state.outputs, "out", "Outputs"); + // Extensions - Function entryPoint; - entryPoint.name = "main"; //< GLSL has only one entry point name possible - entryPoint.node = node; - entryPoint.retType = ShaderAst::ExpressionType::Void; + std::vector requiredExtensions; - AppendFunction(entryPoint); + // GL_ARB_shading_language_420pack (required for layout(binding = X)) + if (m_glslVersion < 420 && HasExplicitBinding(shader)) + requiredExtensions.emplace_back("GL_ARB_shading_language_420pack"); - return state.stream; - } + // GL_ARB_explicit_uniform_location (required for layout(location = X)) + if (m_glslVersion < 430 && HasExplicitLocation(shader)) + requiredExtensions.emplace_back("GL_ARB_explicit_uniform_location"); - void GlslWriter::RegisterFunction(const String& name, ShaderAst::StatementPtr statement, std::initializer_list parameters, ShaderAst::ExpressionType retType) - { - Function func; - func.retType = retType; - func.name = name; - func.node = std::move(statement); - func.parameters.assign(parameters); - - m_functions[name] = std::move(func); - } - - void GlslWriter::RegisterVariable(ShaderAst::VariableType kind, const String& name, ShaderAst::ExpressionType type) - { - NazaraAssert(m_currentState, "This function should only be called while processing an AST"); - NazaraAssert(kind != ShaderAst::VariableType::Builtin, "Builtin variables should not be registered"); - - switch (kind) + if (!requiredExtensions.empty()) { - case ShaderAst::VariableType::Builtin: //< Only there to make compiler happy - case ShaderAst::VariableType::Variable: - break; + for (const std::string& ext : requiredExtensions) + AppendLine("#extension " + ext + " : require"); - case ShaderAst::VariableType::Input: - m_currentState->inputs.emplace(type, name); - break; - - case ShaderAst::VariableType::Output: - m_currentState->outputs.emplace(type, name); - break; - - case ShaderAst::VariableType::Parameter: - { - if (m_currentFunction) - { - bool found = false; - for (const auto& varPtr : m_currentFunction->parameters) - { - if (varPtr->name == name) - { - found = true; - if (varPtr->type != type) - { - //TODO: AstParseError - throw std::runtime_error("Function uses parameter \"" + name.ToStdString() + "\" with a different type than specified in the function arguments"); - } - - break; - } - } - - if (!found) - //TODO: AstParseError - throw std::runtime_error("Function has no parameter \"" + name.ToStdString() + "\""); - } - - break; - } - - case ShaderAst::VariableType::Uniform: - m_currentState->uniforms.emplace(type, name); - break; + AppendLine(); } + + // Global variables (uniforms, input and outputs) + DeclareVariables(shader.GetUniforms(), "uniform", "Uniforms"); + DeclareVariables(shader.GetInputs(), "in", "Inputs"); + DeclareVariables(shader.GetOutputs(), "out", "Outputs"); + + std::size_t functionCount = shader.GetFunctionCount(); + if (functionCount > 1) + { + AppendCommentSection("Prototypes"); + for (const auto& func : shader.GetFunctions()) + { + if (func.name != "main") + { + AppendFunctionPrototype(func); + AppendLine(";"); + } + } + } + + for (const auto& func : shader.GetFunctions()) + AppendFunction(func); + + return state.stream.str(); } void GlslWriter::SetGlslVersion(unsigned int version) @@ -122,22 +84,127 @@ namespace Nz m_glslVersion = version; } - void GlslWriter::Visit(const ShaderAst::Sample2D& node) + void GlslWriter::Append(ShaderNodes::BuiltinEntry builtin) { - Append("texture("); - Visit(node.sampler); - Append(", "); - Visit(node.coordinates); - Append(")"); + switch (builtin) + { + case ShaderNodes::BuiltinEntry::VertexPosition: + Append("gl_Position"); + break; + } } - void GlslWriter::Visit(const ShaderAst::AssignOp& node) + void GlslWriter::Append(ShaderNodes::ExpressionType type) + { + switch (type) + { + case ShaderNodes::ExpressionType::Boolean: + Append("bool"); + break; + case ShaderNodes::ExpressionType::Float1: + Append("float"); + break; + case ShaderNodes::ExpressionType::Float2: + Append("vec2"); + break; + case ShaderNodes::ExpressionType::Float3: + Append("vec3"); + break; + case ShaderNodes::ExpressionType::Float4: + Append("vec4"); + break; + case ShaderNodes::ExpressionType::Mat4x4: + Append("mat4"); + break; + case ShaderNodes::ExpressionType::Sampler2D: + Append("sampler2D"); + break; + case ShaderNodes::ExpressionType::Void: + Append("void"); + break; + } + } + + void GlslWriter::AppendCommentSection(const std::string& section) + { + NazaraAssert(m_currentState, "This function should only be called while processing an AST"); + + String stars((section.size() < 33) ? (36 - section.size()) / 2 : 3, '*'); + m_currentState->stream << "/*" << stars << ' ' << section << ' ' << stars << "*/"; + AppendLine(); + } + + void GlslWriter::AppendFunction(const ShaderAst::Function& func) + { + NazaraAssert(!m_context.currentFunction, "A function is already being processed"); + NazaraAssert(m_currentState, "This function should only be called while processing an AST"); + + AppendFunctionPrototype(func); + + m_context.currentFunction = &func; + CallOnExit onExit([this] () + { + m_context.currentFunction = nullptr; + }); + + EnterScope(); + { + Visit(func.statement); + } + LeaveScope(); + } + + void GlslWriter::AppendFunctionPrototype(const ShaderAst::Function& func) + { + Append(func.returnType); + + Append(" "); + Append(func.name); + + Append("("); + for (std::size_t i = 0; i < func.parameters.size(); ++i) + { + if (i != 0) + Append(", "); + + Append(func.parameters[i].type); + Append(" "); + Append(func.parameters[i].name); + } + Append(")\n"); + } + + void GlslWriter::AppendLine(const std::string& txt) + { + NazaraAssert(m_currentState, "This function should only be called while processing an AST"); + + m_currentState->stream << txt << '\n' << std::string(m_currentState->indentLevel, '\t'); + } + + void GlslWriter::EnterScope() + { + NazaraAssert(m_currentState, "This function should only be called while processing an AST"); + + m_currentState->indentLevel++; + AppendLine("{"); + } + + void GlslWriter::LeaveScope() + { + NazaraAssert(m_currentState, "This function should only be called while processing an AST"); + + m_currentState->indentLevel--; + AppendLine(); + AppendLine("}"); + } + + void GlslWriter::Visit(const ShaderNodes::AssignOp& node) { Visit(node.left); switch (node.op) { - case ShaderAst::AssignType::Simple: + case ShaderNodes::AssignType::Simple: Append(" = "); break; } @@ -145,7 +212,7 @@ namespace Nz Visit(node.right); } - void GlslWriter::Visit(const ShaderAst::Branch& node) + void GlslWriter::Visit(const ShaderNodes::Branch& node) { bool first = true; for (const auto& statement : node.condStatements) @@ -174,45 +241,25 @@ namespace Nz } } - void GlslWriter::Visit(const ShaderAst::BinaryFunc& node) - { - switch (node.intrinsic) - { - case ShaderAst::BinaryIntrinsic::CrossProduct: - Append("cross"); - break; - - case ShaderAst::BinaryIntrinsic::DotProduct: - Append("dot"); - break; - } - - Append("("); - Visit(node.left); - Append(", "); - Visit(node.right); - Append(")"); - } - - void GlslWriter::Visit(const ShaderAst::BinaryOp& node) + void GlslWriter::Visit(const ShaderNodes::BinaryOp& node) { Visit(node.left); switch (node.op) { - case ShaderAst::BinaryType::Add: + case ShaderNodes::BinaryType::Add: Append(" + "); break; - case ShaderAst::BinaryType::Substract: + case ShaderNodes::BinaryType::Substract: Append(" - "); break; - case ShaderAst::BinaryType::Multiply: + case ShaderNodes::BinaryType::Multiply: Append(" * "); break; - case ShaderAst::BinaryType::Divide: + case ShaderNodes::BinaryType::Divide: Append(" / "); break; - case ShaderAst::BinaryType::Equality: + case ShaderNodes::BinaryType::Equality: Append(" == "); break; } @@ -220,18 +267,18 @@ namespace Nz Visit(node.right); } - void GlslWriter::Visit(const ShaderAst::BuiltinVariable& node) + void GlslWriter::Visit(const ShaderNodes::BuiltinVariable& var) { - Append(node.var); + Append(var.type); } - void GlslWriter::Visit(const ShaderAst::Cast& node) + void GlslWriter::Visit(const ShaderNodes::Cast& node) { Append(node.exprType); Append("("); unsigned int i = 0; - unsigned int requiredComponents = ShaderAst::Node::GetComponentCount(node.exprType); + unsigned int requiredComponents = ShaderNodes::Node::GetComponentCount(node.exprType); while (requiredComponents > 0) { if (i != 0) @@ -241,34 +288,34 @@ namespace Nz NazaraAssert(exprPtr, "Invalid expression"); Visit(exprPtr); - requiredComponents -= ShaderAst::Node::GetComponentCount(exprPtr->GetExpressionType()); + requiredComponents -= ShaderNodes::Node::GetComponentCount(exprPtr->GetExpressionType()); } Append(")"); } - void GlslWriter::Visit(const ShaderAst::Constant& node) + void GlslWriter::Visit(const ShaderNodes::Constant& node) { switch (node.exprType) { - case ShaderAst::ExpressionType::Boolean: + case ShaderNodes::ExpressionType::Boolean: Append((node.values.bool1) ? "true" : "false"); break; - case ShaderAst::ExpressionType::Float1: - Append(String::Number(node.values.vec1)); + case ShaderNodes::ExpressionType::Float1: + Append(std::to_string(node.values.vec1)); break; - case ShaderAst::ExpressionType::Float2: - Append("vec2(" + String::Number(node.values.vec2.x) + ", " + String::Number(node.values.vec2.y) + ")"); + case ShaderNodes::ExpressionType::Float2: + Append("vec2(" + std::to_string(node.values.vec2.x) + ", " + std::to_string(node.values.vec2.y) + ")"); break; - case ShaderAst::ExpressionType::Float3: - Append("vec3(" + String::Number(node.values.vec3.x) + ", " + String::Number(node.values.vec3.y) + ", " + String::Number(node.values.vec3.z) + ")"); + case ShaderNodes::ExpressionType::Float3: + Append("vec3(" + std::to_string(node.values.vec3.x) + ", " + std::to_string(node.values.vec3.y) + ", " + std::to_string(node.values.vec3.z) + ")"); break; - case ShaderAst::ExpressionType::Float4: - Append("vec4(" + String::Number(node.values.vec4.x) + ", " + String::Number(node.values.vec4.y) + ", " + String::Number(node.values.vec4.z) + ", " + String::Number(node.values.vec4.w) + ")"); + case ShaderNodes::ExpressionType::Float4: + Append("vec4(" + std::to_string(node.values.vec4.x) + ", " + std::to_string(node.values.vec4.y) + ", " + std::to_string(node.values.vec4.z) + ", " + std::to_string(node.values.vec4.w) + ")"); break; default: @@ -276,9 +323,9 @@ namespace Nz } } - void GlslWriter::Visit(const ShaderAst::DeclareVariable& node) + void GlslWriter::Visit(const ShaderNodes::DeclareVariable& node) { - Append(node.variable->GetExpressionType()); + Append(node.variable->type); Append(" "); Append(node.variable->name); if (node.expression) @@ -292,21 +339,76 @@ namespace Nz AppendLine(";"); } - void GlslWriter::Visit(const ShaderAst::ExpressionStatement& node) + void GlslWriter::Visit(const ShaderNodes::ExpressionStatement& node) { Visit(node.expression); Append(";"); } - void GlslWriter::Visit(const ShaderAst::NamedVariable& node) + void GlslWriter::Visit(const ShaderNodes::Identifier& node) { - Append(node.name); + Visit(node.var); } - void GlslWriter::Visit(const ShaderAst::StatementBlock& node) + void GlslWriter::Visit(const ShaderNodes::InputVariable& var) + { + Append(var.name); + } + + void GlslWriter::Visit(const ShaderNodes::IntrinsicCall& node) + { + switch (node.intrinsic) + { + case ShaderNodes::IntrinsicType::CrossProduct: + Append("cross"); + break; + + case ShaderNodes::IntrinsicType::DotProduct: + Append("dot"); + break; + } + + m_currentState->stream << '('; + for (std::size_t i = 0; i < node.parameters.size(); ++i) + { + if (i != 0) + m_currentState->stream << ", "; + + Visit(node.parameters[i]); + m_currentState->stream << ' '; + Visit(node.parameters[i]); + } + m_currentState->stream << ")\n"; + } + + void GlslWriter::Visit(const ShaderNodes::LocalVariable& var) + { + Append(var.name); + } + + void GlslWriter::Visit(const ShaderNodes::ParameterVariable& var) + { + Append(var.name); + } + + void GlslWriter::Visit(const ShaderNodes::OutputVariable& var) + { + Append(var.name); + } + + void GlslWriter::Visit(const ShaderNodes::Sample2D& node) + { + Append("texture("); + Visit(node.sampler); + Append(", "); + Visit(node.coordinates); + Append(")"); + } + + void GlslWriter::Visit(const ShaderNodes::StatementBlock& node) { bool first = true; - for (const ShaderAst::StatementPtr& statement : node.statements) + for (const ShaderNodes::StatementPtr& statement : node.statements) { if (!first) AppendLine(); @@ -317,7 +419,7 @@ namespace Nz } } - void GlslWriter::Visit(const ShaderAst::SwizzleOp& node) + void GlslWriter::Visit(const ShaderNodes::SwizzleOp& node) { Visit(node.expression); Append("."); @@ -326,166 +428,55 @@ namespace Nz { switch (node.components[i]) { - case ShaderAst::SwizzleComponent::First: + case ShaderNodes::SwizzleComponent::First: Append("x"); break; - case ShaderAst::SwizzleComponent::Second: + case ShaderNodes::SwizzleComponent::Second: Append("y"); break; - case ShaderAst::SwizzleComponent::Third: + case ShaderNodes::SwizzleComponent::Third: Append("z"); break; - case ShaderAst::SwizzleComponent::Fourth: + case ShaderNodes::SwizzleComponent::Fourth: Append("w"); break; } } } - void GlslWriter::Append(ShaderAst::BuiltinEntry builtin) + void GlslWriter::Visit(const ShaderNodes::UniformVariable& var) { - switch (builtin) + Append(var.name); + } + + bool GlslWriter::HasExplicitBinding(const ShaderAst& shader) + { + for (const auto& uniform : shader.GetUniforms()) { - case ShaderAst::BuiltinEntry::VertexPosition: - Append("gl_Position"); - break; + if (uniform.bindingIndex.has_value()) + return true; } + + return false; } - void GlslWriter::Append(ShaderAst::ExpressionType type) + bool GlslWriter::HasExplicitLocation(const ShaderAst& shader) { - switch (type) + for (const auto& input : shader.GetInputs()) { - case ShaderAst::ExpressionType::Boolean: - Append("bool"); - break; - case ShaderAst::ExpressionType::Float1: - Append("float"); - break; - case ShaderAst::ExpressionType::Float2: - Append("vec2"); - break; - case ShaderAst::ExpressionType::Float3: - Append("vec3"); - break; - case ShaderAst::ExpressionType::Float4: - Append("vec4"); - break; - case ShaderAst::ExpressionType::Mat4x4: - Append("mat4"); - break; - case ShaderAst::ExpressionType::Sampler2D: - Append("sampler2D"); - break; - case ShaderAst::ExpressionType::Void: - Append("void"); - break; + if (input.locationIndex.has_value()) + return true; } - } - void GlslWriter::Append(const String& txt) - { - NazaraAssert(m_currentState, "This function should only be called while processing an AST"); - - m_currentState->stream << txt; - } - - void GlslWriter::AppendCommentSection(const String& section) - { - NazaraAssert(m_currentState, "This function should only be called while processing an AST"); - - String stars((section.GetSize() < 33) ? (36 - section.GetSize()) / 2 : 3, '*'); - m_currentState->stream << "/*" << stars << ' ' << section << ' ' << stars << "*/"; - AppendLine(); - } - - void GlslWriter::AppendFunction(Function& func) - { - NazaraAssert(!m_currentFunction, "A function is already being processed"); - NazaraAssert(m_currentState, "This function should only be called while processing an AST"); - - m_currentFunction = &func; - CallOnExit onExit([this] () + for (const auto& output : shader.GetOutputs()) { - m_currentFunction = nullptr; - }); - - func.node->Register(*this); - - Append(func.retType); - - m_currentState->stream << ' '; - Append(func.name); - - m_currentState->stream << '('; - for (std::size_t i = 0; i < func.parameters.size(); ++i) - { - if (i != 0) - m_currentState->stream << ", "; - - Append(func.parameters[i]->type); - m_currentState->stream << ' '; - Append(func.parameters[i]->name); + if (output.locationIndex.has_value()) + return true; } - m_currentState->stream << ")\n"; - EnterScope(); - { - Visit(func.node); - } - LeaveScope(); + return false; } - - void GlslWriter::AppendLine(const String& txt) - { - NazaraAssert(m_currentState, "This function should only be called while processing an AST"); - - m_currentState->stream << txt << '\n' << String(m_currentState->indentLevel, '\t'); - } - - void GlslWriter::DeclareVariables(const VariableContainer& variables, const String& keyword, const String& section) - { - if (!variables.empty()) - { - if (!section.IsEmpty()) - AppendCommentSection(section); - - for (const auto& pair : variables) - { - if (!keyword.IsEmpty()) - { - Append(keyword); - Append(" "); - } - - Append(pair.first); - Append(" "); - Append(pair.second); - AppendLine(";"); - } - - AppendLine(); - } - } - - void GlslWriter::EnterScope() - { - NazaraAssert(m_currentState, "This function should only be called while processing an AST"); - - m_currentState->indentLevel++; - AppendLine("{"); - } - - void GlslWriter::LeaveScope() - { - NazaraAssert(m_currentState, "This function should only be called while processing an AST"); - - m_currentState->indentLevel--; - AppendLine(); - AppendLine("}"); - } - } diff --git a/src/Nazara/Renderer/ShaderAst.cpp b/src/Nazara/Renderer/ShaderAst.cpp index b6623cc48..a52cca657 100644 --- a/src/Nazara/Renderer/ShaderAst.cpp +++ b/src/Nazara/Renderer/ShaderAst.cpp @@ -3,275 +3,40 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include -#include -#include #include -namespace Nz::ShaderAst +namespace Nz { - Node::~Node() = default; - - ExpressionCategory Expression::GetExpressionCategory() const + void ShaderAst::AddFunction(std::string name, ShaderNodes::StatementPtr statement, std::vector parameters, ShaderNodes::ExpressionType returnType) { - return ExpressionCategory::RValue; + auto& functionEntry = m_functions.emplace_back(); + functionEntry.name = std::move(name); + functionEntry.parameters = std::move(parameters); + functionEntry.returnType = returnType; + functionEntry.statement = std::move(statement); } - void ExpressionStatement::Register(ShaderWriter& visitor) + void ShaderAst::AddInput(std::string name, ShaderNodes::ExpressionType type, std::optional locationIndex) { - expression->Register(visitor); + auto& inputEntry = m_inputs.emplace_back(); + inputEntry.name = std::move(name); + inputEntry.locationIndex = std::move(locationIndex); + inputEntry.type = type; } - void ExpressionStatement::Visit(ShaderVisitor& visitor) + void ShaderAst::AddOutput(std::string name, ShaderNodes::ExpressionType type, std::optional locationIndex) { - visitor.Visit(*this); + auto& outputEntry = m_outputs.emplace_back(); + outputEntry.name = std::move(name); + outputEntry.locationIndex = std::move(locationIndex); + outputEntry.type = type; } - - void ConditionalStatement::Register(ShaderWriter& visitor) + void ShaderAst::AddUniform(std::string name, ShaderNodes::ExpressionType type, std::optional bindingIndex) { - if (visitor.IsConditionEnabled(conditionName)) - statement->Register(visitor); - } - - void ConditionalStatement::Visit(ShaderVisitor& visitor) - { - if (visitor.IsConditionEnabled(conditionName)) - statement->Visit(visitor); - } - - - void StatementBlock::Register(ShaderWriter& visitor) - { - for (auto& statementPtr : statements) - statementPtr->Register(visitor); - } - - void StatementBlock::Visit(ShaderVisitor& visitor) - { - visitor.Visit(*this); - } - - ExpressionCategory Variable::GetExpressionCategory() const - { - return ExpressionCategory::LValue; - } - - ExpressionType Variable::GetExpressionType() const - { - return type; - } - - - void BuiltinVariable::Register(ShaderWriter& /*visitor*/) - { - } - - void BuiltinVariable::Visit(ShaderVisitor& visitor) - { - visitor.Visit(*this); - } - - - void NamedVariable::Register(ShaderWriter& visitor) - { - visitor.RegisterVariable(kind, name, type); - } - - void NamedVariable::Visit(ShaderVisitor& visitor) - { - visitor.Visit(*this); - } - - - void DeclareVariable::Register(ShaderWriter& visitor) - { - variable->Register(visitor); - - if (expression) - expression->Register(visitor); - } - - void DeclareVariable::Visit(ShaderVisitor& visitor) - { - visitor.Visit(*this); - } - - - ExpressionType AssignOp::GetExpressionType() const - { - return left->GetExpressionType(); - } - - void AssignOp::Register(ShaderWriter& visitor) - { - left->Register(visitor); - right->Register(visitor); - } - - void AssignOp::Visit(ShaderVisitor& visitor) - { - visitor.Visit(*this); - } - - - ExpressionType BinaryOp::GetExpressionType() const - { - ShaderAst::ExpressionType exprType = ShaderAst::ExpressionType::Void; - - switch (op) - { - case ShaderAst::BinaryType::Add: - case ShaderAst::BinaryType::Substract: - exprType = left->GetExpressionType(); - break; - - case ShaderAst::BinaryType::Divide: - case ShaderAst::BinaryType::Multiply: - //FIXME - exprType = static_cast(std::max(UnderlyingCast(left->GetExpressionType()), UnderlyingCast(right->GetExpressionType()))); - break; - - case ShaderAst::BinaryType::Equality: - exprType = ExpressionType::Boolean; - break; - } - - NazaraAssert(exprType != ShaderAst::ExpressionType::Void, "Unhandled builtin"); - - return exprType; - } - - void BinaryOp::Register(ShaderWriter& visitor) - { - left->Register(visitor); - right->Register(visitor); - } - - void BinaryOp::Visit(ShaderVisitor& visitor) - { - visitor.Visit(*this); - } - - - void Branch::Register(ShaderWriter& visitor) - { - for (ConditionalStatement& statement : condStatements) - { - statement.condition->Register(visitor); - statement.statement->Register(visitor); - } - - if (elseStatement) - elseStatement->Register(visitor); - } - - void Branch::Visit(ShaderVisitor& visitor) - { - visitor.Visit(*this); - } - - - ExpressionType Constant::GetExpressionType() const - { - return exprType; - } - - void Constant::Register(ShaderWriter&) - { - } - - void Constant::Visit(ShaderVisitor& visitor) - { - visitor.Visit(*this); - } - - ExpressionType Cast::GetExpressionType() const - { - return exprType; - } - - void Cast::Register(ShaderWriter& visitor) - { - auto it = expressions.begin(); - (*it)->Register(visitor); - - for (; it != expressions.end(); ++it) - { - if (!*it) - break; - - (*it)->Register(visitor); - } - } - - void Cast::Visit(ShaderVisitor& visitor) - { - visitor.Visit(*this); - } - - - ExpressionCategory SwizzleOp::GetExpressionCategory() const - { - return ExpressionCategory::LValue; - } - - ExpressionType SwizzleOp::GetExpressionType() const - { - return static_cast(UnderlyingCast(GetComponentType(expression->GetExpressionType())) + componentCount - 1); - } - - void SwizzleOp::Register(ShaderWriter& visitor) - { - expression->Register(visitor); - } - - void SwizzleOp::Visit(ShaderVisitor& visitor) - { - visitor.Visit(*this); - } - - - ExpressionType Sample2D::GetExpressionType() const - { - return ExpressionType::Float4; - } - - void Sample2D::Register(ShaderWriter& visitor) - { - sampler->Register(visitor); - coordinates->Register(visitor); - } - - void Sample2D::Visit(ShaderVisitor& visitor) - { - visitor.Visit(*this); - } - - - ExpressionType BinaryFunc::GetExpressionType() const - { - switch (intrinsic) - { - case BinaryIntrinsic::CrossProduct: - return left->GetExpressionType(); - - case BinaryIntrinsic::DotProduct: - return ExpressionType::Float1; - } - - NazaraAssert(false, "Unhandled builtin"); - return ExpressionType::Void; - } - - void BinaryFunc::Register(ShaderWriter& visitor) - { - left->Register(visitor); - right->Register(visitor); - } - - void BinaryFunc::Visit(ShaderVisitor& visitor) - { - visitor.Visit(*this); + auto& uniformEntry = m_uniforms.emplace_back(); + uniformEntry.bindingIndex = std::move(bindingIndex); + uniformEntry.name = std::move(name); + uniformEntry.type = type; } } diff --git a/src/Nazara/Renderer/ShaderNodes.cpp b/src/Nazara/Renderer/ShaderNodes.cpp new file mode 100644 index 000000000..eb4f59160 --- /dev/null +++ b/src/Nazara/Renderer/ShaderNodes.cpp @@ -0,0 +1,179 @@ +// 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 + +#include +#include +#include +#include +#include + +namespace Nz::ShaderNodes +{ + Node::~Node() = default; + + ExpressionCategory Expression::GetExpressionCategory() const + { + return ExpressionCategory::RValue; + } + + void ExpressionStatement::Visit(ShaderVisitor& visitor) + { + visitor.Visit(*this); + } + + + void ConditionalStatement::Visit(ShaderVisitor& visitor) + { + if (visitor.IsConditionEnabled(conditionName)) + statement->Visit(visitor); + } + + + void StatementBlock::Visit(ShaderVisitor& visitor) + { + visitor.Visit(*this); + } + + + void DeclareVariable::Visit(ShaderVisitor& visitor) + { + visitor.Visit(*this); + } + + + ExpressionCategory Identifier::GetExpressionCategory() const + { + return ExpressionCategory::LValue; + } + + ExpressionType Identifier::GetExpressionType() const + { + assert(var); + return var->type; + } + + void Identifier::Visit(ShaderVisitor& visitor) + { + visitor.Visit(*this); + } + + + ExpressionType AssignOp::GetExpressionType() const + { + return left->GetExpressionType(); + } + + void AssignOp::Visit(ShaderVisitor& visitor) + { + visitor.Visit(*this); + } + + + ExpressionType BinaryOp::GetExpressionType() const + { + ShaderNodes::ExpressionType exprType = ShaderNodes::ExpressionType::Void; + + switch (op) + { + case ShaderNodes::BinaryType::Add: + case ShaderNodes::BinaryType::Substract: + exprType = left->GetExpressionType(); + break; + + case ShaderNodes::BinaryType::Divide: + case ShaderNodes::BinaryType::Multiply: + //FIXME + exprType = static_cast(std::max(UnderlyingCast(left->GetExpressionType()), UnderlyingCast(right->GetExpressionType()))); + break; + + case ShaderNodes::BinaryType::Equality: + exprType = ExpressionType::Boolean; + break; + } + + NazaraAssert(exprType != ShaderNodes::ExpressionType::Void, "Unhandled builtin"); + + return exprType; + } + + void BinaryOp::Visit(ShaderVisitor& visitor) + { + visitor.Visit(*this); + } + + + void Branch::Visit(ShaderVisitor& visitor) + { + visitor.Visit(*this); + } + + + ExpressionType Constant::GetExpressionType() const + { + return exprType; + } + + void Constant::Visit(ShaderVisitor& visitor) + { + visitor.Visit(*this); + } + + ExpressionType Cast::GetExpressionType() const + { + return exprType; + } + + void Cast::Visit(ShaderVisitor& visitor) + { + visitor.Visit(*this); + } + + + ExpressionCategory SwizzleOp::GetExpressionCategory() const + { + return ExpressionCategory::LValue; + } + + ExpressionType SwizzleOp::GetExpressionType() const + { + return static_cast(UnderlyingCast(GetComponentType(expression->GetExpressionType())) + componentCount - 1); + } + + void SwizzleOp::Visit(ShaderVisitor& visitor) + { + visitor.Visit(*this); + } + + + ExpressionType Sample2D::GetExpressionType() const + { + return ExpressionType::Float4; + } + + void Sample2D::Visit(ShaderVisitor& visitor) + { + visitor.Visit(*this); + } + + + ExpressionType IntrinsicCall::GetExpressionType() const + { + switch (intrinsic) + { + case IntrinsicType::CrossProduct: + return parameters.front()->GetExpressionType(); + + case IntrinsicType::DotProduct: + return ExpressionType::Float1; + } + + NazaraAssert(false, "Unhandled builtin"); + return ExpressionType::Void; + } + + void IntrinsicCall::Visit(ShaderVisitor& visitor) + { + visitor.Visit(*this); + } +} diff --git a/src/Nazara/Renderer/ShaderSerializer.cpp b/src/Nazara/Renderer/ShaderSerializer.cpp index 6e6e3e8ff..909422f52 100644 --- a/src/Nazara/Renderer/ShaderSerializer.cpp +++ b/src/Nazara/Renderer/ShaderSerializer.cpp @@ -3,13 +3,15 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include +#include #include -namespace Nz::ShaderAst +namespace Nz::ShaderNodes { namespace { - class ShaderSerializerVisitor : public ShaderVisitor + class ShaderSerializerVisitor : public ShaderVisitor, public ShaderVarVisitor { public: ShaderSerializerVisitor(ShaderSerializerBase& serializer) : @@ -22,11 +24,6 @@ namespace Nz::ShaderAst Serialize(node); } - void Visit(const BinaryFunc& node) override - { - Serialize(node); - } - void Visit(const BinaryOp& node) override { Serialize(node); @@ -37,11 +34,6 @@ namespace Nz::ShaderAst Serialize(node); } - void Visit(const BuiltinVariable& node) override - { - Serialize(node); - } - void Visit(const Cast& node) override { Serialize(node); @@ -62,7 +54,12 @@ namespace Nz::ShaderAst Serialize(node); } - void Visit(const NamedVariable& node) override + void Visit(const Identifier& node) override + { + Serialize(node); + } + + void Visit(const IntrinsicCall& node) override { Serialize(node); } @@ -82,6 +79,37 @@ namespace Nz::ShaderAst Serialize(node); } + + void Visit(const ShaderNodes::BuiltinVariable& var) override + { + Serialize(var); + } + + void Visit(const ShaderNodes::InputVariable& var) override + { + Serialize(var); + } + + void Visit(const ShaderNodes::LocalVariable& var) override + { + Serialize(var); + } + + void Visit(const ShaderNodes::OutputVariable& var) override + { + Serialize(var); + } + + void Visit(const ShaderNodes::ParameterVariable& var) override + { + Serialize(var); + } + + void Visit(const ShaderNodes::UniformVariable& var) override + { + Serialize(var); + } + private: template void Serialize(const T& node) @@ -101,13 +129,6 @@ namespace Nz::ShaderAst Node(node.right); } - void ShaderSerializerBase::Serialize(BinaryFunc& node) - { - Enum(node.intrinsic); - Node(node.left); - Node(node.right); - } - void ShaderSerializerBase::Serialize(BinaryOp& node) { Enum(node.op); @@ -129,7 +150,7 @@ namespace Nz::ShaderAst void ShaderSerializerBase::Serialize(BuiltinVariable& node) { - Enum(node.var); + Enum(node.type); Enum(node.type); } @@ -170,7 +191,7 @@ namespace Nz::ShaderAst void ShaderSerializerBase::Serialize(DeclareVariable& node) { - Node(node.variable); + Variable(node.variable); Node(node.expression); } @@ -179,10 +200,22 @@ namespace Nz::ShaderAst Node(node.expression); } + void ShaderSerializerBase::Serialize(Identifier& node) + { + Variable(node.var); + } + + void ShaderSerializerBase::Serialize(IntrinsicCall& node) + { + Enum(node.intrinsic); + Container(node.parameters); + for (auto& param : node.parameters) + Node(param); + } + void ShaderSerializerBase::Serialize(NamedVariable& node) { Value(node.name); - Enum(node.kind); Enum(node.type); } @@ -272,6 +305,18 @@ namespace Nz::ShaderAst m_stream << val; } + void ShaderSerializer::Variable(VariablePtr& var) + { + VariableType nodeType = (var) ? var->GetType() : VariableType::None; + m_stream << static_cast(nodeType); + + if (var) + { + ShaderSerializerVisitor visitor(*this); + var->Visit(visitor); + } + } + ByteArray Serialize(const StatementPtr& shader) { ByteArray byteArray; @@ -309,27 +354,26 @@ namespace Nz::ShaderAst NodeType nodeType = static_cast(nodeTypeInt); -#define HandleNodeType(Type) case NodeType:: Type : node = std::make_shared(); break +#define HandleType(Type) case NodeType:: Type : node = std::make_shared(); break switch (nodeType) { case NodeType::None: break; - HandleNodeType(AssignOp); - HandleNodeType(BinaryFunc); - HandleNodeType(BinaryOp); - HandleNodeType(Branch); - HandleNodeType(BuiltinVariable); - HandleNodeType(Cast); - HandleNodeType(Constant); - HandleNodeType(ConditionalStatement); - HandleNodeType(DeclareVariable); - HandleNodeType(ExpressionStatement); - HandleNodeType(NamedVariable); - HandleNodeType(Sample2D); - HandleNodeType(SwizzleOp); - HandleNodeType(StatementBlock); + HandleType(AssignOp); + HandleType(BinaryOp); + HandleType(Branch); + HandleType(Cast); + HandleType(Constant); + HandleType(ConditionalStatement); + HandleType(DeclareVariable); + HandleType(ExpressionStatement); + HandleType(Identifier); + HandleType(IntrinsicCall); + HandleType(Sample2D); + HandleType(SwizzleOp); + HandleType(StatementBlock); } -#undef HandleNodeType +#undef HandleType if (node) { @@ -372,5 +416,32 @@ namespace Nz::ShaderAst { m_stream >> val; } + + void ShaderUnserializer::Variable(VariablePtr& var) + { + Int32 nodeTypeInt; + m_stream >> nodeTypeInt; + + VariableType nodeType = static_cast(nodeTypeInt); + +#define HandleType(Type) case VariableType:: Type : var = std::make_shared(); break + switch (nodeType) + { + case VariableType::None: break; + + HandleType(BuiltinVariable); + HandleType(InputVariable); + HandleType(LocalVariable); + HandleType(OutputVariable); + HandleType(UniformVariable); + } +#undef HandleType + + if (var) + { + ShaderSerializerVisitor visitor(*this); + var->Visit(visitor); + } + } } diff --git a/src/Nazara/Renderer/ShaderValidator.cpp b/src/Nazara/Renderer/ShaderValidator.cpp index c7a25989f..aab559a61 100644 --- a/src/Nazara/Renderer/ShaderValidator.cpp +++ b/src/Nazara/Renderer/ShaderValidator.cpp @@ -3,20 +3,49 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include +#include +#include +#include #include -namespace Nz::ShaderAst +namespace Nz { struct AstError { std::string errMsg; }; - bool ShaderValidator::Validate(const StatementPtr& shader, std::string* error) + struct ShaderValidator::Context + { + struct Local + { + std::string name; + ShaderNodes::ExpressionType type; + }; + + const ShaderAst::Function* currentFunction; + std::vector declaredLocals; + std::vector blockLocalIndex; + }; + + bool ShaderValidator::Validate(std::string* error) { try { - shader->Visit(*this); + for (std::size_t i = 0; i < m_shader.GetFunctionCount(); ++i) + { + const auto& func = m_shader.GetFunction(i); + + Context currentContext; + currentContext.currentFunction = &func; + + m_context = ¤tContext; + CallOnExit resetContext([&] { m_context = nullptr; }); + + func.statement->Visit(*this); + } + return true; } catch (const AstError& e) @@ -28,14 +57,14 @@ namespace Nz::ShaderAst } } - const ExpressionPtr& ShaderValidator::MandatoryExpr(const ExpressionPtr& node) + const ShaderNodes::ExpressionPtr& ShaderValidator::MandatoryExpr(const ShaderNodes::ExpressionPtr& node) { MandatoryNode(node); return node; } - const NodePtr& ShaderValidator::MandatoryNode(const NodePtr& node) + const ShaderNodes::NodePtr& ShaderValidator::MandatoryNode(const ShaderNodes::NodePtr& node) { if (!node) throw AstError{ "Invalid node" }; @@ -43,90 +72,76 @@ namespace Nz::ShaderAst return node; } - void ShaderValidator::TypeMustMatch(const ExpressionPtr& left, const ExpressionPtr& right) + void ShaderValidator::TypeMustMatch(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right) { - if (left->GetExpressionType() != right->GetExpressionType()) + return TypeMustMatch(left->GetExpressionType(), right->GetExpressionType()); + } + + void ShaderValidator::TypeMustMatch(ShaderNodes::ExpressionType left, ShaderNodes::ExpressionType right) + { + if (left != right) throw AstError{ "Left expression type must match right expression type" }; } - void ShaderValidator::Visit(const AssignOp& node) + void ShaderValidator::Visit(const ShaderNodes::AssignOp& node) { MandatoryNode(node.left); MandatoryNode(node.right); TypeMustMatch(node.left, node.right); - Visit(node.left); - Visit(node.right); - } - - void ShaderValidator::Visit(const BinaryFunc& node) - { - MandatoryNode(node.left); - MandatoryNode(node.right); - TypeMustMatch(node.left, node.right); - - switch (node.intrinsic) - { - case BinaryIntrinsic::CrossProduct: - { - if (node.left->GetExpressionType() != ExpressionType::Float3) - throw AstError{ "CrossProduct only works with Float3 expressions" }; - } - - case BinaryIntrinsic::DotProduct: - break; - } + if (node.left->GetExpressionCategory() != ShaderNodes::ExpressionCategory::LValue) + throw AstError { "Assignation is only possible with a l-value" }; Visit(node.left); Visit(node.right); } - void ShaderValidator::Visit(const BinaryOp& node) + void ShaderValidator::Visit(const ShaderNodes::BinaryOp& node) { MandatoryNode(node.left); MandatoryNode(node.right); - ExpressionType leftType = node.left->GetExpressionType(); - ExpressionType rightType = node.right->GetExpressionType(); + ShaderNodes::ExpressionType leftType = node.left->GetExpressionType(); + ShaderNodes::ExpressionType rightType = node.right->GetExpressionType(); switch (node.op) { - case BinaryType::Add: - case BinaryType::Equality: - case BinaryType::Substract: + case ShaderNodes::BinaryType::Add: + case ShaderNodes::BinaryType::Equality: + case ShaderNodes::BinaryType::Substract: TypeMustMatch(node.left, node.right); break; - case BinaryType::Multiply: - case BinaryType::Divide: + case ShaderNodes::BinaryType::Multiply: + case ShaderNodes::BinaryType::Divide: { switch (leftType) { - case ExpressionType::Float1: + case ShaderNodes::ExpressionType::Float1: { - if (Node::GetComponentType(rightType) != ExpressionType::Float1) + if (ShaderNodes::Node::GetComponentType(rightType) != ShaderNodes::ExpressionType::Float1) throw AstError{ "Left expression type is not compatible with right expression type" }; break; } - case ExpressionType::Float2: - case ExpressionType::Float3: - case ExpressionType::Float4: + case ShaderNodes::ExpressionType::Float2: + case ShaderNodes::ExpressionType::Float3: + case ShaderNodes::ExpressionType::Float4: { - if (leftType != rightType && rightType != ExpressionType::Float1) + if (leftType != rightType && rightType != ShaderNodes::ExpressionType::Float1) throw AstError{ "Left expression type is not compatible with right expression type" }; break; } - case ExpressionType::Mat4x4: + case ShaderNodes::ExpressionType::Mat4x4: { switch (rightType) { - case ExpressionType::Float1: - case ExpressionType::Float4: - case ExpressionType::Mat4x4: + case ShaderNodes::ExpressionType::Float1: + case ShaderNodes::ExpressionType::Float4: + case ShaderNodes::ExpressionType::Mat4x4: break; default: @@ -146,7 +161,7 @@ namespace Nz::ShaderAst Visit(node.right); } - void ShaderValidator::Visit(const Branch& node) + void ShaderValidator::Visit(const ShaderNodes::Branch& node) { for (const auto& condStatement : node.condStatements) { @@ -155,11 +170,7 @@ namespace Nz::ShaderAst } } - void ShaderValidator::Visit(const BuiltinVariable& /*node*/) - { - } - - void ShaderValidator::Visit(const Cast& node) + void ShaderValidator::Visit(const ShaderNodes::Cast& node) { unsigned int componentCount = 0; unsigned int requiredComponents = node.GetComponentCount(node.exprType); @@ -176,55 +187,203 @@ namespace Nz::ShaderAst throw AstError{ "Component count doesn't match required component count" }; } - void ShaderValidator::Visit(const Constant& /*node*/) + void ShaderValidator::Visit(const ShaderNodes::Constant& /*node*/) { } - void ShaderValidator::Visit(const DeclareVariable& node) + void ShaderValidator::Visit(const ShaderNodes::DeclareVariable& node) + { + assert(m_context); + + if (node.expression) + Visit(node.expression); + + auto& local = m_context->declaredLocals.emplace_back(); + local.name = node.variable->name; + local.type = node.variable->type; + } + + void ShaderValidator::Visit(const ShaderNodes::ExpressionStatement& node) { Visit(MandatoryNode(node.expression)); } - void ShaderValidator::Visit(const ExpressionStatement& node) + void ShaderValidator::Visit(const ShaderNodes::Identifier& node) { - Visit(MandatoryNode(node.expression)); + assert(m_context); + + if (!node.var) + throw AstError{ "Invalid variable" }; + + //< FIXME: Use variable visitor + switch (node.var->GetType()) + { + case ShaderNodes::VariableType::BuiltinVariable: + break; + + case ShaderNodes::VariableType::InputVariable: + { + auto& namedVar = static_cast(*node.var); + + for (std::size_t i = 0; i < m_shader.GetInputCount(); ++i) + { + const auto& input = m_shader.GetInput(i); + if (input.name == namedVar.name) + { + TypeMustMatch(input.type, namedVar.type); + return; + } + } + + throw AstError{ "Input not found" }; + } + + case ShaderNodes::VariableType::LocalVariable: + { + auto& localVar = static_cast(*node.var); + const auto& vars = m_context->declaredLocals; + + auto it = std::find_if(vars.begin(), vars.end(), [&](const auto& var) { return var.name == localVar.name; }); + if (it == vars.end()) + throw AstError{ "Local variable not found in this block" }; + + TypeMustMatch(it->type, localVar.type); + break; + } + + case ShaderNodes::VariableType::OutputVariable: + { + auto& outputVar = static_cast(*node.var); + + for (std::size_t i = 0; i < m_shader.GetOutputCount(); ++i) + { + const auto& input = m_shader.GetOutput(i); + if (input.name == outputVar.name) + { + TypeMustMatch(input.type, outputVar.type); + return; + } + } + + throw AstError{ "Output not found" }; + } + + case ShaderNodes::VariableType::ParameterVariable: + { + assert(m_context->currentFunction); + + auto& parameter = static_cast(*node.var); + const auto& parameters = m_context->currentFunction->parameters; + + auto it = std::find_if(parameters.begin(), parameters.end(), [&](const auto& parameter) { return parameter.name == parameter.name; }); + if (it == parameters.end()) + throw AstError{ "Parameter not found in function" }; + + TypeMustMatch(it->type, parameter.type); + break; + } + + case ShaderNodes::VariableType::UniformVariable: + { + auto& uniformVar = static_cast(*node.var); + + for (std::size_t i = 0; i < m_shader.GetUniformCount(); ++i) + { + const auto& uniform = m_shader.GetUniform(i); + if (uniform.name == uniformVar.name) + { + TypeMustMatch(uniform.type, uniformVar.type); + return; + } + } + + throw AstError{ "Uniform not found" }; + } + + default: + break; + } } - void ShaderValidator::Visit(const NamedVariable& node) + void ShaderValidator::Visit(const ShaderNodes::IntrinsicCall& node) { - if (node.name.empty()) - throw AstError{ "Variable has empty name" }; + switch (node.intrinsic) + { + case ShaderNodes::IntrinsicType::CrossProduct: + case ShaderNodes::IntrinsicType::DotProduct: + { + if (node.parameters.size() != 2) + throw AstError { "Expected 2 parameters" }; + + for (auto& param : node.parameters) + MandatoryNode(param); + + ShaderNodes::ExpressionType type = node.parameters.front()->GetExpressionType(); + for (std::size_t i = 1; i < node.parameters.size(); ++i) + { + if (type != node.parameters[i]->GetExpressionType()) + throw AstError{ "All type must match" }; + } + + break; + } + } + + switch (node.intrinsic) + { + case ShaderNodes::IntrinsicType::CrossProduct: + { + if (node.parameters[0]->GetExpressionType() != ShaderNodes::ExpressionType::Float3) + throw AstError{ "CrossProduct only works with Float3 expressions" }; + + break; + } + + case ShaderNodes::IntrinsicType::DotProduct: + break; + } + + for (auto& param : node.parameters) + Visit(param); } - void ShaderValidator::Visit(const Sample2D& node) + void ShaderValidator::Visit(const ShaderNodes::Sample2D& node) { - if (MandatoryExpr(node.sampler)->GetExpressionType() != ExpressionType::Sampler2D) + if (MandatoryExpr(node.sampler)->GetExpressionType() != ShaderNodes::ExpressionType::Sampler2D) throw AstError{ "Sampler must be a Sampler2D" }; - if (MandatoryExpr(node.coordinates)->GetExpressionType() != ExpressionType::Float2) + if (MandatoryExpr(node.coordinates)->GetExpressionType() != ShaderNodes::ExpressionType::Float2) throw AstError{ "Coordinates must be a Float2" }; Visit(node.sampler); Visit(node.coordinates); } - void ShaderValidator::Visit(const StatementBlock& node) + void ShaderValidator::Visit(const ShaderNodes::StatementBlock& node) { + assert(m_context); + + m_context->blockLocalIndex.push_back(m_context->declaredLocals.size()); + for (const auto& statement : node.statements) Visit(MandatoryNode(statement)); + + assert(m_context->declaredLocals.size() >= m_context->blockLocalIndex.back()); + m_context->declaredLocals.resize(m_context->blockLocalIndex.back()); + m_context->blockLocalIndex.pop_back(); } - void ShaderValidator::Visit(const SwizzleOp& node) + void ShaderValidator::Visit(const ShaderNodes::SwizzleOp& node) { if (node.componentCount > 4) throw AstError{ "Cannot swizzle more than four elements" }; switch (MandatoryExpr(node.expression)->GetExpressionType()) { - case ExpressionType::Float1: - case ExpressionType::Float2: - case ExpressionType::Float3: - case ExpressionType::Float4: + case ShaderNodes::ExpressionType::Float1: + case ShaderNodes::ExpressionType::Float2: + case ShaderNodes::ExpressionType::Float3: + case ShaderNodes::ExpressionType::Float4: break; default: @@ -234,9 +393,9 @@ namespace Nz::ShaderAst Visit(node.expression); } - bool Validate(const StatementPtr& shader, std::string* error) + bool ValidateShader(const ShaderAst& shader, std::string* error) { - ShaderValidator validator; - return validator.Validate(shader, error); + ShaderValidator validator(shader); + return validator.Validate(error); } } diff --git a/src/Nazara/Renderer/ShaderVarVisitor.cpp b/src/Nazara/Renderer/ShaderVarVisitor.cpp new file mode 100644 index 000000000..6f3838f26 --- /dev/null +++ b/src/Nazara/Renderer/ShaderVarVisitor.cpp @@ -0,0 +1,16 @@ +// Copyright (C) 2015 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 + +#include +#include + +namespace Nz +{ + ShaderVarVisitor::~ShaderVarVisitor() = default; + + void ShaderVarVisitor::Visit(const ShaderNodes::VariablePtr& node) + { + node->Visit(*this); + } +} diff --git a/src/Nazara/Renderer/ShaderVariables.cpp b/src/Nazara/Renderer/ShaderVariables.cpp new file mode 100644 index 000000000..93701c4ef --- /dev/null +++ b/src/Nazara/Renderer/ShaderVariables.cpp @@ -0,0 +1,77 @@ +// 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 + +#include +#include +#include + +namespace Nz::ShaderNodes +{ + ShaderNodes::Variable::~Variable() = default; + + VariableType BuiltinVariable::GetType() const + { + return VariableType::BuiltinVariable; + } + + void BuiltinVariable::Visit(ShaderVarVisitor& visitor) + { + visitor.Visit(*this); + } + + + VariableType InputVariable::GetType() const + { + return VariableType::InputVariable; + } + + void InputVariable::Visit(ShaderVarVisitor& visitor) + { + visitor.Visit(*this); + } + + + VariableType LocalVariable::GetType() const + { + return VariableType::LocalVariable; + } + + void LocalVariable::Visit(ShaderVarVisitor& visitor) + { + visitor.Visit(*this); + } + + + VariableType OutputVariable::GetType() const + { + return VariableType::OutputVariable; + } + + void OutputVariable::Visit(ShaderVarVisitor& visitor) + { + visitor.Visit(*this); + } + + + VariableType ParameterVariable::GetType() const + { + return VariableType::ParameterVariable; + } + + void ParameterVariable::Visit(ShaderVarVisitor& visitor) + { + visitor.Visit(*this); + } + + + VariableType UniformVariable::GetType() const + { + return VariableType::UniformVariable; + } + + void UniformVariable::Visit(ShaderVarVisitor& visitor) + { + visitor.Visit(*this); + } +} diff --git a/src/Nazara/Renderer/ShaderVisitor.cpp b/src/Nazara/Renderer/ShaderVisitor.cpp index 2b5a590bd..dd7e01542 100644 --- a/src/Nazara/Renderer/ShaderVisitor.cpp +++ b/src/Nazara/Renderer/ShaderVisitor.cpp @@ -9,7 +9,7 @@ namespace Nz { ShaderVisitor::~ShaderVisitor() = default; - void ShaderVisitor::EnableCondition(const String& name, bool cond) + void ShaderVisitor::EnableCondition(const std::string& name, bool cond) { if (cond) m_conditions.insert(name); @@ -17,12 +17,12 @@ namespace Nz m_conditions.erase(name); } - bool ShaderVisitor::IsConditionEnabled(const String& name) const + bool ShaderVisitor::IsConditionEnabled(const std::string& name) const { return m_conditions.count(name) != 0; } - void ShaderVisitor::Visit(const ShaderAst::NodePtr& node) + void ShaderVisitor::Visit(const ShaderNodes::NodePtr& node) { node->Visit(*this); } diff --git a/src/Nazara/Renderer/ShaderWriter.cpp b/src/Nazara/Renderer/ShaderWriter.cpp index 982251556..8ca48da3e 100644 --- a/src/Nazara/Renderer/ShaderWriter.cpp +++ b/src/Nazara/Renderer/ShaderWriter.cpp @@ -7,4 +7,5 @@ namespace Nz { + ShaderWriter::~ShaderWriter() = default; } diff --git a/src/ShaderNode/DataModels/Cast.hpp b/src/ShaderNode/DataModels/Cast.hpp index bb287555c..c30f3eadc 100644 --- a/src/ShaderNode/DataModels/Cast.hpp +++ b/src/ShaderNode/DataModels/Cast.hpp @@ -19,7 +19,7 @@ class CastVec : public ShaderNode void BuildNodeEdition(QFormLayout* layout) override; - Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override; + Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override; QString caption() const override; QString name() const override; diff --git a/src/ShaderNode/DataModels/Cast.inl b/src/ShaderNode/DataModels/Cast.inl index 1a304c2c7..ccb15385c 100644 --- a/src/ShaderNode/DataModels/Cast.inl +++ b/src/ShaderNode/DataModels/Cast.inl @@ -49,7 +49,7 @@ void CastVec::BuildNodeEdition(QFormLayout* layout) } template -Nz::ShaderAst::ExpressionPtr CastVec::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const +Nz::ShaderNodes::ExpressionPtr CastVec::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const { assert(m_input); assert(count == 1); @@ -60,7 +60,7 @@ Nz::ShaderAst::ExpressionPtr CastVec::GetExpression(Nz::Shader { std::size_t overflowComponentCount = ToComponentCount - fromComponentCount; - std::array expr; + std::array expr; expr[0] = expressions[0]; for (std::size_t i = 0; i < overflowComponentCount; ++i) expr[i + 1] = Nz::ShaderBuilder::Constant(m_overflowComponents[i]); @@ -71,13 +71,13 @@ Nz::ShaderAst::ExpressionPtr CastVec::GetExpression(Nz::Shader } else if (ToComponentCount < fromComponentCount) { - std::array swizzleComponents; + std::array swizzleComponents; for (std::size_t i = 0; i < ToComponentCount; ++i) - swizzleComponents[i] = static_cast(static_cast(Nz::ShaderAst::SwizzleComponent::First) + i); + swizzleComponents[i] = static_cast(static_cast(Nz::ShaderNodes::SwizzleComponent::First) + i); return std::apply([&](auto... components) { - std::initializer_list componentList{ components... }; + std::initializer_list componentList{ components... }; return Nz::ShaderBuilder::Swizzle(expressions[0], componentList); }, swizzleComponents); } diff --git a/src/ShaderNode/DataModels/FloatValue.cpp b/src/ShaderNode/DataModels/FloatValue.cpp index 3da83982e..f9c25074b 100644 --- a/src/ShaderNode/DataModels/FloatValue.cpp +++ b/src/ShaderNode/DataModels/FloatValue.cpp @@ -71,7 +71,7 @@ void FloatValue::BuildNodeEdition(QFormLayout* layout) layout->addRow(tr("Value"), spinbox); } -Nz::ShaderAst::ExpressionPtr FloatValue::GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const +Nz::ShaderNodes::ExpressionPtr FloatValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const { assert(count == 0); diff --git a/src/ShaderNode/DataModels/FloatValue.hpp b/src/ShaderNode/DataModels/FloatValue.hpp index 44244cd46..fe77e5464 100644 --- a/src/ShaderNode/DataModels/FloatValue.hpp +++ b/src/ShaderNode/DataModels/FloatValue.hpp @@ -28,7 +28,7 @@ class FloatValue : public ShaderNode void BuildNodeEdition(QFormLayout* layout) override; - Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override; + Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override; private: bool ComputePreview(QPixmap& pixmap) override; diff --git a/src/ShaderNode/DataModels/InputValue.cpp b/src/ShaderNode/DataModels/InputValue.cpp index 92d08ba3e..5a2b088dd 100644 --- a/src/ShaderNode/DataModels/InputValue.cpp +++ b/src/ShaderNode/DataModels/InputValue.cpp @@ -107,7 +107,7 @@ void InputValue::BuildNodeEdition(QFormLayout* layout) layout->addRow(tr("Input"), inputSelection); } -Nz::ShaderAst::ExpressionPtr InputValue::GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const +Nz::ShaderNodes::ExpressionPtr InputValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const { assert(count == 0); @@ -116,22 +116,22 @@ Nz::ShaderAst::ExpressionPtr InputValue::GetExpression(Nz::ShaderAst::Expression const auto& inputEntry = GetGraph().GetInput(*m_currentInputIndex); - Nz::ShaderAst::ExpressionType expression = [&] + Nz::ShaderNodes::ExpressionType expression = [&] { switch (inputEntry.type) { - case InOutType::Bool: return Nz::ShaderAst::ExpressionType::Boolean; - case InOutType::Float1: return Nz::ShaderAst::ExpressionType::Float1; - case InOutType::Float2: return Nz::ShaderAst::ExpressionType::Float2; - case InOutType::Float3: return Nz::ShaderAst::ExpressionType::Float3; - case InOutType::Float4: return Nz::ShaderAst::ExpressionType::Float4; + case InOutType::Bool: return Nz::ShaderNodes::ExpressionType::Boolean; + case InOutType::Float1: return Nz::ShaderNodes::ExpressionType::Float1; + case InOutType::Float2: return Nz::ShaderNodes::ExpressionType::Float2; + case InOutType::Float3: return Nz::ShaderNodes::ExpressionType::Float3; + case InOutType::Float4: return Nz::ShaderNodes::ExpressionType::Float4; } assert(false); throw std::runtime_error("Unhandled input type"); }(); - return Nz::ShaderBuilder::Input(inputEntry.name, expression); + return Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Input(inputEntry.name, expression)); } auto InputValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType @@ -145,7 +145,7 @@ auto InputValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portInd const auto& inputEntry = GetGraph().GetInput(*m_currentInputIndex); switch (inputEntry.type) { - //case InputType::Bool: return Nz::ShaderAst::ExpressionType::Boolean; + //case InputType::Bool: return Nz::ShaderNodes::ExpressionType::Boolean; case InOutType::Float1: return FloatData::Type(); diff --git a/src/ShaderNode/DataModels/InputValue.hpp b/src/ShaderNode/DataModels/InputValue.hpp index a5eaabf01..d0e1593b9 100644 --- a/src/ShaderNode/DataModels/InputValue.hpp +++ b/src/ShaderNode/DataModels/InputValue.hpp @@ -19,7 +19,7 @@ class InputValue : public ShaderNode void BuildNodeEdition(QFormLayout* layout) override; - Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const override; + Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const override; QString caption() const override { return "Input"; } QString name() const override { return "Input"; } diff --git a/src/ShaderNode/DataModels/OutputValue.cpp b/src/ShaderNode/DataModels/OutputValue.cpp index 09d7aff78..7cf6fedec 100644 --- a/src/ShaderNode/DataModels/OutputValue.cpp +++ b/src/ShaderNode/DataModels/OutputValue.cpp @@ -51,10 +51,10 @@ void OutputValue::BuildNodeEdition(QFormLayout* layout) layout->addRow(tr("Output"), outputSelection); } -Nz::ShaderAst::ExpressionPtr OutputValue::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const +Nz::ShaderNodes::ExpressionPtr OutputValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const { - using namespace Nz::ShaderAst; using namespace Nz::ShaderBuilder; + using namespace Nz::ShaderNodes; assert(count == 1); @@ -63,22 +63,22 @@ Nz::ShaderAst::ExpressionPtr OutputValue::GetExpression(Nz::ShaderAst::Expressio const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex); - Nz::ShaderAst::ExpressionType expression = [&] + Nz::ShaderNodes::ExpressionType expression = [&] { switch (outputEntry.type) { - case InOutType::Bool: return Nz::ShaderAst::ExpressionType::Boolean; - case InOutType::Float1: return Nz::ShaderAst::ExpressionType::Float1; - case InOutType::Float2: return Nz::ShaderAst::ExpressionType::Float2; - case InOutType::Float3: return Nz::ShaderAst::ExpressionType::Float3; - case InOutType::Float4: return Nz::ShaderAst::ExpressionType::Float4; + case InOutType::Bool: return Nz::ShaderNodes::ExpressionType::Boolean; + case InOutType::Float1: return Nz::ShaderNodes::ExpressionType::Float1; + case InOutType::Float2: return Nz::ShaderNodes::ExpressionType::Float2; + case InOutType::Float3: return Nz::ShaderNodes::ExpressionType::Float3; + case InOutType::Float4: return Nz::ShaderNodes::ExpressionType::Float4; } assert(false); throw std::runtime_error("Unhandled output type"); }(); - auto output = Nz::ShaderBuilder::Output(outputEntry.name, expression); + auto output = Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Output(outputEntry.name, expression)); return Nz::ShaderBuilder::Assign(std::move(output), *expressions); } @@ -94,8 +94,8 @@ QtNodes::NodeDataType OutputValue::dataType(QtNodes::PortType portType, QtNodes: const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex); switch (outputEntry.type) { - //case InOutType::Bool: return Nz::ShaderAst::ExpressionType::Boolean; - //case InOutType::Float1: return Nz::ShaderAst::ExpressionType::Float1; + //case InOutType::Bool: return Nz::ShaderNodes::ExpressionType::Boolean; + //case InOutType::Float1: return Nz::ShaderNodes::ExpressionType::Float1; case InOutType::Float2: case InOutType::Float3: case InOutType::Float4: diff --git a/src/ShaderNode/DataModels/OutputValue.hpp b/src/ShaderNode/DataModels/OutputValue.hpp index 320b2bacb..284e302ea 100644 --- a/src/ShaderNode/DataModels/OutputValue.hpp +++ b/src/ShaderNode/DataModels/OutputValue.hpp @@ -16,7 +16,7 @@ class OutputValue : public ShaderNode void BuildNodeEdition(QFormLayout* layout) override; - Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override; + Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override; QString caption() const override { return "Output"; } QString name() const override { return "Output"; } diff --git a/src/ShaderNode/DataModels/SampleTexture.cpp b/src/ShaderNode/DataModels/SampleTexture.cpp index 3f0036519..2c9e2dcac 100644 --- a/src/ShaderNode/DataModels/SampleTexture.cpp +++ b/src/ShaderNode/DataModels/SampleTexture.cpp @@ -91,7 +91,7 @@ bool SampleTexture::ComputePreview(QPixmap& pixmap) return true; } -Nz::ShaderAst::ExpressionPtr SampleTexture::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const +Nz::ShaderNodes::ExpressionPtr SampleTexture::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const { assert(m_texture); assert(m_uv); diff --git a/src/ShaderNode/DataModels/SampleTexture.hpp b/src/ShaderNode/DataModels/SampleTexture.hpp index 7afb77e0f..5b1dd98fd 100644 --- a/src/ShaderNode/DataModels/SampleTexture.hpp +++ b/src/ShaderNode/DataModels/SampleTexture.hpp @@ -17,7 +17,7 @@ class SampleTexture : public ShaderNode SampleTexture(ShaderGraph& graph); ~SampleTexture() = default; - Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const override; + Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const override; QString caption() const override { return "Sample texture"; } QString name() const override { return "SampleTexture"; } diff --git a/src/ShaderNode/DataModels/ShaderNode.hpp b/src/ShaderNode/DataModels/ShaderNode.hpp index e7ac130c9..30e2504ca 100644 --- a/src/ShaderNode/DataModels/ShaderNode.hpp +++ b/src/ShaderNode/DataModels/ShaderNode.hpp @@ -4,7 +4,7 @@ #define NAZARA_SHADERNODES_SHADERNODE_HPP #include -#include +#include #include #include #include @@ -23,7 +23,7 @@ class ShaderNode : public QtNodes::NodeDataModel inline void DisablePreview(); void EnablePreview(bool enable = true); - virtual Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const = 0; + virtual Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const = 0; inline ShaderGraph& GetGraph(); inline const ShaderGraph& GetGraph() const; inline const std::string& GetVariableName() const; diff --git a/src/ShaderNode/DataModels/TextureValue.cpp b/src/ShaderNode/DataModels/TextureValue.cpp index d543a502e..2e25eaa03 100644 --- a/src/ShaderNode/DataModels/TextureValue.cpp +++ b/src/ShaderNode/DataModels/TextureValue.cpp @@ -106,7 +106,7 @@ void TextureValue::BuildNodeEdition(QFormLayout* layout) layout->addRow(tr("Texture"), textureSelection); } -Nz::ShaderAst::ExpressionPtr TextureValue::GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const +Nz::ShaderNodes::ExpressionPtr TextureValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const { if (!m_currentTextureIndex) throw std::runtime_error("invalid texture input"); @@ -115,18 +115,18 @@ Nz::ShaderAst::ExpressionPtr TextureValue::GetExpression(Nz::ShaderAst::Expressi const auto& textureEntry = GetGraph().GetTexture(*m_currentTextureIndex); - Nz::ShaderAst::ExpressionType expression = [&] + Nz::ShaderNodes::ExpressionType expression = [&] { switch (textureEntry.type) { - case TextureType::Sampler2D: return Nz::ShaderAst::ExpressionType::Sampler2D; + case TextureType::Sampler2D: return Nz::ShaderNodes::ExpressionType::Sampler2D; } assert(false); throw std::runtime_error("Unhandled texture type"); }(); - return Nz::ShaderBuilder::Uniform(textureEntry.name, expression); + return Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Uniform(textureEntry.name, expression)); } auto TextureValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType diff --git a/src/ShaderNode/DataModels/TextureValue.hpp b/src/ShaderNode/DataModels/TextureValue.hpp index 89cfcff21..dfb7efaff 100644 --- a/src/ShaderNode/DataModels/TextureValue.hpp +++ b/src/ShaderNode/DataModels/TextureValue.hpp @@ -18,7 +18,7 @@ class TextureValue : public ShaderNode void BuildNodeEdition(QFormLayout* layout) override; - Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const override; + Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const override; QString caption() const override { return "Texture"; } QString name() const override { return "Texture"; } diff --git a/src/ShaderNode/DataModels/VecBinOp.hpp b/src/ShaderNode/DataModels/VecBinOp.hpp index 977b0d3ba..d00049c04 100644 --- a/src/ShaderNode/DataModels/VecBinOp.hpp +++ b/src/ShaderNode/DataModels/VecBinOp.hpp @@ -6,14 +6,14 @@ #include #include -template +template class VecBinOp : public ShaderNode { public: VecBinOp(ShaderGraph& graph); ~VecBinOp() = default; - Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override; + Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override; unsigned int nPorts(QtNodes::PortType portType) const override; @@ -37,10 +37,10 @@ class VecBinOp : public ShaderNode std::shared_ptr m_output; }; -class VecAdd : public VecBinOp +class VecAdd : public VecBinOp { public: - using VecBinOp::VecBinOp; + using VecBinOp::VecBinOp; QString caption() const override; QString name() const override; @@ -48,10 +48,10 @@ class VecAdd : public VecBinOp void ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount) override; }; -class VecMul : public VecBinOp +class VecMul : public VecBinOp { public: - using VecBinOp::VecBinOp; + using VecBinOp::VecBinOp; QString caption() const override; QString name() const override; @@ -59,10 +59,10 @@ class VecMul : public VecBinOp void ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount) override; }; -class VecSub : public VecBinOp +class VecSub : public VecBinOp { public: - using VecBinOp::VecBinOp; + using VecBinOp::VecBinOp; QString caption() const override; QString name() const override; @@ -70,10 +70,10 @@ class VecSub : public VecBinOp void ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount) override; }; -class VecDiv : public VecBinOp +class VecDiv : public VecBinOp { public: - using VecBinOp::VecBinOp; + using VecBinOp::VecBinOp; QString caption() const override; QString name() const override; diff --git a/src/ShaderNode/DataModels/VecBinOp.inl b/src/ShaderNode/DataModels/VecBinOp.inl index 5a12aff08..255946543 100644 --- a/src/ShaderNode/DataModels/VecBinOp.inl +++ b/src/ShaderNode/DataModels/VecBinOp.inl @@ -1,15 +1,15 @@ #include #include -template +template VecBinOp::VecBinOp(ShaderGraph& graph) : ShaderNode(graph) { UpdateOutput(); } -template -Nz::ShaderAst::ExpressionPtr VecBinOp::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const +template +Nz::ShaderNodes::ExpressionPtr VecBinOp::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const { assert(count == 2); using BuilderType = typename Nz::ShaderBuilder::template BinOpBuilder; @@ -17,7 +17,7 @@ Nz::ShaderAst::ExpressionPtr VecBinOp::GetExpression(Nz::ShaderAst::Expre return builder(expressions[0], expressions[1]); } -template +template QtNodes::NodeDataType VecBinOp::dataType(QtNodes::PortType /*portType*/, QtNodes::PortIndex portIndex) const { assert(portIndex == 0 || portIndex == 1); @@ -25,7 +25,7 @@ QtNodes::NodeDataType VecBinOp::dataType(QtNodes::PortType /*portType*/, return VecData::Type(); } -template +template unsigned int VecBinOp::nPorts(QtNodes::PortType portType) const { switch (portType) @@ -37,14 +37,14 @@ unsigned int VecBinOp::nPorts(QtNodes::PortType portType) const return 0; } -template +template std::shared_ptr VecBinOp::outData(QtNodes::PortIndex port) { assert(port == 0); return m_output; } -template +template void VecBinOp::setInData(std::shared_ptr value, int index) { assert(index == 0 || index == 1); @@ -65,7 +65,7 @@ void VecBinOp::setInData(std::shared_ptr value, int in UpdateOutput(); } -template +template QtNodes::NodeValidationState VecBinOp::validationState() const { if (!m_lhs || !m_rhs) @@ -77,7 +77,7 @@ QtNodes::NodeValidationState VecBinOp::validationState() const return QtNodes::NodeValidationState::Valid; } -template +template QString VecBinOp::validationMessage() const { if (!m_lhs || !m_rhs) @@ -89,7 +89,7 @@ QString VecBinOp::validationMessage() const return QString(); } -template +template bool VecBinOp::ComputePreview(QPixmap& pixmap) { if (!m_lhs || !m_rhs) @@ -99,7 +99,7 @@ bool VecBinOp::ComputePreview(QPixmap& pixmap) return true; } -template +template void VecBinOp::UpdateOutput() { if (validationState() != QtNodes::NodeValidationState::Valid) diff --git a/src/ShaderNode/DataModels/VecDot.cpp b/src/ShaderNode/DataModels/VecDot.cpp index 47b67b72c..48aac108c 100644 --- a/src/ShaderNode/DataModels/VecDot.cpp +++ b/src/ShaderNode/DataModels/VecDot.cpp @@ -1,5 +1,5 @@ #include -#include +#include VecDot::VecDot(ShaderGraph& graph) : ShaderNode(graph) @@ -8,11 +8,11 @@ ShaderNode(graph) UpdateOutput(); } -Nz::ShaderAst::ExpressionPtr VecDot::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const +Nz::ShaderNodes::ExpressionPtr VecDot::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const { assert(count == 2); - using namespace Nz::ShaderAst; - return BinaryFunc::Build(BinaryIntrinsic::DotProduct, expressions[0], expressions[1]); + using namespace Nz::ShaderNodes; + return IntrinsicCall::Build(IntrinsicType::DotProduct, { expressions[0], expressions[1] }); } QString VecDot::caption() const diff --git a/src/ShaderNode/DataModels/VecDot.hpp b/src/ShaderNode/DataModels/VecDot.hpp index dc92bb5c8..74e6a7266 100644 --- a/src/ShaderNode/DataModels/VecDot.hpp +++ b/src/ShaderNode/DataModels/VecDot.hpp @@ -13,7 +13,7 @@ class VecDot : public ShaderNode VecDot(ShaderGraph& graph); ~VecDot() = default; - Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override; + Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override; QString caption() const override; QString name() const override; diff --git a/src/ShaderNode/DataModels/VecFloatMul.cpp b/src/ShaderNode/DataModels/VecFloatMul.cpp index f4ec6f957..3c10d08e2 100644 --- a/src/ShaderNode/DataModels/VecFloatMul.cpp +++ b/src/ShaderNode/DataModels/VecFloatMul.cpp @@ -1,5 +1,5 @@ #include -#include +#include VecFloatMul::VecFloatMul(ShaderGraph& graph) : ShaderNode(graph) @@ -7,10 +7,10 @@ ShaderNode(graph) UpdateOutput(); } -Nz::ShaderAst::ExpressionPtr VecFloatMul::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const +Nz::ShaderNodes::ExpressionPtr VecFloatMul::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const { assert(count == 2); - using namespace Nz::ShaderAst; + using namespace Nz::ShaderNodes; return BinaryOp::Build(BinaryType::Multiply, expressions[0], expressions[1]); } diff --git a/src/ShaderNode/DataModels/VecFloatMul.hpp b/src/ShaderNode/DataModels/VecFloatMul.hpp index c4a9a97f7..dd1fbd1af 100644 --- a/src/ShaderNode/DataModels/VecFloatMul.hpp +++ b/src/ShaderNode/DataModels/VecFloatMul.hpp @@ -13,7 +13,7 @@ class VecFloatMul : public ShaderNode VecFloatMul(ShaderGraph& graph); ~VecFloatMul() = default; - Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override; + Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override; QString caption() const override; QString name() const override; diff --git a/src/ShaderNode/DataModels/VecValue.hpp b/src/ShaderNode/DataModels/VecValue.hpp index fe94e67cb..86cd93692 100644 --- a/src/ShaderNode/DataModels/VecValue.hpp +++ b/src/ShaderNode/DataModels/VecValue.hpp @@ -29,7 +29,7 @@ class VecValue : public ShaderNode void BuildNodeEdition(QFormLayout* layout) override; - Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override; + Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override; private: bool ComputePreview(QPixmap& pixmap) override; diff --git a/src/ShaderNode/DataModels/VecValue.inl b/src/ShaderNode/DataModels/VecValue.inl index a3ea2068e..8e158b94b 100644 --- a/src/ShaderNode/DataModels/VecValue.inl +++ b/src/ShaderNode/DataModels/VecValue.inl @@ -94,7 +94,7 @@ void VecValue::BuildNodeEdition(QFormLayout* layout) } template -Nz::ShaderAst::ExpressionPtr VecValue::GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const +Nz::ShaderNodes::ExpressionPtr VecValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const { assert(count == 0); diff --git a/src/ShaderNode/DataTypes/TextureData.hpp b/src/ShaderNode/DataTypes/TextureData.hpp index 778e66e05..632fa5bde 100644 --- a/src/ShaderNode/DataTypes/TextureData.hpp +++ b/src/ShaderNode/DataTypes/TextureData.hpp @@ -3,7 +3,7 @@ #ifndef NAZARA_SHADERNODES_TEXTUREDATA_HPP #define NAZARA_SHADERNODES_TEXTUREDATA_HPP -#include +#include #include #include diff --git a/src/ShaderNode/DataTypes/VecData.cpp b/src/ShaderNode/DataTypes/VecData.cpp index c1f883079..2d4a38001 100644 --- a/src/ShaderNode/DataTypes/VecData.cpp +++ b/src/ShaderNode/DataTypes/VecData.cpp @@ -2,13 +2,13 @@ #include #include -Nz::ShaderAst::ExpressionType VecData::GetExpressionType() const +Nz::ShaderNodes::ExpressionType VecData::GetExpressionType() const { switch (componentCount) { - case 2: return Nz::ShaderAst::ExpressionType::Float2; - case 3: return Nz::ShaderAst::ExpressionType::Float3; - case 4: return Nz::ShaderAst::ExpressionType::Float4; + case 2: return Nz::ShaderNodes::ExpressionType::Float2; + case 3: return Nz::ShaderNodes::ExpressionType::Float3; + case 4: return Nz::ShaderNodes::ExpressionType::Float4; default: break; } diff --git a/src/ShaderNode/DataTypes/VecData.hpp b/src/ShaderNode/DataTypes/VecData.hpp index 5c19be942..f333f9483 100644 --- a/src/ShaderNode/DataTypes/VecData.hpp +++ b/src/ShaderNode/DataTypes/VecData.hpp @@ -3,7 +3,7 @@ #ifndef NAZARA_SHADERNODES_VECDATA_HPP #define NAZARA_SHADERNODES_VECDATA_HPP -#include +#include #include #include @@ -13,7 +13,7 @@ struct VecData : public QtNodes::NodeData inline QtNodes::NodeDataType type() const override; - Nz::ShaderAst::ExpressionType GetExpressionType() const; + Nz::ShaderNodes::ExpressionType GetExpressionType() const; static inline QtNodes::NodeDataType Type(); @@ -27,28 +27,28 @@ struct VecExpressionTypeHelper; template<> struct VecExpressionTypeHelper<1> { - static constexpr Nz::ShaderAst::ExpressionType ExpressionType = Nz::ShaderAst::ExpressionType::Float1; + static constexpr Nz::ShaderNodes::ExpressionType ExpressionType = Nz::ShaderNodes::ExpressionType::Float1; }; template<> struct VecExpressionTypeHelper<2> { - static constexpr Nz::ShaderAst::ExpressionType ExpressionType = Nz::ShaderAst::ExpressionType::Float2; + static constexpr Nz::ShaderNodes::ExpressionType ExpressionType = Nz::ShaderNodes::ExpressionType::Float2; }; template<> struct VecExpressionTypeHelper<3> { - static constexpr Nz::ShaderAst::ExpressionType ExpressionType = Nz::ShaderAst::ExpressionType::Float3; + static constexpr Nz::ShaderNodes::ExpressionType ExpressionType = Nz::ShaderNodes::ExpressionType::Float3; }; template<> struct VecExpressionTypeHelper<4> { - static constexpr Nz::ShaderAst::ExpressionType ExpressionType = Nz::ShaderAst::ExpressionType::Float4; + static constexpr Nz::ShaderNodes::ExpressionType ExpressionType = Nz::ShaderNodes::ExpressionType::Float4; }; -template constexpr Nz::ShaderAst::ExpressionType VecExpressionType = VecExpressionTypeHelper::template ExpressionType; +template constexpr Nz::ShaderNodes::ExpressionType VecExpressionType = VecExpressionTypeHelper::template ExpressionType; struct VecTypeDummy {}; diff --git a/src/ShaderNode/ShaderGraph.cpp b/src/ShaderNode/ShaderGraph.cpp index 06b0ddea0..880afb2a9 100644 --- a/src/ShaderNode/ShaderGraph.cpp +++ b/src/ShaderNode/ShaderGraph.cpp @@ -46,9 +46,9 @@ m_flowScene(BuildRegistry()) }); // Test - AddInput("UV", InOutType::Float2, InputRole::TexCoord, 0); - AddOutput("RenderTarget0", InOutType::Float4); - AddTexture("Potato", TextureType::Sampler2D); + AddInput("UV", InOutType::Float2, InputRole::TexCoord, 0, 0); + AddOutput("RenderTarget0", InOutType::Float4, 0); + AddTexture("Potato", TextureType::Sampler2D, 1); UpdateTexturePreview(0, QImage(R"(C:\Users\Lynix\Pictures\potatavril.png)")); @@ -79,10 +79,11 @@ ShaderGraph::~ShaderGraph() m_flowScene.clearScene(); } -std::size_t ShaderGraph::AddInput(std::string name, InOutType type, InputRole role, std::size_t roleIndex) +std::size_t ShaderGraph::AddInput(std::string name, InOutType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex) { std::size_t index = m_inputs.size(); auto& inputEntry = m_inputs.emplace_back(); + inputEntry.locationIndex = locationIndex; inputEntry.name = std::move(name); inputEntry.role = role; inputEntry.roleIndex = roleIndex; @@ -93,10 +94,11 @@ std::size_t ShaderGraph::AddInput(std::string name, InOutType type, InputRole ro return index; } -std::size_t ShaderGraph::AddOutput(std::string name, InOutType type) +std::size_t ShaderGraph::AddOutput(std::string name, InOutType type, std::size_t locationIndex) { std::size_t index = m_outputs.size(); auto& outputEntry = m_outputs.emplace_back(); + outputEntry.locationIndex = locationIndex; outputEntry.name = std::move(name); outputEntry.type = type; @@ -105,10 +107,11 @@ std::size_t ShaderGraph::AddOutput(std::string name, InOutType type) return index; } -std::size_t ShaderGraph::AddTexture(std::string name, TextureType type) +std::size_t ShaderGraph::AddTexture(std::string name, TextureType type, std::size_t bindingIndex) { std::size_t index = m_textures.size(); auto& textureEntry = m_textures.emplace_back(); + textureEntry.bindingIndex = bindingIndex; textureEntry.name = std::move(name); textureEntry.type = type; @@ -141,6 +144,7 @@ void ShaderGraph::Load(const QJsonObject& data) QJsonObject inputDoc = inputDocRef.toObject(); InputEntry& input = m_inputs.emplace_back(); + input.locationIndex = static_cast(inputDoc["locationIndex"].toInt(0)); input.name = inputDoc["name"].toString().toStdString(); input.role = DecodeEnum(inputDoc["role"].toString().toStdString()).value(); input.roleIndex = static_cast(inputDoc["roleIndex"].toInt(0)); @@ -155,6 +159,7 @@ void ShaderGraph::Load(const QJsonObject& data) QJsonObject outputDoc = outputDocRef.toObject(); OutputEntry& output = m_outputs.emplace_back(); + output.locationIndex = static_cast(outputDoc["locationIndex"].toInt(0)); output.name = outputDoc["name"].toString().toStdString(); output.type = DecodeEnum(outputDoc["type"].toString().toStdString()).value(); } @@ -167,6 +172,7 @@ void ShaderGraph::Load(const QJsonObject& data) QJsonObject textureDoc = textureDocRef.toObject(); TextureEntry& texture = m_textures.emplace_back(); + texture.bindingIndex = static_cast(textureDoc["bindingIndex"].toInt(0)); texture.name = textureDoc["name"].toString().toStdString(); texture.type = DecodeEnum(textureDoc["type"].toString().toStdString()).value(); } @@ -189,6 +195,7 @@ QJsonObject ShaderGraph::Save() for (const auto& input : m_inputs) { QJsonObject inputDoc; + inputDoc["locationIndex"] = int(input.locationIndex); inputDoc["name"] = QString::fromStdString(input.name); inputDoc["role"] = QString(EnumToString(input.role)); inputDoc["roleIndex"] = int(input.roleIndex); @@ -204,6 +211,7 @@ QJsonObject ShaderGraph::Save() for (const auto& output : m_outputs) { QJsonObject outputDoc; + outputDoc["locationIndex"] = int(output.locationIndex); outputDoc["name"] = QString::fromStdString(output.name); outputDoc["type"] = QString(EnumToString(output.type)); @@ -217,6 +225,7 @@ QJsonObject ShaderGraph::Save() for (const auto& texture : m_textures) { QJsonObject textureDoc; + textureDoc["bindingIndex"] = int(texture.bindingIndex); textureDoc["name"] = QString::fromStdString(texture.name); textureDoc["type"] = QString(EnumToString(texture.type)); @@ -247,9 +256,9 @@ QJsonObject ShaderGraph::Save() return sceneJson; } -Nz::ShaderAst::StatementPtr ShaderGraph::ToAst() +Nz::ShaderNodes::StatementPtr ShaderGraph::ToAst() { - std::vector statements; + std::vector statements; QHash usageCount; std::function DetectVariables; @@ -278,13 +287,13 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst() DetectVariables(node); }); - QHash variableExpressions; + QHash variableExpressions; unsigned int varCount = 0; std::unordered_set usedVariableNames; - std::function HandleNode; - HandleNode = [&](QtNodes::Node* node) -> Nz::ShaderAst::ExpressionPtr + std::function HandleNode; + HandleNode = [&](QtNodes::Node* node) -> Nz::ShaderNodes::ExpressionPtr { ShaderNode* shaderNode = static_cast(node->nodeDataModel()); if (shaderNode->validationState() != QtNodes::NodeValidationState::Valid) @@ -298,7 +307,7 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst() assert(it != usageCount.end()); std::size_t inputCount = shaderNode->nPorts(QtNodes::PortType::In); - Nz::StackArray expressions = NazaraStackArray(Nz::ShaderAst::ExpressionPtr, inputCount); + Nz::StackArray expressions = NazaraStackArray(Nz::ShaderNodes::ExpressionPtr, inputCount); std::size_t i = 0; for (const auto& connectionSet : node->nodeState().getEntries(QtNodes::PortType::In)) @@ -316,8 +325,8 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst() const std::string& variableName = shaderNode->GetVariableName(); if (*it > 1 || !variableName.empty()) { - Nz::ShaderAst::ExpressionPtr varExpression; - if (expression->GetExpressionCategory() == Nz::ShaderAst::ExpressionCategory::RValue) + Nz::ShaderNodes::ExpressionPtr varExpression; + if (expression->GetExpressionCategory() == Nz::ShaderNodes::ExpressionCategory::RValue) { std::string name; if (variableName.empty()) @@ -330,10 +339,10 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst() usedVariableNames.insert(name); - auto variable = Nz::ShaderBuilder::Variable(std::move(name), expression->GetExpressionType()); + auto variable = Nz::ShaderBuilder::Local(std::move(name), expression->GetExpressionType()); statements.emplace_back(Nz::ShaderBuilder::DeclareVariable(variable, expression)); - varExpression = variable; + varExpression = Nz::ShaderBuilder::Identifier(variable); } else varExpression = expression; @@ -354,13 +363,14 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst() } }); - return Nz::ShaderAst::StatementBlock::Build(std::move(statements)); + return Nz::ShaderNodes::StatementBlock::Build(std::move(statements)); } -void ShaderGraph::UpdateInput(std::size_t inputIndex, std::string name, InOutType type, InputRole role, std::size_t roleIndex) +void ShaderGraph::UpdateInput(std::size_t inputIndex, std::string name, InOutType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex) { assert(inputIndex < m_inputs.size()); auto& inputEntry = m_inputs[inputIndex]; + inputEntry.locationIndex = locationIndex; inputEntry.name = std::move(name); inputEntry.role = role; inputEntry.roleIndex = roleIndex; @@ -369,10 +379,11 @@ void ShaderGraph::UpdateInput(std::size_t inputIndex, std::string name, InOutTyp OnInputUpdate(this, inputIndex); } -void ShaderGraph::UpdateOutput(std::size_t outputIndex, std::string name, InOutType type) +void ShaderGraph::UpdateOutput(std::size_t outputIndex, std::string name, InOutType type, std::size_t locationIndex) { assert(outputIndex < m_outputs.size()); auto& outputEntry = m_outputs[outputIndex]; + outputEntry.locationIndex = locationIndex; outputEntry.name = std::move(name); outputEntry.type = type; diff --git a/src/ShaderNode/ShaderGraph.hpp b/src/ShaderNode/ShaderGraph.hpp index 536a01dcc..add7e52ab 100644 --- a/src/ShaderNode/ShaderGraph.hpp +++ b/src/ShaderNode/ShaderGraph.hpp @@ -4,7 +4,7 @@ #define NAZARA_SHADERNODES_SHADERGRAPH_HPP #include -#include +#include #include #include #include @@ -23,9 +23,9 @@ class ShaderGraph ShaderGraph(); ~ShaderGraph(); - std::size_t AddInput(std::string name, InOutType type, InputRole role, std::size_t roleIndex); - std::size_t AddOutput(std::string name, InOutType type); - std::size_t AddTexture(std::string name, TextureType type); + std::size_t AddInput(std::string name, InOutType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex); + std::size_t AddOutput(std::string name, InOutType type, std::size_t locationIndex); + std::size_t AddTexture(std::string name, TextureType type, std::size_t bindingIndex); void Clear(); @@ -44,14 +44,15 @@ class ShaderGraph void Load(const QJsonObject& data); QJsonObject Save(); - Nz::ShaderAst::StatementPtr ToAst(); + Nz::ShaderNodes::StatementPtr ToAst(); - void UpdateInput(std::size_t inputIndex, std::string name, InOutType type, InputRole role, std::size_t roleIndex); - void UpdateOutput(std::size_t outputIndex, std::string name, InOutType type); + void UpdateInput(std::size_t inputIndex, std::string name, InOutType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex); + void UpdateOutput(std::size_t outputIndex, std::string name, InOutType type, std::size_t locationIndex); void UpdateTexturePreview(std::size_t texture, QImage preview); struct InputEntry { + std::size_t locationIndex; std::size_t roleIndex; std::string name; InputRole role; @@ -60,12 +61,14 @@ class ShaderGraph struct OutputEntry { + std::size_t locationIndex; std::string name; InOutType type; }; struct TextureEntry { + std::size_t bindingIndex; std::string name; TextureType type; QImage preview; diff --git a/src/ShaderNode/Widgets/InputEditDialog.cpp b/src/ShaderNode/Widgets/InputEditDialog.cpp index 09f711f3d..bd56fd598 100644 --- a/src/ShaderNode/Widgets/InputEditDialog.cpp +++ b/src/ShaderNode/Widgets/InputEditDialog.cpp @@ -23,6 +23,8 @@ QDialog(parent) for (std::size_t i = 0; i < InputRoleCount; ++i) m_roleList->addItem(EnumToString(static_cast(i))); + m_locationIndex = new QSpinBox; + m_roleIndex = new QSpinBox; QFormLayout* formLayout = new QFormLayout; @@ -30,6 +32,7 @@ QDialog(parent) formLayout->addRow(tr("Type"), m_typeList); formLayout->addRow(tr("Role"), m_roleList); formLayout->addRow(tr("Role index"), m_roleIndex); + formLayout->addRow(tr("Input index"), m_locationIndex); QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); connect(buttonBox, &QDialogButtonBox::accepted, this, &InputEditDialog::OnAccept); @@ -46,6 +49,7 @@ InputEditDialog::InputEditDialog(const InputInfo& input, QWidget* parent) : InputEditDialog(parent) { m_inputName->setText(QString::fromStdString(input.name)); + m_locationIndex->setValue(int(input.locationIndex)); m_roleIndex->setValue(int(input.roleIndex)); m_roleList->setCurrentText(EnumToString(input.role)); m_typeList->setCurrentText(EnumToString(input.type)); @@ -54,6 +58,7 @@ InputEditDialog(parent) InputInfo InputEditDialog::GetInputInfo() const { InputInfo inputInfo; + inputInfo.locationIndex = static_cast(m_locationIndex->value()); inputInfo.name = m_inputName->text().toStdString(); inputInfo.role = static_cast(m_roleList->currentIndex()); inputInfo.roleIndex = static_cast(m_roleIndex->value()); diff --git a/src/ShaderNode/Widgets/InputEditDialog.hpp b/src/ShaderNode/Widgets/InputEditDialog.hpp index 633b9c99d..0f6655088 100644 --- a/src/ShaderNode/Widgets/InputEditDialog.hpp +++ b/src/ShaderNode/Widgets/InputEditDialog.hpp @@ -12,6 +12,7 @@ class QSpinBox; struct InputInfo { + std::size_t locationIndex; std::size_t roleIndex; std::string name; InputRole role; @@ -33,6 +34,7 @@ class InputEditDialog : public QDialog QComboBox* m_roleList; QComboBox* m_typeList; QLineEdit* m_inputName; + QSpinBox* m_locationIndex; QSpinBox* m_roleIndex; }; diff --git a/src/ShaderNode/Widgets/InputEditor.cpp b/src/ShaderNode/Widgets/InputEditor.cpp index a0dee923d..f281c327a 100644 --- a/src/ShaderNode/Widgets/InputEditor.cpp +++ b/src/ShaderNode/Widgets/InputEditor.cpp @@ -39,7 +39,7 @@ void InputEditor::OnAddInput() connect(dialog, &QDialog::accepted, [this, dialog] { InputInfo inputInfo = dialog->GetInputInfo(); - m_shaderGraph.AddInput(std::move(inputInfo.name), inputInfo.type, inputInfo.role, inputInfo.roleIndex); + m_shaderGraph.AddInput(std::move(inputInfo.name), inputInfo.type, inputInfo.role, inputInfo.roleIndex, inputInfo.locationIndex); }); dialog->open(); @@ -60,7 +60,7 @@ void InputEditor::OnEditInput(int inputIndex) connect(dialog, &QDialog::accepted, [this, dialog, inputIndex] { InputInfo inputInfo = dialog->GetInputInfo(); - m_shaderGraph.UpdateInput(inputIndex, std::move(inputInfo.name), inputInfo.type, inputInfo.role, inputInfo.roleIndex); + m_shaderGraph.UpdateInput(inputIndex, std::move(inputInfo.name), inputInfo.type, inputInfo.role, inputInfo.roleIndex, inputInfo.locationIndex); }); dialog->open(); diff --git a/src/ShaderNode/Widgets/MainWindow.cpp b/src/ShaderNode/Widgets/MainWindow.cpp index c30007f14..c59a59254 100644 --- a/src/ShaderNode/Widgets/MainWindow.cpp +++ b/src/ShaderNode/Widgets/MainWindow.cpp @@ -1,5 +1,7 @@ #include +#include #include +#include #include #include #include @@ -84,8 +86,6 @@ void MainWindow::BuildMenu() QMenu* shader = menu->addMenu(tr("&Shader")); { - QtNodes::FlowScene* scene = &m_shaderGraph.GetScene(); - QAction* loadShader = shader->addAction(tr("Load...")); QObject::connect(loadShader, &QAction::triggered, this, &MainWindow::OnLoad); QAction* saveShader = shader->addAction(tr("Save...")); @@ -101,8 +101,52 @@ void MainWindow::OnCompileToGLSL() { try { + Nz::ShaderNodes::StatementPtr shaderAst = m_shaderGraph.ToAst(); + + Nz::File file("shader.shader", Nz::OpenMode_WriteOnly); + file.Write(Nz::ShaderNodes::Serialize(shaderAst)); + + //TODO: Put in another function + auto GetExpressionFromInOut = [&] (InOutType type) + { + switch (type) + { + case InOutType::Bool: return Nz::ShaderNodes::ExpressionType::Boolean; + case InOutType::Float1: return Nz::ShaderNodes::ExpressionType::Float1; + case InOutType::Float2: return Nz::ShaderNodes::ExpressionType::Float2; + case InOutType::Float3: return Nz::ShaderNodes::ExpressionType::Float3; + case InOutType::Float4: return Nz::ShaderNodes::ExpressionType::Float4; + } + + assert(false); + throw std::runtime_error("Unhandled input type"); + }; + + auto GetExpressionFromTexture = [&](TextureType type) + { + switch (type) + { + case TextureType::Sampler2D: return Nz::ShaderNodes::ExpressionType::Sampler2D; + } + + assert(false); + throw std::runtime_error("Unhandled texture type"); + }; + + Nz::ShaderAst shader; + for (const auto& input : m_shaderGraph.GetInputs()) + shader.AddInput(input.name, GetExpressionFromInOut(input.type), input.locationIndex); + + for (const auto& output : m_shaderGraph.GetOutputs()) + shader.AddOutput(output.name, GetExpressionFromInOut(output.type), output.locationIndex); + + for (const auto& uniform : m_shaderGraph.GetTextures()) + shader.AddUniform(uniform.name, GetExpressionFromTexture(uniform.type), uniform.bindingIndex); + + shader.AddFunction("main", shaderAst); + Nz::GlslWriter writer; - Nz::String glsl = writer.Generate(m_shaderGraph.ToAst()); + Nz::String glsl = writer.Generate(shader); std::cout << glsl << std::endl; diff --git a/src/ShaderNode/Widgets/OutputEditDialog.cpp b/src/ShaderNode/Widgets/OutputEditDialog.cpp index 23f092f75..d2c83e58e 100644 --- a/src/ShaderNode/Widgets/OutputEditDialog.cpp +++ b/src/ShaderNode/Widgets/OutputEditDialog.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include OutputEditDialog::OutputEditDialog(QWidget* parent) : @@ -18,9 +19,12 @@ QDialog(parent) for (std::size_t i = 0; i < InOutTypeCount; ++i) m_typeList->addItem(EnumToString(static_cast(i))); + m_locationIndex = new QSpinBox; + QFormLayout* formLayout = new QFormLayout; formLayout->addRow(tr("Name"), m_outputName); formLayout->addRow(tr("Type"), m_typeList); + formLayout->addRow(tr("Output index"), m_locationIndex); QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); connect(buttonBox, &QDialogButtonBox::accepted, this, &OutputEditDialog::OnAccept); @@ -33,16 +37,18 @@ QDialog(parent) setLayout(verticalLayout); } -OutputEditDialog::OutputEditDialog(const OutputInfo& input, QWidget* parent) : +OutputEditDialog::OutputEditDialog(const OutputInfo& output, QWidget* parent) : OutputEditDialog(parent) { - m_outputName->setText(QString::fromStdString(input.name)); - m_typeList->setCurrentText(EnumToString(input.type)); + m_locationIndex->setValue(int(output.locationIndex)); + m_outputName->setText(QString::fromStdString(output.name)); + m_typeList->setCurrentText(EnumToString(output.type)); } OutputInfo OutputEditDialog::GetOutputInfo() const { OutputInfo inputInfo; + inputInfo.locationIndex = static_cast(m_locationIndex->value()); inputInfo.name = m_outputName->text().toStdString(); inputInfo.type = static_cast(m_typeList->currentIndex()); diff --git a/src/ShaderNode/Widgets/OutputEditDialog.hpp b/src/ShaderNode/Widgets/OutputEditDialog.hpp index 3c06323dd..6a8cc68fb 100644 --- a/src/ShaderNode/Widgets/OutputEditDialog.hpp +++ b/src/ShaderNode/Widgets/OutputEditDialog.hpp @@ -8,9 +8,11 @@ class QComboBox; class QLineEdit; +class QSpinBox; struct OutputInfo { + std::size_t locationIndex; std::string name; InOutType type; }; @@ -19,7 +21,7 @@ class OutputEditDialog : public QDialog { public: OutputEditDialog(QWidget* parent = nullptr); - OutputEditDialog(const OutputInfo& input, QWidget* parent = nullptr); + OutputEditDialog(const OutputInfo& output, QWidget* parent = nullptr); ~OutputEditDialog() = default; OutputInfo GetOutputInfo() const; @@ -29,6 +31,7 @@ class OutputEditDialog : public QDialog QComboBox* m_typeList; QLineEdit* m_outputName; + QSpinBox* m_locationIndex; }; #include diff --git a/src/ShaderNode/Widgets/OutputEditor.cpp b/src/ShaderNode/Widgets/OutputEditor.cpp index ba317de07..868168c8a 100644 --- a/src/ShaderNode/Widgets/OutputEditor.cpp +++ b/src/ShaderNode/Widgets/OutputEditor.cpp @@ -38,8 +38,8 @@ void OutputEditor::OnAddOutput() dialog->setAttribute(Qt::WA_DeleteOnClose, true); connect(dialog, &QDialog::accepted, [this, dialog] { - OutputInfo inputInfo = dialog->GetOutputInfo(); - m_shaderGraph.AddOutput(std::move(inputInfo.name), inputInfo.type); + OutputInfo outputInfo = dialog->GetOutputInfo(); + m_shaderGraph.AddOutput(std::move(outputInfo.name), outputInfo.type, outputInfo.locationIndex); }); dialog->open(); @@ -57,8 +57,8 @@ void OutputEditor::OnEditOutput(int inputIndex) dialog->setAttribute(Qt::WA_DeleteOnClose, true); connect(dialog, &QDialog::accepted, [this, dialog, inputIndex] { - OutputInfo inputInfo = dialog->GetOutputInfo(); - m_shaderGraph.UpdateOutput(inputIndex, std::move(inputInfo.name), inputInfo.type); + OutputInfo outputInfo = dialog->GetOutputInfo(); + m_shaderGraph.UpdateOutput(inputIndex, std::move(outputInfo.name), outputInfo.type, outputInfo.locationIndex); }); dialog->open();