From 8467c79021982804d951191ced9a36b6ac28698a Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 5 Jun 2020 19:47:29 +0200 Subject: [PATCH] Renderer: Add shader serialization --- include/Nazara/Renderer/GlslWriter.hpp | 28 +- include/Nazara/Renderer/ShaderAst.hpp | 318 +++++++++------- include/Nazara/Renderer/ShaderAst.inl | 364 ++++++++++-------- include/Nazara/Renderer/ShaderBuilder.inl | 16 +- include/Nazara/Renderer/ShaderSerializer.hpp | 111 ++++++ include/Nazara/Renderer/ShaderSerializer.inl | 79 ++++ include/Nazara/Renderer/ShaderVisitor.hpp | 50 +++ include/Nazara/Renderer/ShaderWriter.hpp | 29 +- src/Nazara/Renderer/GlslWriter.cpp | 65 ++-- src/Nazara/Renderer/Renderer.cpp | 2 +- src/Nazara/Renderer/ShaderAst.cpp | 91 ++--- src/Nazara/Renderer/ShaderSerializer.cpp | 376 +++++++++++++++++++ src/Nazara/Renderer/ShaderVisitor.cpp | 29 ++ src/Nazara/Renderer/ShaderWriter.cpp | 14 - src/ShaderNode/ShaderGraph.cpp | 2 +- 15 files changed, 1131 insertions(+), 443 deletions(-) create mode 100644 include/Nazara/Renderer/ShaderSerializer.hpp create mode 100644 include/Nazara/Renderer/ShaderSerializer.inl create mode 100644 include/Nazara/Renderer/ShaderVisitor.hpp create mode 100644 src/Nazara/Renderer/ShaderSerializer.cpp create mode 100644 src/Nazara/Renderer/ShaderVisitor.cpp diff --git a/include/Nazara/Renderer/GlslWriter.hpp b/include/Nazara/Renderer/GlslWriter.hpp index 373a9950e..2caaa6a75 100644 --- a/include/Nazara/Renderer/GlslWriter.hpp +++ b/include/Nazara/Renderer/GlslWriter.hpp @@ -31,20 +31,20 @@ namespace Nz void SetGlslVersion(unsigned int version); - void Write(const ShaderAst::AssignOp& node) override; - void Write(const ShaderAst::Branch& node) override; - void Write(const ShaderAst::BinaryFunc& node) override; - void Write(const ShaderAst::BinaryOp& node) override; - void Write(const ShaderAst::BuiltinVariable& node) override; - void Write(const ShaderAst::Cast& node) override; - void Write(const ShaderAst::Constant& node) override; - void Write(const ShaderAst::DeclareVariable& node) override; - void Write(const ShaderAst::ExpressionStatement& node) override; - void Write(const ShaderAst::NamedVariable& node) override; - void Write(const ShaderAst::NodePtr& node) override; - void Write(const ShaderAst::Sample2D& node) override; - void Write(const ShaderAst::StatementBlock& node) override; - void Write(const ShaderAst::SwizzleOp& node) override; + 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; diff --git a/include/Nazara/Renderer/ShaderAst.hpp b/include/Nazara/Renderer/ShaderAst.hpp index 6dd43ea89..0bbaec9f3 100644 --- a/include/Nazara/Renderer/ShaderAst.hpp +++ b/include/Nazara/Renderer/ShaderAst.hpp @@ -17,6 +17,8 @@ namespace Nz { + class ByteStream; + class ShaderVisitor; class ShaderWriter; namespace ShaderAst @@ -66,6 +68,26 @@ namespace Nz 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, @@ -93,13 +115,21 @@ namespace Nz class NAZARA_RENDERER_API Node { public: - virtual ~Node() = default; + virtual ~Node(); + + inline NodeType GetType() const; virtual void Register(ShaderWriter& visitor) = 0; - virtual void Visit(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; @@ -108,6 +138,8 @@ namespace Nz class NAZARA_RENDERER_API Statement : public Node { + public: + using Node::Node; }; class Expression; @@ -117,236 +149,250 @@ namespace Nz class NAZARA_RENDERER_API Expression : public Node { public: + using Node::Node; + virtual ExpressionCategory GetExpressionCategory() const; virtual ExpressionType GetExpressionType() const = 0; }; - class NAZARA_RENDERER_API ExpressionStatement : public Statement + struct NAZARA_RENDERER_API ExpressionStatement : public Statement { - public: - inline explicit ExpressionStatement(ExpressionPtr expr); + inline ExpressionStatement(); - void Register(ShaderWriter& visitor) override; - void Visit(ShaderWriter& visitor) override; + void Register(ShaderWriter& visitor) override; + void Visit(ShaderVisitor& visitor) override; - ExpressionPtr expression; + ExpressionPtr expression; + + static inline std::shared_ptr Build(ExpressionPtr expr); }; ////////////////////////////////////////////////////////////////////////// - class NAZARA_RENDERER_API ConditionalStatement : public Statement + struct NAZARA_RENDERER_API ConditionalStatement : public Statement { - public: - inline ConditionalStatement(const String& condition, StatementPtr statementPtr); + inline ConditionalStatement(); - void Register(ShaderWriter& visitor) override; - void Visit(ShaderWriter& visitor) override; + void Register(ShaderWriter& visitor) override; + void Visit(ShaderVisitor& visitor) override; - String conditionName; - StatementPtr statement; + std::string conditionName; + StatementPtr statement; + + static inline std::shared_ptr Build(std::string condition, StatementPtr statementPtr); }; - class NAZARA_RENDERER_API StatementBlock : public Statement + struct NAZARA_RENDERER_API StatementBlock : public Statement { - public: - template explicit StatementBlock(Args&&... args); + inline StatementBlock(); - void Register(ShaderWriter& visitor) override; - void Visit(ShaderWriter& visitor) override; + void Register(ShaderWriter& visitor) override; + void Visit(ShaderVisitor& visitor) override; - std::vector statements; + std::vector statements; + + template static std::shared_ptr Build(Args&&... args); }; - class Variable; + struct Variable; using VariablePtr = std::shared_ptr; - class NAZARA_RENDERER_API Variable : public Expression + struct NAZARA_RENDERER_API Variable : public Expression { - public: - inline Variable(VariableType varKind, ExpressionType varType); + using Expression::Expression; - ExpressionCategory GetExpressionCategory() const override; - ExpressionType GetExpressionType() const override; + ExpressionCategory GetExpressionCategory() const override; + ExpressionType GetExpressionType() const override; - ExpressionType type; - VariableType kind; + ExpressionType type; + VariableType kind; }; - class NAZARA_RENDERER_API BuiltinVariable : public Variable + struct NAZARA_RENDERER_API BuiltinVariable : public Variable { - public: - inline BuiltinVariable(BuiltinEntry variable, ExpressionType varType); + inline BuiltinVariable(); - void Register(ShaderWriter& visitor) override; - void Visit(ShaderWriter& visitor) override; + void Register(ShaderWriter& visitor) override; + void Visit(ShaderVisitor& visitor) override; - BuiltinEntry var; + BuiltinEntry var; + + static inline std::shared_ptr Build(BuiltinEntry variable, ExpressionType varType); }; - class NamedVariable; + struct NamedVariable; using NamedVariablePtr = std::shared_ptr; - class NAZARA_RENDERER_API NamedVariable : public Variable + struct NAZARA_RENDERER_API NamedVariable : public Variable { - public: - inline NamedVariable(VariableType varKind, const Nz::String& varName, ExpressionType varType); + inline NamedVariable(); - void Register(ShaderWriter& visitor) override; - void Visit(ShaderWriter& visitor) override; + void Register(ShaderWriter& visitor) override; + void Visit(ShaderVisitor& visitor) override; - Nz::String name; + std::string name; + + static inline std::shared_ptr Build(VariableType varType, std::string varName, ExpressionType expressionType); }; - class NAZARA_RENDERER_API DeclareVariable : public Statement + struct NAZARA_RENDERER_API DeclareVariable : public Statement { - public: - inline DeclareVariable(NamedVariablePtr Variable, ExpressionPtr Expression = nullptr); + inline DeclareVariable(); - void Register(ShaderWriter& visitor) override; - void Visit(ShaderWriter& visitor) override; + void Register(ShaderWriter& visitor) override; + void Visit(ShaderVisitor& visitor) override; - NamedVariablePtr variable; - ExpressionPtr expression; + NamedVariablePtr variable; + ExpressionPtr expression; + + static inline std::shared_ptr Build(NamedVariablePtr variable, ExpressionPtr expression = nullptr); }; ////////////////////////////////////////////////////////////////////////// - class NAZARA_RENDERER_API AssignOp : public Expression + struct NAZARA_RENDERER_API AssignOp : public Expression { - public: - inline AssignOp(AssignType Op, ExpressionPtr Left, ExpressionPtr Right); + inline AssignOp(); - ExpressionType GetExpressionType() const override; - void Register(ShaderWriter& visitor) override; - void Visit(ShaderWriter& visitor) override; + ExpressionType GetExpressionType() const override; + void Register(ShaderWriter& visitor) override; + void Visit(ShaderVisitor& visitor) override; - AssignType op; - ExpressionPtr left; - ExpressionPtr right; + AssignType op; + ExpressionPtr left; + ExpressionPtr right; + + static inline std::shared_ptr Build(AssignType op, ExpressionPtr left, ExpressionPtr right); }; - class NAZARA_RENDERER_API BinaryOp : public Expression + struct NAZARA_RENDERER_API BinaryOp : public Expression { - public: - inline BinaryOp(BinaryType Op, ExpressionPtr Left, ExpressionPtr Right); + inline BinaryOp(); - ExpressionType GetExpressionType() const override; - void Register(ShaderWriter& visitor) override; - void Visit(ShaderWriter& visitor) override; + ExpressionType GetExpressionType() const override; + void Register(ShaderWriter& visitor) override; + void Visit(ShaderVisitor& visitor) override; - BinaryType op; - ExpressionPtr left; - ExpressionPtr right; + BinaryType op; + ExpressionPtr left; + ExpressionPtr right; + + static inline std::shared_ptr Build(BinaryType op, ExpressionPtr left, ExpressionPtr right); }; - class NAZARA_RENDERER_API Branch : public Statement + struct NAZARA_RENDERER_API Branch : public Statement { - public: - inline Branch(ExpressionPtr condition, StatementPtr trueStatement, StatementPtr falseStatement = nullptr); + struct ConditionalStatement; - void Register(ShaderWriter& visitor) override; - void Visit(ShaderWriter& visitor) override; + inline Branch(); - struct ConditionalStatement - { - ExpressionPtr condition; - StatementPtr statement; - }; + void Register(ShaderWriter& visitor) override; + void Visit(ShaderVisitor& visitor) override; - std::vector condStatements; - StatementPtr elseStatement; + std::vector condStatements; + StatementPtr elseStatement; + + struct ConditionalStatement + { + ExpressionPtr condition; + StatementPtr statement; + }; + + inline std::shared_ptr Build(ExpressionPtr condition, StatementPtr trueStatement, StatementPtr falseStatement = nullptr); }; - class NAZARA_RENDERER_API Cast : public Expression + struct NAZARA_RENDERER_API Cast : public Expression { - public: - inline Cast(ExpressionType castTo, ExpressionPtr first, ExpressionPtr second = nullptr, ExpressionPtr third = nullptr, ExpressionPtr fourth = nullptr); - inline Cast(ExpressionType castTo, ExpressionPtr* expressions, std::size_t expressionCount); + inline Cast(); - ExpressionType GetExpressionType() const override; - void Register(ShaderWriter& visitor) override; - void Visit(ShaderWriter& visitor) override; + ExpressionType GetExpressionType() const override; + void Register(ShaderWriter& visitor) override; + void Visit(ShaderVisitor& visitor) override; - ExpressionType exprType; - std::array expressions; + ExpressionType exprType; + std::array expressions; - private: - void Validate() const; + 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); }; - class NAZARA_RENDERER_API Constant : public Expression + struct NAZARA_RENDERER_API Constant : public Expression { - public: - inline explicit Constant(bool value); - inline explicit Constant(float value); - inline explicit Constant(const Vector2f& value); - inline explicit Constant(const Vector3f& value); - inline explicit Constant(const Vector4f& value); + inline Constant(); - ExpressionType GetExpressionType() const override; - void Register(ShaderWriter& visitor) override; - void Visit(ShaderWriter& visitor) override; + ExpressionType GetExpressionType() const override; + void Register(ShaderWriter& visitor) override; + void Visit(ShaderVisitor& visitor) override; - ExpressionType exprType; + ExpressionType exprType; - union - { - bool bool1; - float vec1; - Vector2f vec2; - Vector3f vec3; - Vector4f vec4; - } values; + 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); }; - class NAZARA_RENDERER_API SwizzleOp : public Expression + struct NAZARA_RENDERER_API SwizzleOp : public Expression { - public: - inline SwizzleOp(ExpressionPtr expressionPtr, std::initializer_list swizzleComponents); + inline SwizzleOp(); - ExpressionCategory GetExpressionCategory() const override; - ExpressionType GetExpressionType() const override; - void Register(ShaderWriter& visitor) override; - void Visit(ShaderWriter& visitor) override; + ExpressionCategory GetExpressionCategory() const override; + ExpressionType GetExpressionType() const override; + void Register(ShaderWriter& visitor) override; + void Visit(ShaderVisitor& visitor) override; - std::array components; - std::size_t componentCount; - ExpressionPtr expression; + std::array components; + std::size_t componentCount; + ExpressionPtr expression; + + static inline std::shared_ptr Build(ExpressionPtr expressionPtr, std::initializer_list swizzleComponents); }; ////////////////////////////////////////////////////////////////////////// - class NAZARA_RENDERER_API Sample2D : public Expression + struct NAZARA_RENDERER_API Sample2D : public Expression { - public: - inline Sample2D(ExpressionPtr samplerPtr, ExpressionPtr coordinatesPtr); + inline Sample2D(); - ExpressionType GetExpressionType() const override; - void Register(ShaderWriter& visitor) override; - void Visit(ShaderWriter& visitor) override; + ExpressionType GetExpressionType() const override; + void Register(ShaderWriter& visitor) override; + void Visit(ShaderVisitor& visitor) override; - ExpressionPtr sampler; - ExpressionPtr coordinates; + ExpressionPtr sampler; + ExpressionPtr coordinates; + + static inline std::shared_ptr Build(ExpressionPtr samplerPtr, ExpressionPtr coordinatesPtr); }; ////////////////////////////////////////////////////////////////////////// - class NAZARA_RENDERER_API BinaryFunc : public Expression + struct NAZARA_RENDERER_API BinaryFunc : public Expression { - public: - inline BinaryFunc(BinaryIntrinsic Op, ExpressionPtr Left, ExpressionPtr Right); + inline BinaryFunc(); - ExpressionType GetExpressionType() const override; - void Register(ShaderWriter& visitor) override; - void Visit(ShaderWriter& visitor) override; + ExpressionType GetExpressionType() const override; + void Register(ShaderWriter& visitor) override; + void Visit(ShaderVisitor& visitor) override; - BinaryIntrinsic intrinsic; - ExpressionPtr left; - ExpressionPtr right; + BinaryIntrinsic intrinsic; + ExpressionPtr left; + ExpressionPtr right; + + static inline std::shared_ptr Build(BinaryIntrinsic intrinsic, ExpressionPtr left, ExpressionPtr right); }; } } diff --git a/include/Nazara/Renderer/ShaderAst.inl b/include/Nazara/Renderer/ShaderAst.inl index 958baecfe..536758832 100644 --- a/include/Nazara/Renderer/ShaderAst.inl +++ b/include/Nazara/Renderer/ShaderAst.inl @@ -9,6 +9,16 @@ namespace Nz { namespace ShaderAst { + 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) @@ -47,224 +57,264 @@ namespace Nz } } - inline ExpressionStatement::ExpressionStatement(ExpressionPtr expr) : - expression(std::move(expr)) + 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 ConditionalStatement::ConditionalStatement(const String& condition, StatementPtr statementPtr) : - conditionName(condition), - statement(std::move(statementPtr)) + 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 - StatementBlock::StatementBlock(Args&& ...args) : - statements({std::forward(args)...}) + 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 Variable::Variable(VariableType varKind, ExpressionType varType) : - type(varType), - kind(varKind) + 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 BuiltinVariable::BuiltinVariable(BuiltinEntry variable, ExpressionType varType) : - Variable(VariableType::Builtin, varType), - var(variable) + 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 NamedVariable::NamedVariable(VariableType varKind, const Nz::String& varName, ExpressionType varType) : - Variable(varKind, varType), - name(varName) + 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 DeclareVariable::DeclareVariable(NamedVariablePtr Variable, ExpressionPtr Expression) : - expression(std::move(Expression)), - variable(std::move(Variable)) + 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 AssignOp::AssignOp(AssignType Op, ExpressionPtr Left, ExpressionPtr Right) : - op(Op), - left(std::move(Left)), - right(std::move(Right)) + inline std::shared_ptr Branch::Build(ExpressionPtr condition, StatementPtr trueStatement, StatementPtr falseStatement) { - if (left->GetExpressionCategory() != ExpressionCategory::LValue) - //TODO: AstParseError - throw std::runtime_error("Assignation is only possible with lvalues"); + auto node = std::make_shared(); + node->condStatements.emplace_back(ConditionalStatement{ std::move(condition), std::move(trueStatement) }); + node->elseStatement = std::move(falseStatement); + + return node; } - inline BinaryOp::BinaryOp(BinaryType Op, ExpressionPtr Left, ExpressionPtr Right) : - op(Op), - left(std::move(Left)), - right(std::move(Right)) + + inline Cast::Cast() : + Expression(NodeType::Cast) { - ExpressionType leftType = left->GetExpressionType(); - ExpressionType rightType = right->GetExpressionType(); - - if (leftType != rightType) - { - switch (op) - { - case BinaryType::Add: - case BinaryType::Equality: - case BinaryType::Substract: - { - //TODO: AstParseError - throw std::runtime_error("Left expression type must match right expression type"); - } - - case BinaryType::Multiply: - case BinaryType::Divide: - { - switch (leftType) - { - case ExpressionType::Float2: - case ExpressionType::Float3: - case ExpressionType::Float4: - { - if (rightType != ExpressionType::Float1) - throw std::runtime_error("Left expression type is not compatible with right expression type"); - - break; - } - - case ExpressionType::Mat4x4: - { - switch (rightType) - { - case ExpressionType::Float1: - case ExpressionType::Float4: - case ExpressionType::Mat4x4: - break; - - //TODO: AstParseError - default: - throw std::runtime_error("Left expression type is not compatible with right expression type"); - } - - break; - } - - default: - //TODO: AstParseError - throw std::runtime_error("Left expression type must match right expression type"); - } - } - } - } } - inline Branch::Branch(ExpressionPtr condition, StatementPtr trueStatement, StatementPtr falseStatement) + inline std::shared_ptr Cast::Build(ExpressionType castTo, ExpressionPtr first, ExpressionPtr second, ExpressionPtr third, ExpressionPtr fourth) { - condStatements.emplace_back(ConditionalStatement{ std::move(condition), std::move(trueStatement) }); - elseStatement = std::move(falseStatement); + auto node = std::make_shared(); + node->exprType = castTo; + node->expressions = { {first, second, third, fourth} }; + + return node; } - inline Cast::Cast(ExpressionType castTo, ExpressionPtr first, ExpressionPtr second, ExpressionPtr third, ExpressionPtr fourth) : - exprType(castTo), - expressions({ {first, second, third, fourth} }) - { - Validate(); - } - - inline Cast::Cast(ExpressionType castTo, ExpressionPtr* Expressions, std::size_t expressionCount) : - exprType(castTo) + 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) - expressions[i] = Expressions[i]; + node->expressions[i] = Expressions[i]; - Validate(); + return node; } - inline Constant::Constant(bool value) : - exprType(ExpressionType::Boolean) + + inline Constant::Constant() : + Expression(NodeType::Constant) { - values.bool1 = value; } - inline Constant::Constant(float value) : - exprType(ExpressionType::Float1) + inline std::shared_ptr Constant::Build(bool value) { - values.vec1 = value; + auto node = std::make_shared(); + node->exprType = ExpressionType::Boolean; + node->values.bool1 = value; + + return node; } - inline Constant::Constant(const Vector2f& value) : - exprType(ExpressionType::Float2) + inline std::shared_ptr Constant::Build(float value) { - values.vec2 = value; + auto node = std::make_shared(); + node->exprType = ExpressionType::Float1; + node->values.vec1 = value; + + return node; } - inline Constant::Constant(const Vector3f& value) : - exprType(ExpressionType::Float3) + inline std::shared_ptr Constant::Build(const Vector2f& value) { - values.vec3 = value; + auto node = std::make_shared(); + node->exprType = ExpressionType::Float2; + node->values.vec2 = value; + + return node; } - inline Constant::Constant(const Vector4f& value) : - exprType(ExpressionType::Float4) + inline std::shared_ptr Constant::Build(const Vector3f& value) { - values.vec4 = value; + auto node = std::make_shared(); + node->exprType = ExpressionType::Float3; + node->values.vec3 = value; + + return node; } - inline SwizzleOp::SwizzleOp(ExpressionPtr expressionPtr, std::initializer_list swizzleComponents) : - componentCount(swizzleComponents.size()), - expression(expressionPtr) + inline std::shared_ptr Constant::Build(const Vector4f& value) { - if (componentCount > 4) - throw std::runtime_error("Cannot swizzle more than four elements"); + auto node = std::make_shared(); + node->exprType = ExpressionType::Float4; + node->values.vec4 = value; - switch (expressionPtr->GetExpressionType()) - { - case ExpressionType::Float1: - case ExpressionType::Float2: - case ExpressionType::Float3: - case ExpressionType::Float4: - break; - - default: - throw std::runtime_error("Cannot swizzle this type"); - } - - std::copy(swizzleComponents.begin(), swizzleComponents.end(), components.begin()); + return node; } - inline Sample2D::Sample2D(ExpressionPtr samplerPtr, ExpressionPtr coordinatesPtr) : - sampler(std::move(samplerPtr)), - coordinates(std::move(coordinatesPtr)) - { - if (sampler->GetExpressionType() != ExpressionType::Sampler2D) - throw std::runtime_error("Sampler must be a Sampler2D"); - if (coordinates->GetExpressionType() != ExpressionType::Float2) - throw std::runtime_error("Coordinates must be a Float2"); + inline SwizzleOp::SwizzleOp() : + Expression(NodeType::SwizzleOp) + { } - inline BinaryFunc::BinaryFunc(BinaryIntrinsic Op, ExpressionPtr Left, ExpressionPtr Right) : - intrinsic(Op), - left(Left), - right(Right) + inline std::shared_ptr SwizzleOp::Build(ExpressionPtr expressionPtr, std::initializer_list swizzleComponents) { - ExpressionType leftType = left->GetExpressionType(); - ExpressionType rightType = right->GetExpressionType(); + auto node = std::make_shared(); + node->componentCount = swizzleComponents.size(); + node->expression = std::move(expressionPtr); - if (leftType != rightType) - //TODO: AstParseError - throw std::runtime_error("Left expression type must match right expression type"); + std::copy(swizzleComponents.begin(), swizzleComponents.end(), node->components.begin()); - switch (intrinsic) - { - case BinaryIntrinsic::CrossProduct: - { - if (leftType != ExpressionType::Float3) - //TODO: AstParseError - throw std::runtime_error("CrossProduct only works with Float3 expressions"); - } - } + 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; } } } diff --git a/include/Nazara/Renderer/ShaderBuilder.inl b/include/Nazara/Renderer/ShaderBuilder.inl index 76f00d394..7f9612a11 100644 --- a/include/Nazara/Renderer/ShaderBuilder.inl +++ b/include/Nazara/Renderer/ShaderBuilder.inl @@ -5,25 +5,25 @@ #include #include -namespace Nz { namespace ShaderBuilder +namespace Nz::ShaderBuilder { template template std::shared_ptr GenBuilder::operator()(Args&&... args) const { - return std::make_shared(std::forward(args)...); + return T::Build(std::forward(args)...); } template std::shared_ptr AssignOpBuilder::operator()(const ShaderAst::ExpressionPtr& left, const ShaderAst::ExpressionPtr& right) const { - return std::make_shared(op, left, right); + return ShaderAst::AssignOp::Build(op, left, right); } template std::shared_ptr BinOpBuilder::operator()(const ShaderAst::ExpressionPtr& left, const ShaderAst::ExpressionPtr& right) const { - return std::make_shared(op, left, right); + return ShaderAst::BinaryOp::Build(op, left, right); } inline std::shared_ptr BuiltinBuilder::operator()(ShaderAst::BuiltinEntry builtin) const @@ -39,21 +39,21 @@ namespace Nz { namespace ShaderBuilder NazaraAssert(exprType != ShaderAst::ExpressionType::Void, "Unhandled builtin"); - return std::make_shared(builtin, exprType); + return ShaderAst::BuiltinVariable::Build(builtin, exprType); } template template ShaderAst::NamedVariablePtr VarBuilder::operator()(Args&&... args) const { - return std::make_shared(type, std::forward(args)...); + return ShaderAst::NamedVariable::Build(type, std::forward(args)...); } template std::shared_ptr Cast(Args&&... args) { - return std::make_shared(Type, std::forward(args)...); + return ShaderAst::Cast::Build(Type, std::forward(args)...); } -} } +} #include diff --git a/include/Nazara/Renderer/ShaderSerializer.hpp b/include/Nazara/Renderer/ShaderSerializer.hpp new file mode 100644 index 000000000..521284370 --- /dev/null +++ b/include/Nazara/Renderer/ShaderSerializer.hpp @@ -0,0 +1,111 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_SHADERSERIALIZER_HPP +#define NAZARA_SHADERSERIALIZER_HPP + +#include +#include +#include +#include +#include + +namespace Nz::ShaderAst +{ + class NAZARA_RENDERER_API ShaderSerializerBase + { + public: + ShaderSerializerBase() = default; + ShaderSerializerBase(const ShaderSerializerBase&) = delete; + ShaderSerializerBase(ShaderSerializerBase&&) = delete; + ~ShaderSerializerBase() = default; + + void Serialize(AssignOp& node); + void Serialize(BinaryFunc& node); + void Serialize(BinaryOp& node); + 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(Sample2D& node); + void Serialize(StatementBlock& node); + void Serialize(SwizzleOp& node); + + protected: + template void Container(T& container); + template void Enum(T& enumVal); + + virtual bool IsWriting() const = 0; + + virtual void Node(NodePtr& node) = 0; + template void Node(std::shared_ptr& node); + + virtual void Value(bool& val) = 0; + virtual void Value(float& val) = 0; + virtual void Value(std::string& val) = 0; + virtual void Value(Vector2f& val) = 0; + virtual void Value(Vector3f& val) = 0; + virtual void Value(Vector4f& val) = 0; + virtual void Value(UInt32& val) = 0; + inline void Value(std::size_t& val); + }; + + class NAZARA_RENDERER_API ShaderSerializer final : public ShaderSerializerBase + { + public: + inline ShaderSerializer(ByteArray& byteArray); + ~ShaderSerializer() = default; + + void Serialize(const StatementPtr& shader); + + private: + bool IsWriting() const override; + void Node(NodePtr& node) override; + void Value(bool& val) override; + void Value(float& val) override; + void Value(std::string& val) override; + void Value(Vector2f& val) override; + void Value(Vector3f& val) override; + void Value(Vector4f& val) override; + void Value(UInt32& val) override; + + ByteArray& m_byteArray; + ByteStream m_stream; + }; + + class NAZARA_RENDERER_API ShaderUnserializer final : public ShaderSerializerBase + { + public: + ShaderUnserializer(const ByteArray& byteArray); + ~ShaderUnserializer() = default; + + StatementPtr Unserialize(); + + private: + bool IsWriting() const override; + void Node(NodePtr & node) override; + void Value(bool& val) override; + void Value(float& val) override; + void Value(std::string& val) override; + void Value(Vector2f& val) override; + void Value(Vector3f& val) override; + void Value(Vector4f& val) override; + void Value(UInt32& val) override; + + const ByteArray& m_byteArray; + ByteStream m_stream; + }; + + NAZARA_RENDERER_API ByteArray Serialize(const StatementPtr& shader); + NAZARA_RENDERER_API StatementPtr Unserialize(const ByteArray& data); +} + +#include + +#endif diff --git a/include/Nazara/Renderer/ShaderSerializer.inl b/include/Nazara/Renderer/ShaderSerializer.inl new file mode 100644 index 000000000..2d8f5bc85 --- /dev/null +++ b/include/Nazara/Renderer/ShaderSerializer.inl @@ -0,0 +1,79 @@ +// 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::ShaderAst +{ + template + void ShaderSerializerBase::Container(T& container) + { + bool isWriting = IsWriting(); + + UInt32 size; + if (isWriting) + size = UInt32(container.size()); + + Value(size); + if (!isWriting) + container.resize(size); + } + + + template + void ShaderSerializerBase::Enum(T& enumVal) + { + bool isWriting = IsWriting(); + + UInt32 value; + if (isWriting) + value = static_cast(enumVal); + + Value(value); + if (!isWriting) + enumVal = static_cast(value); + } + + template + inline void ShaderSerializerBase::Node(std::shared_ptr& node) + { + bool isWriting = IsWriting(); + + NodePtr value; + if (isWriting) + value = node; + + Node(value); + if (!isWriting) + node = std::static_pointer_cast(value); + } + + inline void ShaderSerializerBase::Value(std::size_t& val) + { + bool isWriting = IsWriting(); + + UInt32 value; + if (isWriting) + value = static_cast(val); + + Value(value); + if (!isWriting) + val = static_cast(value); + } + + inline ShaderSerializer::ShaderSerializer(ByteArray& byteArray) : + m_byteArray(byteArray), + m_stream(&m_byteArray, OpenModeFlags(OpenMode_WriteOnly)) + { + } + + inline ShaderUnserializer::ShaderUnserializer(const ByteArray& byteArray) : + m_byteArray(byteArray), + m_stream(const_cast(&m_byteArray), OpenModeFlags(OpenMode_ReadOnly)) + { + } +} + +#include diff --git a/include/Nazara/Renderer/ShaderVisitor.hpp b/include/Nazara/Renderer/ShaderVisitor.hpp new file mode 100644 index 000000000..47a5741f4 --- /dev/null +++ b/include/Nazara/Renderer/ShaderVisitor.hpp @@ -0,0 +1,50 @@ +// 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_SHADERVISITOR_HPP +#define NAZARA_SHADERVISITOR_HPP + +#include +#include +#include +#include +#include + +namespace Nz +{ + class NAZARA_RENDERER_API ShaderVisitor + { + public: + ShaderVisitor() = default; + ShaderVisitor(const ShaderVisitor&) = delete; + ShaderVisitor(ShaderVisitor&&) = delete; + virtual ~ShaderVisitor(); + + void EnableCondition(const String& name, bool cond); + + bool IsConditionEnabled(const 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; + + private: + std::unordered_set m_conditions; + }; +} + +#endif diff --git a/include/Nazara/Renderer/ShaderWriter.hpp b/include/Nazara/Renderer/ShaderWriter.hpp index 1058fa924..ae00f2fa5 100644 --- a/include/Nazara/Renderer/ShaderWriter.hpp +++ b/include/Nazara/Renderer/ShaderWriter.hpp @@ -10,45 +10,22 @@ #include #include #include -#include -#include +#include namespace Nz { - class NAZARA_RENDERER_API ShaderWriter + class NAZARA_RENDERER_API ShaderWriter : public ShaderVisitor { public: ShaderWriter() = default; ShaderWriter(const ShaderWriter&) = delete; ShaderWriter(ShaderWriter&&) = delete; - virtual ~ShaderWriter(); - - void EnableCondition(const String& name, bool cond); - - bool IsConditionEnabled(const String& name) const; + ~ShaderWriter() = default; 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 void Write(const ShaderAst::AssignOp& node) = 0; - virtual void Write(const ShaderAst::Branch& node) = 0; - virtual void Write(const ShaderAst::BinaryFunc& node) = 0; - virtual void Write(const ShaderAst::BinaryOp& node) = 0; - virtual void Write(const ShaderAst::BuiltinVariable& node) = 0; - virtual void Write(const ShaderAst::Cast& node) = 0; - virtual void Write(const ShaderAst::Constant& node) = 0; - virtual void Write(const ShaderAst::DeclareVariable& node) = 0; - virtual void Write(const ShaderAst::ExpressionStatement& node) = 0; - virtual void Write(const ShaderAst::NamedVariable& node) = 0; - virtual void Write(const ShaderAst::NodePtr& node) = 0; - virtual void Write(const ShaderAst::Sample2D& node) = 0; - virtual void Write(const ShaderAst::StatementBlock& node) = 0; - virtual void Write(const ShaderAst::SwizzleOp& node) = 0; - - private: - std::unordered_set m_conditions; }; } diff --git a/src/Nazara/Renderer/GlslWriter.cpp b/src/Nazara/Renderer/GlslWriter.cpp index b37b9deff..e7b8f6155 100644 --- a/src/Nazara/Renderer/GlslWriter.cpp +++ b/src/Nazara/Renderer/GlslWriter.cpp @@ -116,23 +116,18 @@ namespace Nz m_glslVersion = version; } - void GlslWriter::Write(const ShaderAst::NodePtr& node) - { - node->Visit(*this); - } - - void GlslWriter::Write(const ShaderAst::Sample2D& node) + void GlslWriter::Visit(const ShaderAst::Sample2D& node) { Append("texture("); - Write(node.sampler); + Visit(node.sampler); Append(", "); - Write(node.coordinates); + Visit(node.coordinates); Append(")"); } - void GlslWriter::Write(const ShaderAst::AssignOp& node) + void GlslWriter::Visit(const ShaderAst::AssignOp& node) { - Write(node.left); + Visit(node.left); switch (node.op) { @@ -141,10 +136,10 @@ namespace Nz break; } - Write(node.right); + Visit(node.right); } - void GlslWriter::Write(const ShaderAst::Branch& node) + void GlslWriter::Visit(const ShaderAst::Branch& node) { bool first = true; for (const auto& statement : node.condStatements) @@ -153,11 +148,11 @@ namespace Nz Append("else "); Append("if ("); - Write(statement.condition); + Visit(statement.condition); AppendLine(")"); EnterScope(); - Write(statement.statement); + Visit(statement.statement); LeaveScope(); first = false; @@ -168,12 +163,12 @@ namespace Nz AppendLine("else"); EnterScope(); - Write(node.elseStatement); + Visit(node.elseStatement); LeaveScope(); } } - void GlslWriter::Write(const ShaderAst::BinaryFunc& node) + void GlslWriter::Visit(const ShaderAst::BinaryFunc& node) { switch (node.intrinsic) { @@ -187,15 +182,15 @@ namespace Nz } Append("("); - Write(node.left); + Visit(node.left); Append(", "); - Write(node.right); + Visit(node.right); Append(")"); } - void GlslWriter::Write(const ShaderAst::BinaryOp& node) + void GlslWriter::Visit(const ShaderAst::BinaryOp& node) { - Write(node.left); + Visit(node.left); switch (node.op) { @@ -216,15 +211,15 @@ namespace Nz break; } - Write(node.right); + Visit(node.right); } - void GlslWriter::Write(const ShaderAst::BuiltinVariable& node) + void GlslWriter::Visit(const ShaderAst::BuiltinVariable& node) { Append(node.var); } - void GlslWriter::Write(const ShaderAst::Cast& node) + void GlslWriter::Visit(const ShaderAst::Cast& node) { Append(node.exprType); Append("("); @@ -239,14 +234,14 @@ namespace Nz const auto& exprPtr = node.expressions[i++]; NazaraAssert(exprPtr, "Invalid expression"); - Write(exprPtr); + Visit(exprPtr); requiredComponents -= ShaderAst::Node::GetComponentCount(exprPtr->GetExpressionType()); } Append(")"); } - void GlslWriter::Write(const ShaderAst::Constant& node) + void GlslWriter::Visit(const ShaderAst::Constant& node) { switch (node.exprType) { @@ -275,7 +270,7 @@ namespace Nz } } - void GlslWriter::Write(const ShaderAst::DeclareVariable& node) + void GlslWriter::Visit(const ShaderAst::DeclareVariable& node) { Append(node.variable->GetExpressionType()); Append(" "); @@ -285,24 +280,24 @@ namespace Nz Append(" "); Append("="); Append(" "); - Write(node.expression); + Visit(node.expression); } AppendLine(";"); } - void GlslWriter::Write(const ShaderAst::ExpressionStatement& node) + void GlslWriter::Visit(const ShaderAst::ExpressionStatement& node) { - Write(node.expression); + Visit(node.expression); Append(";"); } - void GlslWriter::Write(const ShaderAst::NamedVariable& node) + void GlslWriter::Visit(const ShaderAst::NamedVariable& node) { Append(node.name); } - void GlslWriter::Write(const ShaderAst::StatementBlock& node) + void GlslWriter::Visit(const ShaderAst::StatementBlock& node) { bool first = true; for (const ShaderAst::StatementPtr& statement : node.statements) @@ -310,15 +305,15 @@ namespace Nz if (!first) AppendLine(); - Write(statement); + Visit(statement); first = false; } } - void GlslWriter::Write(const ShaderAst::SwizzleOp& node) + void GlslWriter::Visit(const ShaderAst::SwizzleOp& node) { - Write(node.expression); + Visit(node.expression); Append("."); for (std::size_t i = 0; i < node.componentCount; ++i) @@ -433,7 +428,7 @@ namespace Nz EnterScope(); { - Write(func.node); + Visit(func.node); } LeaveScope(); } diff --git a/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index 6954f5cf0..9df137326 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -69,7 +69,7 @@ namespace Nz }; RegisterImpl("NazaraOpenGLRenderer" NazaraRendererDebugSuffix, [] { return 50; }); - RegisterImpl("NazaraVulkanRenderer" NazaraRendererDebugSuffix, [] { return 100; }); + //RegisterImpl("NazaraVulkanRenderer" NazaraRendererDebugSuffix, [] { return 100; }); std::sort(implementations.begin(), implementations.end(), [](const auto& lhs, const auto& rhs) { return lhs.score > rhs.score; }); diff --git a/src/Nazara/Renderer/ShaderAst.cpp b/src/Nazara/Renderer/ShaderAst.cpp index 0a2373d17..d60ebab6a 100644 --- a/src/Nazara/Renderer/ShaderAst.cpp +++ b/src/Nazara/Renderer/ShaderAst.cpp @@ -3,11 +3,15 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include +#include #include #include namespace Nz::ShaderAst { + Node::~Node() = default; + ExpressionCategory Expression::GetExpressionCategory() const { return ExpressionCategory::RValue; @@ -18,9 +22,9 @@ namespace Nz::ShaderAst expression->Register(visitor); } - void ExpressionStatement::Visit(ShaderWriter& visitor) + void ExpressionStatement::Visit(ShaderVisitor& visitor) { - visitor.Write(*this); + visitor.Visit(*this); } @@ -30,7 +34,7 @@ namespace Nz::ShaderAst statement->Register(visitor); } - void ConditionalStatement::Visit(ShaderWriter& visitor) + void ConditionalStatement::Visit(ShaderVisitor& visitor) { if (visitor.IsConditionEnabled(conditionName)) statement->Visit(visitor); @@ -43,9 +47,9 @@ namespace Nz::ShaderAst statementPtr->Register(visitor); } - void StatementBlock::Visit(ShaderWriter& visitor) + void StatementBlock::Visit(ShaderVisitor& visitor) { - visitor.Write(*this); + visitor.Visit(*this); } ExpressionCategory Variable::GetExpressionCategory() const @@ -58,14 +62,25 @@ namespace Nz::ShaderAst 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(ShaderWriter& visitor) + void NamedVariable::Visit(ShaderVisitor& visitor) { - visitor.Write(*this); + visitor.Visit(*this); } @@ -77,18 +92,9 @@ namespace Nz::ShaderAst expression->Register(visitor); } - void DeclareVariable::Visit(ShaderWriter& visitor) + void DeclareVariable::Visit(ShaderVisitor& visitor) { - visitor.Write(*this); - } - - void BuiltinVariable::Register(ShaderWriter& /*visitor*/) - { - } - - void BuiltinVariable::Visit(ShaderWriter& visitor) - { - visitor.Write(*this); + visitor.Visit(*this); } @@ -103,9 +109,9 @@ namespace Nz::ShaderAst right->Register(visitor); } - void AssignOp::Visit(ShaderWriter& visitor) + void AssignOp::Visit(ShaderVisitor& visitor) { - visitor.Write(*this); + visitor.Visit(*this); } @@ -138,9 +144,9 @@ namespace Nz::ShaderAst right->Register(visitor); } - void BinaryOp::Visit(ShaderWriter& visitor) + void BinaryOp::Visit(ShaderVisitor& visitor) { - visitor.Write(*this); + visitor.Visit(*this); } @@ -156,9 +162,9 @@ namespace Nz::ShaderAst elseStatement->Register(visitor); } - void Branch::Visit(ShaderWriter& visitor) + void Branch::Visit(ShaderVisitor& visitor) { - visitor.Write(*this); + visitor.Visit(*this); } @@ -171,9 +177,9 @@ namespace Nz::ShaderAst { } - void Constant::Visit(ShaderWriter& visitor) + void Constant::Visit(ShaderVisitor& visitor) { - visitor.Write(*this); + visitor.Visit(*this); } ExpressionType Cast::GetExpressionType() const @@ -195,26 +201,9 @@ namespace Nz::ShaderAst } } - void Cast::Visit(ShaderWriter& visitor) + void Cast::Visit(ShaderVisitor& visitor) { - visitor.Write(*this); - } - - void Cast::Validate() const - { - unsigned int componentCount = 0; - unsigned int requiredComponents = GetComponentCount(exprType); - for (const auto& exprPtr : expressions) - { - if (!exprPtr) - break; - - componentCount += GetComponentCount(exprPtr->GetExpressionType()); - } - - //TODO: AstParseError - if (componentCount != requiredComponents) - throw std::runtime_error("Component count doesn't match required component count"); + visitor.Visit(*this); } @@ -233,9 +222,9 @@ namespace Nz::ShaderAst expression->Register(visitor); } - void SwizzleOp::Visit(ShaderWriter& visitor) + void SwizzleOp::Visit(ShaderVisitor& visitor) { - visitor.Write(*this); + visitor.Visit(*this); } @@ -250,9 +239,9 @@ namespace Nz::ShaderAst coordinates->Register(visitor); } - void Sample2D::Visit(ShaderWriter& visitor) + void Sample2D::Visit(ShaderVisitor& visitor) { - visitor.Write(*this); + visitor.Visit(*this); } @@ -277,8 +266,8 @@ namespace Nz::ShaderAst right->Register(visitor); } - void BinaryFunc::Visit(ShaderWriter& visitor) + void BinaryFunc::Visit(ShaderVisitor& visitor) { - visitor.Write(*this); + visitor.Visit(*this); } } diff --git a/src/Nazara/Renderer/ShaderSerializer.cpp b/src/Nazara/Renderer/ShaderSerializer.cpp new file mode 100644 index 000000000..6e6e3e8ff --- /dev/null +++ b/src/Nazara/Renderer/ShaderSerializer.cpp @@ -0,0 +1,376 @@ +// 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::ShaderAst +{ + namespace + { + class ShaderSerializerVisitor : public ShaderVisitor + { + public: + ShaderSerializerVisitor(ShaderSerializerBase& serializer) : + m_serializer(serializer) + { + } + + void Visit(const AssignOp& node) override + { + Serialize(node); + } + + void Visit(const BinaryFunc& node) override + { + Serialize(node); + } + + void Visit(const BinaryOp& node) override + { + Serialize(node); + } + + void Visit(const Branch& node) override + { + Serialize(node); + } + + void Visit(const BuiltinVariable& node) override + { + Serialize(node); + } + + void Visit(const Cast& node) override + { + Serialize(node); + } + + void Visit(const Constant& node) override + { + Serialize(node); + } + + void Visit(const DeclareVariable& node) override + { + Serialize(node); + } + + void Visit(const ExpressionStatement& node) override + { + Serialize(node); + } + + void Visit(const NamedVariable& node) override + { + Serialize(node); + } + + void Visit(const Sample2D& node) override + { + Serialize(node); + } + + void Visit(const StatementBlock& node) override + { + Serialize(node); + } + + void Visit(const SwizzleOp& node) override + { + Serialize(node); + } + + private: + template + void Serialize(const T& node) + { + // I know const_cast is evil but I don't have a better solution here (it's not used to write) + m_serializer.Serialize(const_cast(node)); + } + + ShaderSerializerBase& m_serializer; + }; + } + + void ShaderSerializerBase::Serialize(AssignOp& node) + { + Enum(node.op); + Node(node.left); + 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); + Node(node.left); + Node(node.right); + } + + void ShaderSerializerBase::Serialize(Branch& node) + { + Container(node.condStatements); + for (auto& condStatement : node.condStatements) + { + Node(condStatement.condition); + Node(condStatement.statement); + } + + Node(node.elseStatement); + } + + void ShaderSerializerBase::Serialize(BuiltinVariable& node) + { + Enum(node.var); + Enum(node.type); + } + + void ShaderSerializerBase::Serialize(Cast& node) + { + Enum(node.exprType); + for (auto& expr : node.expressions) + Node(expr); + } + + void ShaderSerializerBase::Serialize(Constant& node) + { + Enum(node.exprType); + + switch (node.exprType) + { + case ExpressionType::Boolean: + Value(node.values.bool1); + break; + + case ExpressionType::Float1: + Value(node.values.vec1); + break; + + case ExpressionType::Float2: + Value(node.values.vec2); + break; + + case ExpressionType::Float3: + Value(node.values.vec3); + break; + + case ExpressionType::Float4: + Value(node.values.vec4); + break; + } + } + + void ShaderSerializerBase::Serialize(DeclareVariable& node) + { + Node(node.variable); + Node(node.expression); + } + + void ShaderSerializerBase::Serialize(ExpressionStatement& node) + { + Node(node.expression); + } + + void ShaderSerializerBase::Serialize(NamedVariable& node) + { + Value(node.name); + Enum(node.kind); + Enum(node.type); + } + + void ShaderSerializerBase::Serialize(Sample2D& node) + { + Node(node.sampler); + Node(node.coordinates); + } + + void ShaderSerializerBase::Serialize(StatementBlock& node) + { + Container(node.statements); + for (auto& statement : node.statements) + Node(statement); + } + + void ShaderSerializerBase::Serialize(SwizzleOp& node) + { + Value(node.componentCount); + Node(node.expression); + + for (std::size_t i = 0; i < node.componentCount; ++i) + Enum(node.components[i]); + } + + + void ShaderSerializer::Serialize(const StatementPtr& shader) + { + assert(shader); + m_stream << static_cast(shader->GetType()); + + ShaderSerializerVisitor visitor(*this); + shader->Visit(visitor); + + m_stream.FlushBits(); + } + + bool ShaderSerializer::IsWriting() const + { + return true; + } + + void ShaderSerializer::Node(NodePtr& node) + { + NodeType nodeType = (node) ? node->GetType() : NodeType::None; + m_stream << static_cast(nodeType); + + if (node) + { + ShaderSerializerVisitor visitor(*this); + node->Visit(visitor); + } + } + + void ShaderSerializer::Value(bool& val) + { + m_stream << val; + } + + void ShaderSerializer::Value(float& val) + { + m_stream << val; + } + + void ShaderSerializer::Value(std::string& val) + { + m_stream << val; + } + + void ShaderSerializer::Value(Vector2f& val) + { + m_stream << val; + } + + void ShaderSerializer::Value(Vector3f& val) + { + m_stream << val; + } + + void ShaderSerializer::Value(Vector4f& val) + { + m_stream << val; + } + + void ShaderSerializer::Value(UInt32& val) + { + m_stream << val; + } + + ByteArray Serialize(const StatementPtr& shader) + { + ByteArray byteArray; + ShaderSerializer serializer(byteArray); + serializer.Serialize(shader); + + return byteArray; + } + + StatementPtr Unserialize(const ByteArray& data) + { + ShaderUnserializer unserializer(data); + return unserializer.Unserialize(); + } + + StatementPtr ShaderUnserializer::Unserialize() + { + NodePtr statement; + Node(statement); + if (!statement || statement->GetType() != NodeType::StatementBlock) + throw std::runtime_error("Invalid shader"); + + return std::static_pointer_cast(statement); + } + + bool ShaderUnserializer::IsWriting() const + { + return false; + } + + void ShaderUnserializer::Node(NodePtr& node) + { + Int32 nodeTypeInt; + m_stream >> nodeTypeInt; + + NodeType nodeType = static_cast(nodeTypeInt); + +#define HandleNodeType(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); + } +#undef HandleNodeType + + if (node) + { + ShaderSerializerVisitor visitor(*this); + node->Visit(visitor); + } + } + + void ShaderUnserializer::Value(bool& val) + { + m_stream >> val; + } + + void ShaderUnserializer::Value(float& val) + { + m_stream >> val; + } + + void ShaderUnserializer::Value(std::string& val) + { + m_stream >> val; + } + + void ShaderUnserializer::Value(Vector2f& val) + { + m_stream >> val; + } + + void ShaderUnserializer::Value(Vector3f& val) + { + m_stream >> val; + } + + void ShaderUnserializer::Value(Vector4f& val) + { + m_stream >> val; + } + + void ShaderUnserializer::Value(UInt32& val) + { + m_stream >> val; + } +} + diff --git a/src/Nazara/Renderer/ShaderVisitor.cpp b/src/Nazara/Renderer/ShaderVisitor.cpp new file mode 100644 index 000000000..2b5a590bd --- /dev/null +++ b/src/Nazara/Renderer/ShaderVisitor.cpp @@ -0,0 +1,29 @@ +// 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 +{ + ShaderVisitor::~ShaderVisitor() = default; + + void ShaderVisitor::EnableCondition(const String& name, bool cond) + { + if (cond) + m_conditions.insert(name); + else + m_conditions.erase(name); + } + + bool ShaderVisitor::IsConditionEnabled(const String& name) const + { + return m_conditions.count(name) != 0; + } + + void ShaderVisitor::Visit(const ShaderAst::NodePtr& node) + { + node->Visit(*this); + } +} diff --git a/src/Nazara/Renderer/ShaderWriter.cpp b/src/Nazara/Renderer/ShaderWriter.cpp index c862572ab..982251556 100644 --- a/src/Nazara/Renderer/ShaderWriter.cpp +++ b/src/Nazara/Renderer/ShaderWriter.cpp @@ -7,18 +7,4 @@ namespace Nz { - ShaderWriter::~ShaderWriter() = default; - - void ShaderWriter::EnableCondition(const String& name, bool cond) - { - if (cond) - m_conditions.insert(name); - else - m_conditions.erase(name); - } - - bool ShaderWriter::IsConditionEnabled(const String & name) const - { - return m_conditions.count(name) != 0; - } } diff --git a/src/ShaderNode/ShaderGraph.cpp b/src/ShaderNode/ShaderGraph.cpp index 6fc2fe6aa..01b5c6cf9 100644 --- a/src/ShaderNode/ShaderGraph.cpp +++ b/src/ShaderNode/ShaderGraph.cpp @@ -352,7 +352,7 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst() } }); - return std::make_shared(std::move(statements)); + return Nz::ShaderAst::StatementBlock::Build(std::move(statements)); } void ShaderGraph::UpdateInput(std::size_t inputIndex, std::string name, InOutType type, InputRole role, std::size_t roleIndex)