Renderer: Add shader serialization

This commit is contained in:
Lynix 2020-06-05 19:47:29 +02:00
parent de1c64253e
commit 8467c79021
15 changed files with 1131 additions and 443 deletions

View File

@ -31,20 +31,20 @@ namespace Nz
void SetGlslVersion(unsigned int version); void SetGlslVersion(unsigned int version);
void Write(const ShaderAst::AssignOp& node) override; using ShaderWriter::Visit;
void Write(const ShaderAst::Branch& node) override; void Visit(const ShaderAst::AssignOp& node) override;
void Write(const ShaderAst::BinaryFunc& node) override; void Visit(const ShaderAst::Branch& node) override;
void Write(const ShaderAst::BinaryOp& node) override; void Visit(const ShaderAst::BinaryFunc& node) override;
void Write(const ShaderAst::BuiltinVariable& node) override; void Visit(const ShaderAst::BinaryOp& node) override;
void Write(const ShaderAst::Cast& node) override; void Visit(const ShaderAst::BuiltinVariable& node) override;
void Write(const ShaderAst::Constant& node) override; void Visit(const ShaderAst::Cast& node) override;
void Write(const ShaderAst::DeclareVariable& node) override; void Visit(const ShaderAst::Constant& node) override;
void Write(const ShaderAst::ExpressionStatement& node) override; void Visit(const ShaderAst::DeclareVariable& node) override;
void Write(const ShaderAst::NamedVariable& node) override; void Visit(const ShaderAst::ExpressionStatement& node) override;
void Write(const ShaderAst::NodePtr& node) override; void Visit(const ShaderAst::NamedVariable& node) override;
void Write(const ShaderAst::Sample2D& node) override; void Visit(const ShaderAst::Sample2D& node) override;
void Write(const ShaderAst::StatementBlock& node) override; void Visit(const ShaderAst::StatementBlock& node) override;
void Write(const ShaderAst::SwizzleOp& node) override; void Visit(const ShaderAst::SwizzleOp& node) override;
private: private:
struct Function; struct Function;

View File

@ -17,6 +17,8 @@
namespace Nz namespace Nz
{ {
class ByteStream;
class ShaderVisitor;
class ShaderWriter; class ShaderWriter;
namespace ShaderAst namespace ShaderAst
@ -66,6 +68,26 @@ namespace Nz
Void // void Void // void
}; };
enum class NodeType
{
None = -1,
AssignOp,
BinaryFunc,
BinaryOp,
Branch,
BuiltinVariable,
Cast,
Constant,
ConditionalStatement,
DeclareVariable,
ExpressionStatement,
NamedVariable,
Sample2D,
SwizzleOp,
StatementBlock
};
enum class SwizzleComponent enum class SwizzleComponent
{ {
First, First,
@ -93,13 +115,21 @@ namespace Nz
class NAZARA_RENDERER_API Node class NAZARA_RENDERER_API Node
{ {
public: public:
virtual ~Node() = default; virtual ~Node();
inline NodeType GetType() const;
virtual void Register(ShaderWriter& visitor) = 0; 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 unsigned int GetComponentCount(ExpressionType type);
static inline ExpressionType GetComponentType(ExpressionType type); static inline ExpressionType GetComponentType(ExpressionType type);
protected:
inline Node(NodeType type);
private:
NodeType m_type;
}; };
class Statement; class Statement;
@ -108,6 +138,8 @@ namespace Nz
class NAZARA_RENDERER_API Statement : public Node class NAZARA_RENDERER_API Statement : public Node
{ {
public:
using Node::Node;
}; };
class Expression; class Expression;
@ -117,236 +149,250 @@ namespace Nz
class NAZARA_RENDERER_API Expression : public Node class NAZARA_RENDERER_API Expression : public Node
{ {
public: public:
using Node::Node;
virtual ExpressionCategory GetExpressionCategory() const; virtual ExpressionCategory GetExpressionCategory() const;
virtual ExpressionType GetExpressionType() const = 0; virtual ExpressionType GetExpressionType() const = 0;
}; };
class NAZARA_RENDERER_API ExpressionStatement : public Statement struct NAZARA_RENDERER_API ExpressionStatement : public Statement
{ {
public: inline ExpressionStatement();
inline explicit ExpressionStatement(ExpressionPtr expr);
void Register(ShaderWriter& visitor) override; void Register(ShaderWriter& visitor) override;
void Visit(ShaderWriter& visitor) override; void Visit(ShaderVisitor& visitor) override;
ExpressionPtr expression; ExpressionPtr expression;
static inline std::shared_ptr<ExpressionStatement> Build(ExpressionPtr expr);
}; };
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
class NAZARA_RENDERER_API ConditionalStatement : public Statement struct NAZARA_RENDERER_API ConditionalStatement : public Statement
{ {
public: inline ConditionalStatement();
inline ConditionalStatement(const String& condition, StatementPtr statementPtr);
void Register(ShaderWriter& visitor) override; void Register(ShaderWriter& visitor) override;
void Visit(ShaderWriter& visitor) override; void Visit(ShaderVisitor& visitor) override;
String conditionName; std::string conditionName;
StatementPtr statement; StatementPtr statement;
static inline std::shared_ptr<ConditionalStatement> Build(std::string condition, StatementPtr statementPtr);
}; };
class NAZARA_RENDERER_API StatementBlock : public Statement struct NAZARA_RENDERER_API StatementBlock : public Statement
{ {
public: inline StatementBlock();
template<typename... Args> explicit StatementBlock(Args&&... args);
void Register(ShaderWriter& visitor) override; void Register(ShaderWriter& visitor) override;
void Visit(ShaderWriter& visitor) override; void Visit(ShaderVisitor& visitor) override;
std::vector<StatementPtr> statements; std::vector<StatementPtr> statements;
template<typename... Args> static std::shared_ptr<StatementBlock> Build(Args&&... args);
}; };
class Variable; struct Variable;
using VariablePtr = std::shared_ptr<Variable>; using VariablePtr = std::shared_ptr<Variable>;
class NAZARA_RENDERER_API Variable : public Expression struct NAZARA_RENDERER_API Variable : public Expression
{ {
public: using Expression::Expression;
inline Variable(VariableType varKind, ExpressionType varType);
ExpressionCategory GetExpressionCategory() const override; ExpressionCategory GetExpressionCategory() const override;
ExpressionType GetExpressionType() const override; ExpressionType GetExpressionType() const override;
ExpressionType type; ExpressionType type;
VariableType kind; VariableType kind;
}; };
class NAZARA_RENDERER_API BuiltinVariable : public Variable struct NAZARA_RENDERER_API BuiltinVariable : public Variable
{ {
public: inline BuiltinVariable();
inline BuiltinVariable(BuiltinEntry variable, ExpressionType varType);
void Register(ShaderWriter& visitor) override; void Register(ShaderWriter& visitor) override;
void Visit(ShaderWriter& visitor) override; void Visit(ShaderVisitor& visitor) override;
BuiltinEntry var; BuiltinEntry var;
static inline std::shared_ptr<BuiltinVariable> Build(BuiltinEntry variable, ExpressionType varType);
}; };
class NamedVariable; struct NamedVariable;
using NamedVariablePtr = std::shared_ptr<NamedVariable>; using NamedVariablePtr = std::shared_ptr<NamedVariable>;
class NAZARA_RENDERER_API NamedVariable : public Variable struct NAZARA_RENDERER_API NamedVariable : public Variable
{ {
public: inline NamedVariable();
inline NamedVariable(VariableType varKind, const Nz::String& varName, ExpressionType varType);
void Register(ShaderWriter& visitor) override; void Register(ShaderWriter& visitor) override;
void Visit(ShaderWriter& visitor) override; void Visit(ShaderVisitor& visitor) override;
Nz::String name; std::string name;
static inline std::shared_ptr<NamedVariable> 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();
inline DeclareVariable(NamedVariablePtr Variable, ExpressionPtr Expression = nullptr);
void Register(ShaderWriter& visitor) override; void Register(ShaderWriter& visitor) override;
void Visit(ShaderWriter& visitor) override; void Visit(ShaderVisitor& visitor) override;
NamedVariablePtr variable; NamedVariablePtr variable;
ExpressionPtr expression; ExpressionPtr expression;
static inline std::shared_ptr<DeclareVariable> Build(NamedVariablePtr variable, ExpressionPtr expression = nullptr);
}; };
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
class NAZARA_RENDERER_API AssignOp : public Expression struct NAZARA_RENDERER_API AssignOp : public Expression
{ {
public: inline AssignOp();
inline AssignOp(AssignType Op, ExpressionPtr Left, ExpressionPtr Right);
ExpressionType GetExpressionType() const override; ExpressionType GetExpressionType() const override;
void Register(ShaderWriter& visitor) override; void Register(ShaderWriter& visitor) override;
void Visit(ShaderWriter& visitor) override; void Visit(ShaderVisitor& visitor) override;
AssignType op; AssignType op;
ExpressionPtr left; ExpressionPtr left;
ExpressionPtr right; ExpressionPtr right;
static inline std::shared_ptr<AssignOp> Build(AssignType op, ExpressionPtr left, ExpressionPtr right);
}; };
class NAZARA_RENDERER_API BinaryOp : public Expression struct NAZARA_RENDERER_API BinaryOp : public Expression
{ {
public: inline BinaryOp();
inline BinaryOp(BinaryType Op, ExpressionPtr Left, ExpressionPtr Right);
ExpressionType GetExpressionType() const override; ExpressionType GetExpressionType() const override;
void Register(ShaderWriter& visitor) override; void Register(ShaderWriter& visitor) override;
void Visit(ShaderWriter& visitor) override; void Visit(ShaderVisitor& visitor) override;
BinaryType op; BinaryType op;
ExpressionPtr left; ExpressionPtr left;
ExpressionPtr right; ExpressionPtr right;
static inline std::shared_ptr<BinaryOp> Build(BinaryType op, ExpressionPtr left, ExpressionPtr right);
}; };
class NAZARA_RENDERER_API Branch : public Statement struct NAZARA_RENDERER_API Branch : public Statement
{ {
public: struct ConditionalStatement;
inline Branch(ExpressionPtr condition, StatementPtr trueStatement, StatementPtr falseStatement = nullptr);
void Register(ShaderWriter& visitor) override; inline Branch();
void Visit(ShaderWriter& visitor) override;
struct ConditionalStatement void Register(ShaderWriter& visitor) override;
{ void Visit(ShaderVisitor& visitor) override;
ExpressionPtr condition;
StatementPtr statement;
};
std::vector<ConditionalStatement> condStatements; std::vector<ConditionalStatement> condStatements;
StatementPtr elseStatement; StatementPtr elseStatement;
struct ConditionalStatement
{
ExpressionPtr condition;
StatementPtr statement;
};
inline std::shared_ptr<Branch> 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();
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);
ExpressionType GetExpressionType() const override; ExpressionType GetExpressionType() const override;
void Register(ShaderWriter& visitor) override; void Register(ShaderWriter& visitor) override;
void Visit(ShaderWriter& visitor) override; void Visit(ShaderVisitor& visitor) override;
ExpressionType exprType; ExpressionType exprType;
std::array<ExpressionPtr, 4> expressions; std::array<ExpressionPtr, 4> expressions;
private: static inline std::shared_ptr<Cast> Build(ExpressionType castTo, ExpressionPtr first, ExpressionPtr second = nullptr, ExpressionPtr third = nullptr, ExpressionPtr fourth = nullptr);
void Validate() const; static inline std::shared_ptr<Cast> 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 Constant();
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);
ExpressionType GetExpressionType() const override; ExpressionType GetExpressionType() const override;
void Register(ShaderWriter& visitor) override; void Register(ShaderWriter& visitor) override;
void Visit(ShaderWriter& visitor) override; void Visit(ShaderVisitor& visitor) override;
ExpressionType exprType; ExpressionType exprType;
union union
{ {
bool bool1; bool bool1;
float vec1; float vec1;
Vector2f vec2; Vector2f vec2;
Vector3f vec3; Vector3f vec3;
Vector4f vec4; Vector4f vec4;
} values; } values;
static inline std::shared_ptr<Constant> Build(bool value);
static inline std::shared_ptr<Constant> Build(float value);
static inline std::shared_ptr<Constant> Build(const Vector2f& value);
static inline std::shared_ptr<Constant> Build(const Vector3f& value);
static inline std::shared_ptr<Constant> Build(const Vector4f& value);
}; };
class NAZARA_RENDERER_API SwizzleOp : public Expression struct NAZARA_RENDERER_API SwizzleOp : public Expression
{ {
public: inline SwizzleOp();
inline SwizzleOp(ExpressionPtr expressionPtr, std::initializer_list<SwizzleComponent> swizzleComponents);
ExpressionCategory GetExpressionCategory() const override; ExpressionCategory GetExpressionCategory() const override;
ExpressionType GetExpressionType() const override; ExpressionType GetExpressionType() const override;
void Register(ShaderWriter& visitor) override; void Register(ShaderWriter& visitor) override;
void Visit(ShaderWriter& visitor) override; void Visit(ShaderVisitor& visitor) override;
std::array<SwizzleComponent, 4> components; std::array<SwizzleComponent, 4> components;
std::size_t componentCount; std::size_t componentCount;
ExpressionPtr expression; ExpressionPtr expression;
static inline std::shared_ptr<SwizzleOp> Build(ExpressionPtr expressionPtr, std::initializer_list<SwizzleComponent> swizzleComponents);
}; };
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
class NAZARA_RENDERER_API Sample2D : public Expression struct NAZARA_RENDERER_API Sample2D : public Expression
{ {
public: inline Sample2D();
inline Sample2D(ExpressionPtr samplerPtr, ExpressionPtr coordinatesPtr);
ExpressionType GetExpressionType() const override; ExpressionType GetExpressionType() const override;
void Register(ShaderWriter& visitor) override; void Register(ShaderWriter& visitor) override;
void Visit(ShaderWriter& visitor) override; void Visit(ShaderVisitor& visitor) override;
ExpressionPtr sampler; ExpressionPtr sampler;
ExpressionPtr coordinates; ExpressionPtr coordinates;
static inline std::shared_ptr<Sample2D> Build(ExpressionPtr samplerPtr, ExpressionPtr coordinatesPtr);
}; };
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
class NAZARA_RENDERER_API BinaryFunc : public Expression struct NAZARA_RENDERER_API BinaryFunc : public Expression
{ {
public: inline BinaryFunc();
inline BinaryFunc(BinaryIntrinsic Op, ExpressionPtr Left, ExpressionPtr Right);
ExpressionType GetExpressionType() const override; ExpressionType GetExpressionType() const override;
void Register(ShaderWriter& visitor) override; void Register(ShaderWriter& visitor) override;
void Visit(ShaderWriter& visitor) override; void Visit(ShaderVisitor& visitor) override;
BinaryIntrinsic intrinsic; BinaryIntrinsic intrinsic;
ExpressionPtr left; ExpressionPtr left;
ExpressionPtr right; ExpressionPtr right;
static inline std::shared_ptr<BinaryFunc> Build(BinaryIntrinsic intrinsic, ExpressionPtr left, ExpressionPtr right);
}; };
} }
} }

View File

@ -9,6 +9,16 @@ namespace Nz
{ {
namespace ShaderAst 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) inline unsigned int Node::GetComponentCount(ExpressionType type)
{ {
switch (type) switch (type)
@ -47,224 +57,264 @@ namespace Nz
} }
} }
inline ExpressionStatement::ExpressionStatement(ExpressionPtr expr) : inline ExpressionStatement::ExpressionStatement() :
expression(std::move(expr)) Statement(NodeType::ExpressionStatement)
{
}
inline std::shared_ptr<ExpressionStatement> ExpressionStatement::Build(ExpressionPtr expr)
{
auto node = std::make_shared<ExpressionStatement>();
node->expression = std::move(expr);
return node;
}
inline ConditionalStatement::ConditionalStatement() :
Statement(NodeType::ConditionalStatement)
{ {
} }
inline ConditionalStatement::ConditionalStatement(const String& condition, StatementPtr statementPtr) : inline std::shared_ptr<ConditionalStatement> ConditionalStatement::Build(std::string condition, StatementPtr statementPtr)
conditionName(condition), {
statement(std::move(statementPtr)) auto node = std::make_shared<ConditionalStatement>();
node->conditionName = std::move(condition);
node->statement = std::move(statementPtr);
return node;
}
inline StatementBlock::StatementBlock() :
Statement(NodeType::StatementBlock)
{ {
} }
template<typename... Args> template<typename... Args>
StatementBlock::StatementBlock(Args&& ...args) : std::shared_ptr<StatementBlock> StatementBlock::Build(Args&&... args)
statements({std::forward<Args>(args)...}) {
auto node = std::make_shared<StatementBlock>();
node->statements = std::vector<StatementPtr>({ std::forward<Args>(args)... });
return node;
}
inline BuiltinVariable::BuiltinVariable() :
Variable(NodeType::BuiltinVariable)
{
kind = VariableType::Builtin;
}
inline std::shared_ptr<BuiltinVariable> BuiltinVariable::Build(BuiltinEntry variable, ExpressionType varType)
{
auto node = std::make_shared<BuiltinVariable>();
node->type = varType;
node->var = variable;
return node;
}
inline NamedVariable::NamedVariable() :
Variable(NodeType::NamedVariable)
{ {
} }
inline Variable::Variable(VariableType varKind, ExpressionType varType) : inline std::shared_ptr<NamedVariable> NamedVariable::Build(VariableType type, std::string varName, ExpressionType expressionType)
type(varType), {
kind(varKind) auto node = std::make_shared<NamedVariable>();
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) : inline std::shared_ptr<DeclareVariable> DeclareVariable::Build(NamedVariablePtr variable, ExpressionPtr expression)
Variable(VariableType::Builtin, varType), {
var(variable) auto node = std::make_shared<DeclareVariable>();
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) : inline std::shared_ptr<AssignOp> AssignOp::Build(AssignType op, ExpressionPtr left, ExpressionPtr right)
Variable(varKind, varType), {
name(varName) auto node = std::make_shared<AssignOp>();
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) : inline std::shared_ptr<BinaryOp> BinaryOp::Build(BinaryType op, ExpressionPtr left, ExpressionPtr right)
expression(std::move(Expression)), {
variable(std::move(Variable)) auto node = std::make_shared<BinaryOp>();
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) : inline std::shared_ptr<Branch> Branch::Build(ExpressionPtr condition, StatementPtr trueStatement, StatementPtr falseStatement)
op(Op),
left(std::move(Left)),
right(std::move(Right))
{ {
if (left->GetExpressionCategory() != ExpressionCategory::LValue) auto node = std::make_shared<Branch>();
//TODO: AstParseError node->condStatements.emplace_back(ConditionalStatement{ std::move(condition), std::move(trueStatement) });
throw std::runtime_error("Assignation is only possible with lvalues"); node->elseStatement = std::move(falseStatement);
return node;
} }
inline BinaryOp::BinaryOp(BinaryType Op, ExpressionPtr Left, ExpressionPtr Right) :
op(Op), inline Cast::Cast() :
left(std::move(Left)), Expression(NodeType::Cast)
right(std::move(Right))
{ {
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> Cast::Build(ExpressionType castTo, ExpressionPtr first, ExpressionPtr second, ExpressionPtr third, ExpressionPtr fourth)
{ {
condStatements.emplace_back(ConditionalStatement{ std::move(condition), std::move(trueStatement) }); auto node = std::make_shared<Cast>();
elseStatement = std::move(falseStatement); node->exprType = castTo;
node->expressions = { {first, second, third, fourth} };
return node;
} }
inline Cast::Cast(ExpressionType castTo, ExpressionPtr first, ExpressionPtr second, ExpressionPtr third, ExpressionPtr fourth) : inline std::shared_ptr<Cast> Cast::Build(ExpressionType castTo, ExpressionPtr* Expressions, std::size_t expressionCount)
exprType(castTo),
expressions({ {first, second, third, fourth} })
{
Validate();
}
inline Cast::Cast(ExpressionType castTo, ExpressionPtr* Expressions, std::size_t expressionCount) :
exprType(castTo)
{ {
auto node = std::make_shared<Cast>();
node->exprType = castTo;
for (std::size_t i = 0; i < expressionCount; ++i) 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) : inline std::shared_ptr<Constant> Constant::Build(bool value)
exprType(ExpressionType::Float1)
{ {
values.vec1 = value; auto node = std::make_shared<Constant>();
node->exprType = ExpressionType::Boolean;
node->values.bool1 = value;
return node;
} }
inline Constant::Constant(const Vector2f& value) : inline std::shared_ptr<Constant> Constant::Build(float value)
exprType(ExpressionType::Float2)
{ {
values.vec2 = value; auto node = std::make_shared<Constant>();
node->exprType = ExpressionType::Float1;
node->values.vec1 = value;
return node;
} }
inline Constant::Constant(const Vector3f& value) : inline std::shared_ptr<Constant> Constant::Build(const Vector2f& value)
exprType(ExpressionType::Float3)
{ {
values.vec3 = value; auto node = std::make_shared<Constant>();
node->exprType = ExpressionType::Float2;
node->values.vec2 = value;
return node;
} }
inline Constant::Constant(const Vector4f& value) : inline std::shared_ptr<Constant> Constant::Build(const Vector3f& value)
exprType(ExpressionType::Float4)
{ {
values.vec4 = value; auto node = std::make_shared<Constant>();
node->exprType = ExpressionType::Float3;
node->values.vec3 = value;
return node;
} }
inline SwizzleOp::SwizzleOp(ExpressionPtr expressionPtr, std::initializer_list<SwizzleComponent> swizzleComponents) : inline std::shared_ptr<Constant> Constant::Build(const Vector4f& value)
componentCount(swizzleComponents.size()),
expression(expressionPtr)
{ {
if (componentCount > 4) auto node = std::make_shared<Constant>();
throw std::runtime_error("Cannot swizzle more than four elements"); node->exprType = ExpressionType::Float4;
node->values.vec4 = value;
switch (expressionPtr->GetExpressionType()) return node;
{
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());
} }
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) inline SwizzleOp::SwizzleOp() :
throw std::runtime_error("Coordinates must be a Float2"); Expression(NodeType::SwizzleOp)
{
} }
inline BinaryFunc::BinaryFunc(BinaryIntrinsic Op, ExpressionPtr Left, ExpressionPtr Right) : inline std::shared_ptr<SwizzleOp> SwizzleOp::Build(ExpressionPtr expressionPtr, std::initializer_list<SwizzleComponent> swizzleComponents)
intrinsic(Op),
left(Left),
right(Right)
{ {
ExpressionType leftType = left->GetExpressionType(); auto node = std::make_shared<SwizzleOp>();
ExpressionType rightType = right->GetExpressionType(); node->componentCount = swizzleComponents.size();
node->expression = std::move(expressionPtr);
if (leftType != rightType) std::copy(swizzleComponents.begin(), swizzleComponents.end(), node->components.begin());
//TODO: AstParseError
throw std::runtime_error("Left expression type must match right expression type");
switch (intrinsic) return node;
{ }
case BinaryIntrinsic::CrossProduct:
{
if (leftType != ExpressionType::Float3) inline Sample2D::Sample2D() :
//TODO: AstParseError Expression(NodeType::Sample2D)
throw std::runtime_error("CrossProduct only works with Float3 expressions"); {
} }
}
inline std::shared_ptr<Sample2D> Sample2D::Build(ExpressionPtr samplerPtr, ExpressionPtr coordinatesPtr)
{
auto node = std::make_shared<Sample2D>();
node->coordinates = std::move(coordinatesPtr);
node->sampler = std::move(samplerPtr);
return node;
}
inline BinaryFunc::BinaryFunc() :
Expression(NodeType::BinaryFunc)
{
}
inline std::shared_ptr<BinaryFunc> BinaryFunc::Build(BinaryIntrinsic intrinsic, ExpressionPtr left, ExpressionPtr right)
{
auto node = std::make_shared<BinaryFunc>();
node->intrinsic = intrinsic;
node->left = std::move(left);
node->right = std::move(right);
return node;
} }
} }
} }

View File

@ -5,25 +5,25 @@
#include <Nazara/Renderer/ShaderBuilder.hpp> #include <Nazara/Renderer/ShaderBuilder.hpp>
#include <Nazara/Renderer/Debug.hpp> #include <Nazara/Renderer/Debug.hpp>
namespace Nz { namespace ShaderBuilder namespace Nz::ShaderBuilder
{ {
template<typename T> template<typename T>
template<typename... Args> template<typename... Args>
std::shared_ptr<T> GenBuilder<T>::operator()(Args&&... args) const std::shared_ptr<T> GenBuilder<T>::operator()(Args&&... args) const
{ {
return std::make_shared<T>(std::forward<Args>(args)...); return T::Build(std::forward<Args>(args)...);
} }
template<ShaderAst::AssignType op> template<ShaderAst::AssignType op>
std::shared_ptr<ShaderAst::AssignOp> AssignOpBuilder<op>::operator()(const ShaderAst::ExpressionPtr& left, const ShaderAst::ExpressionPtr& right) const std::shared_ptr<ShaderAst::AssignOp> AssignOpBuilder<op>::operator()(const ShaderAst::ExpressionPtr& left, const ShaderAst::ExpressionPtr& right) const
{ {
return std::make_shared<ShaderAst::AssignOp>(op, left, right); return ShaderAst::AssignOp::Build(op, left, right);
} }
template<ShaderAst::BinaryType op> template<ShaderAst::BinaryType op>
std::shared_ptr<ShaderAst::BinaryOp> BinOpBuilder<op>::operator()(const ShaderAst::ExpressionPtr& left, const ShaderAst::ExpressionPtr& right) const std::shared_ptr<ShaderAst::BinaryOp> BinOpBuilder<op>::operator()(const ShaderAst::ExpressionPtr& left, const ShaderAst::ExpressionPtr& right) const
{ {
return std::make_shared<ShaderAst::BinaryOp>(op, left, right); return ShaderAst::BinaryOp::Build(op, left, right);
} }
inline std::shared_ptr<ShaderAst::Variable> BuiltinBuilder::operator()(ShaderAst::BuiltinEntry builtin) const inline std::shared_ptr<ShaderAst::Variable> BuiltinBuilder::operator()(ShaderAst::BuiltinEntry builtin) const
@ -39,21 +39,21 @@ namespace Nz { namespace ShaderBuilder
NazaraAssert(exprType != ShaderAst::ExpressionType::Void, "Unhandled builtin"); NazaraAssert(exprType != ShaderAst::ExpressionType::Void, "Unhandled builtin");
return std::make_shared<ShaderAst::BuiltinVariable>(builtin, exprType); return ShaderAst::BuiltinVariable::Build(builtin, exprType);
} }
template<ShaderAst::VariableType type> template<ShaderAst::VariableType type>
template<typename... Args> template<typename... Args>
ShaderAst::NamedVariablePtr VarBuilder<type>::operator()(Args&&... args) const ShaderAst::NamedVariablePtr VarBuilder<type>::operator()(Args&&... args) const
{ {
return std::make_shared<ShaderAst::NamedVariable>(type, std::forward<Args>(args)...); return ShaderAst::NamedVariable::Build(type, std::forward<Args>(args)...);
} }
template<ShaderAst::ExpressionType Type, typename... Args> template<ShaderAst::ExpressionType Type, typename... Args>
std::shared_ptr<ShaderAst::Cast> Cast(Args&&... args) std::shared_ptr<ShaderAst::Cast> Cast(Args&&... args)
{ {
return std::make_shared<ShaderAst::Cast>(Type, std::forward<Args>(args)...); return ShaderAst::Cast::Build(Type, std::forward<Args>(args)...);
} }
} } }
#include <Nazara/Renderer/DebugOff.hpp> #include <Nazara/Renderer/DebugOff.hpp>

View File

@ -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 <Nazara/Prerequisites.hpp>
#include <Nazara/Core/ByteArray.hpp>
#include <Nazara/Core/ByteStream.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/ShaderVisitor.hpp>
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<typename T> void Container(T& container);
template<typename T> void Enum(T& enumVal);
virtual bool IsWriting() const = 0;
virtual void Node(NodePtr& node) = 0;
template<typename T> void Node(std::shared_ptr<T>& 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 <Nazara/Renderer/ShaderSerializer.inl>
#endif

View File

@ -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 <Nazara/Renderer/ShaderSerializer.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz::ShaderAst
{
template<typename T>
void ShaderSerializerBase::Container(T& container)
{
bool isWriting = IsWriting();
UInt32 size;
if (isWriting)
size = UInt32(container.size());
Value(size);
if (!isWriting)
container.resize(size);
}
template<typename T>
void ShaderSerializerBase::Enum(T& enumVal)
{
bool isWriting = IsWriting();
UInt32 value;
if (isWriting)
value = static_cast<UInt32>(enumVal);
Value(value);
if (!isWriting)
enumVal = static_cast<T>(value);
}
template<typename T>
inline void ShaderSerializerBase::Node(std::shared_ptr<T>& node)
{
bool isWriting = IsWriting();
NodePtr value;
if (isWriting)
value = node;
Node(value);
if (!isWriting)
node = std::static_pointer_cast<T>(value);
}
inline void ShaderSerializerBase::Value(std::size_t& val)
{
bool isWriting = IsWriting();
UInt32 value;
if (isWriting)
value = static_cast<UInt32>(val);
Value(value);
if (!isWriting)
val = static_cast<std::size_t>(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<ByteArray*>(&m_byteArray), OpenModeFlags(OpenMode_ReadOnly))
{
}
}
#include <Nazara/Renderer/DebugOff.hpp>

View File

@ -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 <Nazara/Prerequisites.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/ShaderAst.hpp>
#include <unordered_set>
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<String> m_conditions;
};
}
#endif

View File

@ -10,45 +10,22 @@
#include <Nazara/Prerequisites.hpp> #include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/String.hpp> #include <Nazara/Core/String.hpp>
#include <Nazara/Renderer/Config.hpp> #include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/ShaderAst.hpp> #include <Nazara/Renderer/ShaderVisitor.hpp>
#include <unordered_set>
namespace Nz namespace Nz
{ {
class NAZARA_RENDERER_API ShaderWriter class NAZARA_RENDERER_API ShaderWriter : public ShaderVisitor
{ {
public: public:
ShaderWriter() = default; ShaderWriter() = default;
ShaderWriter(const ShaderWriter&) = delete; ShaderWriter(const ShaderWriter&) = delete;
ShaderWriter(ShaderWriter&&) = delete; ShaderWriter(ShaderWriter&&) = delete;
virtual ~ShaderWriter(); ~ShaderWriter() = default;
void EnableCondition(const String& name, bool cond);
bool IsConditionEnabled(const String& name) const;
virtual Nz::String Generate(const ShaderAst::StatementPtr& node) = 0; virtual Nz::String Generate(const ShaderAst::StatementPtr& node) = 0;
virtual void RegisterFunction(const String& name, ShaderAst::StatementPtr node, std::initializer_list<ShaderAst::NamedVariablePtr> parameters, ShaderAst::ExpressionType ret) = 0; virtual void RegisterFunction(const String& name, ShaderAst::StatementPtr node, std::initializer_list<ShaderAst::NamedVariablePtr> parameters, ShaderAst::ExpressionType ret) = 0;
virtual void RegisterVariable(ShaderAst::VariableType kind, const String& name, ShaderAst::ExpressionType type) = 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<String> m_conditions;
}; };
} }

View File

@ -116,23 +116,18 @@ namespace Nz
m_glslVersion = version; m_glslVersion = version;
} }
void GlslWriter::Write(const ShaderAst::NodePtr& node) void GlslWriter::Visit(const ShaderAst::Sample2D& node)
{
node->Visit(*this);
}
void GlslWriter::Write(const ShaderAst::Sample2D& node)
{ {
Append("texture("); Append("texture(");
Write(node.sampler); Visit(node.sampler);
Append(", "); Append(", ");
Write(node.coordinates); Visit(node.coordinates);
Append(")"); Append(")");
} }
void GlslWriter::Write(const ShaderAst::AssignOp& node) void GlslWriter::Visit(const ShaderAst::AssignOp& node)
{ {
Write(node.left); Visit(node.left);
switch (node.op) switch (node.op)
{ {
@ -141,10 +136,10 @@ namespace Nz
break; break;
} }
Write(node.right); Visit(node.right);
} }
void GlslWriter::Write(const ShaderAst::Branch& node) void GlslWriter::Visit(const ShaderAst::Branch& node)
{ {
bool first = true; bool first = true;
for (const auto& statement : node.condStatements) for (const auto& statement : node.condStatements)
@ -153,11 +148,11 @@ namespace Nz
Append("else "); Append("else ");
Append("if ("); Append("if (");
Write(statement.condition); Visit(statement.condition);
AppendLine(")"); AppendLine(")");
EnterScope(); EnterScope();
Write(statement.statement); Visit(statement.statement);
LeaveScope(); LeaveScope();
first = false; first = false;
@ -168,12 +163,12 @@ namespace Nz
AppendLine("else"); AppendLine("else");
EnterScope(); EnterScope();
Write(node.elseStatement); Visit(node.elseStatement);
LeaveScope(); LeaveScope();
} }
} }
void GlslWriter::Write(const ShaderAst::BinaryFunc& node) void GlslWriter::Visit(const ShaderAst::BinaryFunc& node)
{ {
switch (node.intrinsic) switch (node.intrinsic)
{ {
@ -187,15 +182,15 @@ namespace Nz
} }
Append("("); Append("(");
Write(node.left); Visit(node.left);
Append(", "); Append(", ");
Write(node.right); Visit(node.right);
Append(")"); Append(")");
} }
void GlslWriter::Write(const ShaderAst::BinaryOp& node) void GlslWriter::Visit(const ShaderAst::BinaryOp& node)
{ {
Write(node.left); Visit(node.left);
switch (node.op) switch (node.op)
{ {
@ -216,15 +211,15 @@ namespace Nz
break; break;
} }
Write(node.right); Visit(node.right);
} }
void GlslWriter::Write(const ShaderAst::BuiltinVariable& node) void GlslWriter::Visit(const ShaderAst::BuiltinVariable& node)
{ {
Append(node.var); Append(node.var);
} }
void GlslWriter::Write(const ShaderAst::Cast& node) void GlslWriter::Visit(const ShaderAst::Cast& node)
{ {
Append(node.exprType); Append(node.exprType);
Append("("); Append("(");
@ -239,14 +234,14 @@ namespace Nz
const auto& exprPtr = node.expressions[i++]; const auto& exprPtr = node.expressions[i++];
NazaraAssert(exprPtr, "Invalid expression"); NazaraAssert(exprPtr, "Invalid expression");
Write(exprPtr); Visit(exprPtr);
requiredComponents -= ShaderAst::Node::GetComponentCount(exprPtr->GetExpressionType()); requiredComponents -= ShaderAst::Node::GetComponentCount(exprPtr->GetExpressionType());
} }
Append(")"); Append(")");
} }
void GlslWriter::Write(const ShaderAst::Constant& node) void GlslWriter::Visit(const ShaderAst::Constant& node)
{ {
switch (node.exprType) 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(node.variable->GetExpressionType());
Append(" "); Append(" ");
@ -285,24 +280,24 @@ namespace Nz
Append(" "); Append(" ");
Append("="); Append("=");
Append(" "); Append(" ");
Write(node.expression); Visit(node.expression);
} }
AppendLine(";"); AppendLine(";");
} }
void GlslWriter::Write(const ShaderAst::ExpressionStatement& node) void GlslWriter::Visit(const ShaderAst::ExpressionStatement& node)
{ {
Write(node.expression); Visit(node.expression);
Append(";"); Append(";");
} }
void GlslWriter::Write(const ShaderAst::NamedVariable& node) void GlslWriter::Visit(const ShaderAst::NamedVariable& node)
{ {
Append(node.name); Append(node.name);
} }
void GlslWriter::Write(const ShaderAst::StatementBlock& node) void GlslWriter::Visit(const ShaderAst::StatementBlock& node)
{ {
bool first = true; bool first = true;
for (const ShaderAst::StatementPtr& statement : node.statements) for (const ShaderAst::StatementPtr& statement : node.statements)
@ -310,15 +305,15 @@ namespace Nz
if (!first) if (!first)
AppendLine(); AppendLine();
Write(statement); Visit(statement);
first = false; first = false;
} }
} }
void GlslWriter::Write(const ShaderAst::SwizzleOp& node) void GlslWriter::Visit(const ShaderAst::SwizzleOp& node)
{ {
Write(node.expression); Visit(node.expression);
Append("."); Append(".");
for (std::size_t i = 0; i < node.componentCount; ++i) for (std::size_t i = 0; i < node.componentCount; ++i)
@ -433,7 +428,7 @@ namespace Nz
EnterScope(); EnterScope();
{ {
Write(func.node); Visit(func.node);
} }
LeaveScope(); LeaveScope();
} }

View File

@ -69,7 +69,7 @@ namespace Nz
}; };
RegisterImpl("NazaraOpenGLRenderer" NazaraRendererDebugSuffix, [] { return 50; }); 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; }); std::sort(implementations.begin(), implementations.end(), [](const auto& lhs, const auto& rhs) { return lhs.score > rhs.score; });

View File

@ -3,11 +3,15 @@
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/ShaderAst.hpp> #include <Nazara/Renderer/ShaderAst.hpp>
#include <Nazara/Core/ByteStream.hpp>
#include <Nazara/Renderer/ShaderSerializer.hpp>
#include <Nazara/Renderer/ShaderWriter.hpp> #include <Nazara/Renderer/ShaderWriter.hpp>
#include <Nazara/Renderer/Debug.hpp> #include <Nazara/Renderer/Debug.hpp>
namespace Nz::ShaderAst namespace Nz::ShaderAst
{ {
Node::~Node() = default;
ExpressionCategory Expression::GetExpressionCategory() const ExpressionCategory Expression::GetExpressionCategory() const
{ {
return ExpressionCategory::RValue; return ExpressionCategory::RValue;
@ -18,9 +22,9 @@ namespace Nz::ShaderAst
expression->Register(visitor); 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); statement->Register(visitor);
} }
void ConditionalStatement::Visit(ShaderWriter& visitor) void ConditionalStatement::Visit(ShaderVisitor& visitor)
{ {
if (visitor.IsConditionEnabled(conditionName)) if (visitor.IsConditionEnabled(conditionName))
statement->Visit(visitor); statement->Visit(visitor);
@ -43,9 +47,9 @@ namespace Nz::ShaderAst
statementPtr->Register(visitor); statementPtr->Register(visitor);
} }
void StatementBlock::Visit(ShaderWriter& visitor) void StatementBlock::Visit(ShaderVisitor& visitor)
{ {
visitor.Write(*this); visitor.Visit(*this);
} }
ExpressionCategory Variable::GetExpressionCategory() const ExpressionCategory Variable::GetExpressionCategory() const
@ -58,14 +62,25 @@ namespace Nz::ShaderAst
return type; return type;
} }
void BuiltinVariable::Register(ShaderWriter& /*visitor*/)
{
}
void BuiltinVariable::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
void NamedVariable::Register(ShaderWriter& visitor) void NamedVariable::Register(ShaderWriter& visitor)
{ {
visitor.RegisterVariable(kind, name, type); 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); expression->Register(visitor);
} }
void DeclareVariable::Visit(ShaderWriter& visitor) void DeclareVariable::Visit(ShaderVisitor& visitor)
{ {
visitor.Write(*this); visitor.Visit(*this);
}
void BuiltinVariable::Register(ShaderWriter& /*visitor*/)
{
}
void BuiltinVariable::Visit(ShaderWriter& visitor)
{
visitor.Write(*this);
} }
@ -103,9 +109,9 @@ namespace Nz::ShaderAst
right->Register(visitor); 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); 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); 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 ExpressionType Cast::GetExpressionType() const
@ -195,26 +201,9 @@ namespace Nz::ShaderAst
} }
} }
void Cast::Visit(ShaderWriter& visitor) void Cast::Visit(ShaderVisitor& visitor)
{ {
visitor.Write(*this); visitor.Visit(*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");
} }
@ -233,9 +222,9 @@ namespace Nz::ShaderAst
expression->Register(visitor); 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); 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); right->Register(visitor);
} }
void BinaryFunc::Visit(ShaderWriter& visitor) void BinaryFunc::Visit(ShaderVisitor& visitor)
{ {
visitor.Write(*this); visitor.Visit(*this);
} }
} }

View File

@ -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 <Nazara/Renderer/ShaderSerializer.hpp>
#include <Nazara/Renderer/Debug.hpp>
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<typename T>
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<T&>(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<Int32>(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<Int32>(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>(statement);
}
bool ShaderUnserializer::IsWriting() const
{
return false;
}
void ShaderUnserializer::Node(NodePtr& node)
{
Int32 nodeTypeInt;
m_stream >> nodeTypeInt;
NodeType nodeType = static_cast<NodeType>(nodeTypeInt);
#define HandleNodeType(Type) case NodeType:: Type : node = std::make_shared<Type>(); 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;
}
}

View File

@ -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 <Nazara/Renderer/ShaderVisitor.hpp>
#include <Nazara/Renderer/Debug.hpp>
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);
}
}

View File

@ -7,18 +7,4 @@
namespace Nz 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;
}
} }

View File

@ -352,7 +352,7 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst()
} }
}); });
return std::make_shared<Nz::ShaderAst::StatementBlock>(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) void ShaderGraph::UpdateInput(std::size_t inputIndex, std::string name, InOutType type, InputRole role, std::size_t roleIndex)