Shader: Cleanup and rename AST files

This commit is contained in:
Jérôme Leclercq
2021-04-15 13:38:14 +02:00
parent afe3a0ea93
commit d335d44d6a
62 changed files with 105 additions and 141 deletions

View File

@@ -0,0 +1,321 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Shader/Ast/AstCloner.hpp>
#include <stdexcept>
#include <Nazara/Shader/Debug.hpp>
namespace Nz::ShaderAst
{
ExpressionPtr AstCloner::Clone(ExpressionPtr& expr)
{
expr->Visit(*this);
assert(m_statementStack.empty() && m_expressionStack.size() == 1);
return PopExpression();
}
StatementPtr AstCloner::Clone(StatementPtr& statement)
{
statement->Visit(*this);
assert(m_expressionStack.empty() && m_statementStack.size() == 1);
return PopStatement();
}
ExpressionPtr AstCloner::CloneExpression(Expression& expr)
{
expr.Visit(*this);
return PopExpression();
}
StatementPtr AstCloner::CloneStatement(Statement& statement)
{
statement.Visit(*this);
return PopStatement();
}
StatementPtr AstCloner::Clone(BranchStatement& node)
{
auto clone = std::make_unique<BranchStatement>();
clone->condStatements.reserve(node.condStatements.size());
for (auto& cond : node.condStatements)
{
auto& condStatement = clone->condStatements.emplace_back();
condStatement.condition = CloneExpression(cond.condition);
condStatement.statement = CloneStatement(cond.statement);
}
clone->elseStatement = CloneStatement(node.elseStatement);
return clone;
}
StatementPtr AstCloner::Clone(ConditionalStatement& node)
{
auto clone = std::make_unique<ConditionalStatement>();
clone->conditionName = node.conditionName;
clone->statement = CloneStatement(node.statement);
return clone;
}
StatementPtr AstCloner::Clone(DeclareExternalStatement& node)
{
auto clone = std::make_unique<DeclareExternalStatement>();
clone->externalVars = node.externalVars;
clone->varIndex = node.varIndex;
return clone;
}
StatementPtr AstCloner::Clone(DeclareFunctionStatement& node)
{
auto clone = std::make_unique<DeclareFunctionStatement>();
clone->entryStage = node.entryStage;
clone->funcIndex = node.funcIndex;
clone->name = node.name;
clone->parameters = node.parameters;
clone->returnType = node.returnType;
clone->varIndex = node.varIndex;
clone->statements.reserve(node.statements.size());
for (auto& statement : node.statements)
clone->statements.push_back(CloneStatement(statement));
return clone;
}
StatementPtr AstCloner::Clone(DeclareStructStatement& node)
{
auto clone = std::make_unique<DeclareStructStatement>();
clone->structIndex = node.structIndex;
clone->description = node.description;
return clone;
}
StatementPtr AstCloner::Clone(DeclareVariableStatement& node)
{
auto clone = std::make_unique<DeclareVariableStatement>();
clone->varIndex = node.varIndex;
clone->varName = node.varName;
clone->varType = node.varType;
clone->initialExpression = CloneExpression(node.initialExpression);
return clone;
}
StatementPtr AstCloner::Clone(DiscardStatement& /*node*/)
{
return std::make_unique<DiscardStatement>();
}
StatementPtr AstCloner::Clone(ExpressionStatement& node)
{
auto clone = std::make_unique<ExpressionStatement>();
clone->expression = CloneExpression(node.expression);
return clone;
}
StatementPtr AstCloner::Clone(MultiStatement& node)
{
auto clone = std::make_unique<MultiStatement>();
clone->statements.reserve(node.statements.size());
for (auto& statement : node.statements)
clone->statements.push_back(CloneStatement(statement));
return clone;
}
StatementPtr AstCloner::Clone(NoOpStatement& /*node*/)
{
return std::make_unique<NoOpStatement>();
}
StatementPtr AstCloner::Clone(ReturnStatement& node)
{
auto clone = std::make_unique<ReturnStatement>();
clone->returnExpr = CloneExpression(node.returnExpr);
return clone;
}
ExpressionPtr AstCloner::Clone(AccessMemberIdentifierExpression& node)
{
auto clone = std::make_unique<AccessMemberIdentifierExpression>();
clone->memberIdentifiers = node.memberIdentifiers;
clone->structExpr = CloneExpression(node.structExpr);
clone->cachedExpressionType = node.cachedExpressionType;
return clone;
}
ExpressionPtr AstCloner::Clone(AccessMemberIndexExpression& node)
{
auto clone = std::make_unique<AccessMemberIndexExpression>();
clone->memberIndices = node.memberIndices;
clone->structExpr = CloneExpression(node.structExpr);
clone->cachedExpressionType = node.cachedExpressionType;
return clone;
}
ExpressionPtr AstCloner::Clone(AssignExpression& node)
{
auto clone = std::make_unique<AssignExpression>();
clone->op = node.op;
clone->left = CloneExpression(node.left);
clone->right = CloneExpression(node.right);
clone->cachedExpressionType = node.cachedExpressionType;
return clone;
}
ExpressionPtr AstCloner::Clone(BinaryExpression& node)
{
auto clone = std::make_unique<BinaryExpression>();
clone->op = node.op;
clone->left = CloneExpression(node.left);
clone->right = CloneExpression(node.right);
clone->cachedExpressionType = node.cachedExpressionType;
return clone;
}
ExpressionPtr AstCloner::Clone(CastExpression& node)
{
auto clone = std::make_unique<CastExpression>();
clone->targetType = node.targetType;
std::size_t expressionCount = 0;
for (auto& expr : node.expressions)
{
if (!expr)
break;
clone->expressions[expressionCount++] = CloneExpression(expr);
}
clone->cachedExpressionType = node.cachedExpressionType;
return clone;
}
ExpressionPtr AstCloner::Clone(ConditionalExpression& node)
{
auto clone = std::make_unique<ConditionalExpression>();
clone->conditionName = node.conditionName;
clone->falsePath = CloneExpression(node.falsePath);
clone->truePath = CloneExpression(node.truePath);
clone->cachedExpressionType = node.cachedExpressionType;
return clone;
}
ExpressionPtr AstCloner::Clone(ConstantExpression& node)
{
auto clone = std::make_unique<ConstantExpression>();
clone->value = node.value;
clone->cachedExpressionType = node.cachedExpressionType;
return clone;
}
ExpressionPtr AstCloner::Clone(IdentifierExpression& node)
{
auto clone = std::make_unique<IdentifierExpression>();
clone->identifier = node.identifier;
clone->cachedExpressionType = node.cachedExpressionType;
return clone;
}
ExpressionPtr AstCloner::Clone(IntrinsicExpression& node)
{
auto clone = std::make_unique<IntrinsicExpression>();
clone->intrinsic = node.intrinsic;
clone->parameters.reserve(node.parameters.size());
for (auto& parameter : node.parameters)
clone->parameters.push_back(CloneExpression(parameter));
clone->cachedExpressionType = node.cachedExpressionType;
return clone;
}
ExpressionPtr AstCloner::Clone(SwizzleExpression& node)
{
auto clone = std::make_unique<SwizzleExpression>();
clone->componentCount = node.componentCount;
clone->components = node.components;
clone->expression = CloneExpression(node.expression);
clone->cachedExpressionType = node.cachedExpressionType;
return clone;
}
ExpressionPtr AstCloner::Clone(VariableExpression& node)
{
auto clone = std::make_unique<VariableExpression>();
clone->variableId = node.variableId;
clone->cachedExpressionType = node.cachedExpressionType;
return clone;
}
#define NAZARA_SHADERAST_EXPRESSION(NodeType) void AstCloner::Visit(NodeType& node) \
{ \
PushExpression(Clone(node)); \
}
#define NAZARA_SHADERAST_STATEMENT(NodeType) void AstCloner::Visit(NodeType& node) \
{ \
PushStatement(Clone(node)); \
}
#include <Nazara/Shader/Ast/AstNodeList.hpp>
void AstCloner::PushExpression(ExpressionPtr expression)
{
m_expressionStack.emplace_back(std::move(expression));
}
void AstCloner::PushStatement(StatementPtr statement)
{
m_statementStack.emplace_back(std::move(statement));
}
ExpressionPtr AstCloner::PopExpression()
{
assert(!m_expressionStack.empty());
ExpressionPtr expr = std::move(m_expressionStack.back());
m_expressionStack.pop_back();
return expr;
}
StatementPtr AstCloner::PopStatement()
{
assert(!m_statementStack.empty());
StatementPtr expr = std::move(m_statementStack.back());
m_statementStack.pop_back();
return expr;
}
}

View File

@@ -0,0 +1,11 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Shader/Ast/AstExpressionVisitor.hpp>
#include <Nazara/Shader/Debug.hpp>
namespace Nz::ShaderAst
{
AstExpressionVisitor::~AstExpressionVisitor() = default;
}

View File

@@ -0,0 +1,15 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Shader/Ast/AstExpressionVisitorExcept.hpp>
#include <Nazara/Shader/Debug.hpp>
namespace Nz::ShaderAst
{
#define NAZARA_SHADERAST_EXPRESSION(Node) void ExpressionVisitorExcept::Visit(ShaderAst::Node& /*node*/) \
{ \
throw std::runtime_error("unexpected " #Node " node"); \
}
#include <Nazara/Shader/Ast/AstNodeList.hpp>
}

View File

@@ -0,0 +1,562 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Shader/Ast/AstOptimizer.hpp>
#include <Nazara/Shader/ShaderBuilder.hpp>
#include <cassert>
#include <stdexcept>
#include <Nazara/Shader/Debug.hpp>
namespace Nz::ShaderAst
{
namespace
{
template<typename T, typename U>
std::unique_ptr<T> static_unique_pointer_cast(std::unique_ptr<U>&& ptr)
{
return std::unique_ptr<T>(static_cast<T*>(ptr.release()));
}
template <typename T>
struct is_complete_helper
{
template <typename U> static auto test(U*)->std::integral_constant<bool, sizeof(U) == sizeof(U)>;
static auto test(...) -> std::false_type;
using type = decltype(test((T*)0));
};
template <typename T>
struct is_complete : is_complete_helper<T>::type {};
template<typename T>
inline constexpr bool is_complete_v = is_complete<T>::value;
template<BinaryType Type, typename T1, typename T2>
struct PropagateConstantType;
// CompEq
template<typename T1, typename T2>
struct CompEqBase
{
ExpressionPtr operator()(const T1& lhs, const T2& rhs)
{
return ShaderBuilder::Constant(lhs == rhs);
}
};
template<typename T1, typename T2>
struct CompEq;
template<typename T1, typename T2>
struct PropagateConstantType<BinaryType::CompEq, T1, T2>
{
using Op = typename CompEq<T1, T2>;
};
// CompGe
template<typename T1, typename T2>
struct CompGeBase
{
ExpressionPtr operator()(const T1& lhs, const T2& rhs)
{
return ShaderBuilder::Constant(lhs >= rhs);
}
};
template<typename T1, typename T2>
struct CompGe;
template<typename T1, typename T2>
struct PropagateConstantType<BinaryType::CompGe, T1, T2>
{
using Op = typename CompGe<T1, T2>;
};
// CompGt
template<typename T1, typename T2>
struct CompGtBase
{
ExpressionPtr operator()(const T1& lhs, const T2& rhs)
{
return ShaderBuilder::Constant(lhs > rhs);
}
};
template<typename T1, typename T2>
struct CompGt;
template<typename T1, typename T2>
struct PropagateConstantType<BinaryType::CompGt, T1, T2>
{
using Op = typename CompGt<T1, T2>;
};
// CompLe
template<typename T1, typename T2>
struct CompLeBase
{
ExpressionPtr operator()(const T1& lhs, const T2& rhs)
{
return ShaderBuilder::Constant(lhs <= rhs);
}
};
template<typename T1, typename T2>
struct CompLe;
template<typename T1, typename T2>
struct PropagateConstantType<BinaryType::CompLe, T1, T2>
{
using Op = typename CompLe<T1, T2>;
};
// CompLt
template<typename T1, typename T2>
struct CompLtBase
{
ExpressionPtr operator()(const T1& lhs, const T2& rhs)
{
return ShaderBuilder::Constant(lhs < rhs);
}
};
template<typename T1, typename T2>
struct CompLt;
template<typename T1, typename T2>
struct PropagateConstantType<BinaryType::CompLt, T1, T2>
{
using Op = typename CompLe<T1, T2>;
};
// CompNe
template<typename T1, typename T2>
struct CompNeBase
{
ExpressionPtr operator()(const T1& lhs, const T2& rhs)
{
return ShaderBuilder::Constant(lhs != rhs);
}
};
template<typename T1, typename T2>
struct CompNe;
template<typename T1, typename T2>
struct PropagateConstantType<BinaryType::CompNe, T1, T2>
{
using Op = typename CompNe<T1, T2>;
};
// Addition
template<typename T1, typename T2>
struct AdditionBase
{
ExpressionPtr operator()(const T1& lhs, const T2& rhs)
{
return ShaderBuilder::Constant(lhs + rhs);
}
};
template<typename T1, typename T2>
struct Addition;
template<typename T1, typename T2>
struct PropagateConstantType<BinaryType::Add, T1, T2>
{
using Op = typename Addition<T1, T2>;
};
// Division
template<typename T1, typename T2>
struct DivisionBase
{
ExpressionPtr operator()(const T1& lhs, const T2& rhs)
{
return ShaderBuilder::Constant(lhs / rhs);
}
};
template<typename T1, typename T2>
struct Division;
template<typename T1, typename T2>
struct PropagateConstantType<BinaryType::Divide, T1, T2>
{
using Op = typename Division<T1, T2>;
};
// Multiplication
template<typename T1, typename T2>
struct MultiplicationBase
{
ExpressionPtr operator()(const T1& lhs, const T2& rhs)
{
return ShaderBuilder::Constant(lhs * rhs);
}
};
template<typename T1, typename T2>
struct Multiplication;
template<typename T1, typename T2>
struct PropagateConstantType<BinaryType::Multiply, T1, T2>
{
using Op = typename Multiplication<T1, T2>;
};
// Subtraction
template<typename T1, typename T2>
struct SubtractionBase
{
ExpressionPtr operator()(const T1& lhs, const T2& rhs)
{
return ShaderBuilder::Constant(lhs - rhs);
}
};
template<typename T1, typename T2>
struct Subtraction;
template<typename T1, typename T2>
struct PropagateConstantType<BinaryType::Subtract, T1, T2>
{
using Op = typename Subtraction<T1, T2>;
};
#define EnableOptimisation(Op, T1, T2) template<> struct Op<T1, T2> : Op##Base<T1, T2> {}
EnableOptimisation(CompEq, bool, bool);
EnableOptimisation(CompEq, double, double);
EnableOptimisation(CompEq, float, float);
EnableOptimisation(CompEq, Nz::Int32, Nz::Int32);
EnableOptimisation(CompEq, Nz::Vector2f, Nz::Vector2f);
EnableOptimisation(CompEq, Nz::Vector3f, Nz::Vector3f);
EnableOptimisation(CompEq, Nz::Vector4f, Nz::Vector4f);
EnableOptimisation(CompEq, Nz::Vector2i32, Nz::Vector2i32);
EnableOptimisation(CompEq, Nz::Vector3i32, Nz::Vector3i32);
EnableOptimisation(CompEq, Nz::Vector4i32, Nz::Vector4i32);
EnableOptimisation(CompGe, bool, bool);
EnableOptimisation(CompGe, double, double);
EnableOptimisation(CompGe, float, float);
EnableOptimisation(CompGe, Nz::Int32, Nz::Int32);
EnableOptimisation(CompGe, Nz::Vector2f, Nz::Vector2f);
EnableOptimisation(CompGe, Nz::Vector3f, Nz::Vector3f);
EnableOptimisation(CompGe, Nz::Vector4f, Nz::Vector4f);
EnableOptimisation(CompGe, Nz::Vector2i32, Nz::Vector2i32);
EnableOptimisation(CompGe, Nz::Vector3i32, Nz::Vector3i32);
EnableOptimisation(CompGe, Nz::Vector4i32, Nz::Vector4i32);
EnableOptimisation(CompGt, bool, bool);
EnableOptimisation(CompGt, double, double);
EnableOptimisation(CompGt, float, float);
EnableOptimisation(CompGt, Nz::Int32, Nz::Int32);
EnableOptimisation(CompGt, Nz::Vector2f, Nz::Vector2f);
EnableOptimisation(CompGt, Nz::Vector3f, Nz::Vector3f);
EnableOptimisation(CompGt, Nz::Vector4f, Nz::Vector4f);
EnableOptimisation(CompGt, Nz::Vector2i32, Nz::Vector2i32);
EnableOptimisation(CompGt, Nz::Vector3i32, Nz::Vector3i32);
EnableOptimisation(CompGt, Nz::Vector4i32, Nz::Vector4i32);
EnableOptimisation(CompLe, bool, bool);
EnableOptimisation(CompLe, double, double);
EnableOptimisation(CompLe, float, float);
EnableOptimisation(CompLe, Nz::Int32, Nz::Int32);
EnableOptimisation(CompLe, Nz::Vector2f, Nz::Vector2f);
EnableOptimisation(CompLe, Nz::Vector3f, Nz::Vector3f);
EnableOptimisation(CompLe, Nz::Vector4f, Nz::Vector4f);
EnableOptimisation(CompLe, Nz::Vector2i32, Nz::Vector2i32);
EnableOptimisation(CompLe, Nz::Vector3i32, Nz::Vector3i32);
EnableOptimisation(CompLe, Nz::Vector4i32, Nz::Vector4i32);
EnableOptimisation(CompLt, bool, bool);
EnableOptimisation(CompLt, double, double);
EnableOptimisation(CompLt, float, float);
EnableOptimisation(CompLt, Nz::Int32, Nz::Int32);
EnableOptimisation(CompLt, Nz::Vector2f, Nz::Vector2f);
EnableOptimisation(CompLt, Nz::Vector3f, Nz::Vector3f);
EnableOptimisation(CompLt, Nz::Vector4f, Nz::Vector4f);
EnableOptimisation(CompLt, Nz::Vector2i32, Nz::Vector2i32);
EnableOptimisation(CompLt, Nz::Vector3i32, Nz::Vector3i32);
EnableOptimisation(CompLt, Nz::Vector4i32, Nz::Vector4i32);
EnableOptimisation(CompNe, bool, bool);
EnableOptimisation(CompNe, double, double);
EnableOptimisation(CompNe, float, float);
EnableOptimisation(CompNe, Nz::Int32, Nz::Int32);
EnableOptimisation(CompNe, Nz::Vector2f, Nz::Vector2f);
EnableOptimisation(CompNe, Nz::Vector3f, Nz::Vector3f);
EnableOptimisation(CompNe, Nz::Vector4f, Nz::Vector4f);
EnableOptimisation(CompNe, Nz::Vector2i32, Nz::Vector2i32);
EnableOptimisation(CompNe, Nz::Vector3i32, Nz::Vector3i32);
EnableOptimisation(CompNe, Nz::Vector4i32, Nz::Vector4i32);
EnableOptimisation(Addition, double, double);
EnableOptimisation(Addition, float, float);
EnableOptimisation(Addition, Nz::Int32, Nz::Int32);
EnableOptimisation(Addition, Nz::Vector2f, Nz::Vector2f);
EnableOptimisation(Addition, Nz::Vector3f, Nz::Vector3f);
EnableOptimisation(Addition, Nz::Vector4f, Nz::Vector4f);
EnableOptimisation(Addition, Nz::Vector2i32, Nz::Vector2i32);
EnableOptimisation(Addition, Nz::Vector3i32, Nz::Vector3i32);
EnableOptimisation(Addition, Nz::Vector4i32, Nz::Vector4i32);
EnableOptimisation(Division, double, double);
EnableOptimisation(Division, double, Nz::Vector2d);
EnableOptimisation(Division, double, Nz::Vector3d);
EnableOptimisation(Division, double, Nz::Vector4d);
EnableOptimisation(Division, float, float);
EnableOptimisation(Division, float, Nz::Vector2f);
EnableOptimisation(Division, float, Nz::Vector3f);
EnableOptimisation(Division, float, Nz::Vector4f);
EnableOptimisation(Division, Nz::Int32, Nz::Int32);
EnableOptimisation(Division, Nz::Int32, Nz::Vector2i32);
EnableOptimisation(Division, Nz::Int32, Nz::Vector3i32);
EnableOptimisation(Division, Nz::Int32, Nz::Vector4i32);
EnableOptimisation(Division, Nz::Vector2f, float);
EnableOptimisation(Division, Nz::Vector2f, Nz::Vector2f);
EnableOptimisation(Division, Nz::Vector3f, float);
EnableOptimisation(Division, Nz::Vector3f, Nz::Vector3f);
EnableOptimisation(Division, Nz::Vector4f, float);
EnableOptimisation(Division, Nz::Vector4f, Nz::Vector4f);
EnableOptimisation(Division, Nz::Vector2d, double);
EnableOptimisation(Division, Nz::Vector2d, Nz::Vector2d);
EnableOptimisation(Division, Nz::Vector3d, double);
EnableOptimisation(Division, Nz::Vector3d, Nz::Vector3d);
EnableOptimisation(Division, Nz::Vector4d, double);
EnableOptimisation(Division, Nz::Vector4d, Nz::Vector4d);
EnableOptimisation(Division, Nz::Vector2i32, Nz::Int32);
EnableOptimisation(Division, Nz::Vector2i32, Nz::Vector2i32);
EnableOptimisation(Division, Nz::Vector3i32, Nz::Int32);
EnableOptimisation(Division, Nz::Vector3i32, Nz::Vector3i32);
EnableOptimisation(Division, Nz::Vector4i32, Nz::Int32);
EnableOptimisation(Division, Nz::Vector4i32, Nz::Vector4i32);
EnableOptimisation(Multiplication, double, double);
EnableOptimisation(Multiplication, double, Nz::Vector2d);
EnableOptimisation(Multiplication, double, Nz::Vector3d);
EnableOptimisation(Multiplication, double, Nz::Vector4d);
EnableOptimisation(Multiplication, float, float);
EnableOptimisation(Multiplication, float, Nz::Vector2f);
EnableOptimisation(Multiplication, float, Nz::Vector3f);
EnableOptimisation(Multiplication, float, Nz::Vector4f);
EnableOptimisation(Multiplication, Nz::Int32, Nz::Int32);
EnableOptimisation(Multiplication, Nz::Int32, Nz::Vector2i32);
EnableOptimisation(Multiplication, Nz::Int32, Nz::Vector3i32);
EnableOptimisation(Multiplication, Nz::Int32, Nz::Vector4i32);
EnableOptimisation(Multiplication, Nz::Vector2f, float);
EnableOptimisation(Multiplication, Nz::Vector2f, Nz::Vector2f);
EnableOptimisation(Multiplication, Nz::Vector3f, float);
EnableOptimisation(Multiplication, Nz::Vector3f, Nz::Vector3f);
EnableOptimisation(Multiplication, Nz::Vector4f, float);
EnableOptimisation(Multiplication, Nz::Vector4f, Nz::Vector4f);
EnableOptimisation(Multiplication, Nz::Vector2d, double);
EnableOptimisation(Multiplication, Nz::Vector2d, Nz::Vector2d);
EnableOptimisation(Multiplication, Nz::Vector3d, double);
EnableOptimisation(Multiplication, Nz::Vector3d, Nz::Vector3d);
EnableOptimisation(Multiplication, Nz::Vector4d, double);
EnableOptimisation(Multiplication, Nz::Vector4d, Nz::Vector4d);
EnableOptimisation(Multiplication, Nz::Vector2i32, Nz::Int32);
EnableOptimisation(Multiplication, Nz::Vector2i32, Nz::Vector2i32);
EnableOptimisation(Multiplication, Nz::Vector3i32, Nz::Int32);
EnableOptimisation(Multiplication, Nz::Vector3i32, Nz::Vector3i32);
EnableOptimisation(Multiplication, Nz::Vector4i32, Nz::Int32);
EnableOptimisation(Multiplication, Nz::Vector4i32, Nz::Vector4i32);
EnableOptimisation(Subtraction, double, double);
EnableOptimisation(Subtraction, float, float);
EnableOptimisation(Subtraction, Nz::Int32, Nz::Int32);
EnableOptimisation(Subtraction, Nz::Vector2f, Nz::Vector2f);
EnableOptimisation(Subtraction, Nz::Vector3f, Nz::Vector3f);
EnableOptimisation(Subtraction, Nz::Vector4f, Nz::Vector4f);
EnableOptimisation(Subtraction, Nz::Vector2i32, Nz::Vector2i32);
EnableOptimisation(Subtraction, Nz::Vector3i32, Nz::Vector3i32);
EnableOptimisation(Subtraction, Nz::Vector4i32, Nz::Vector4i32);
#undef EnableOptimisation
}
StatementPtr AstOptimizer::Optimise(StatementPtr& statement)
{
return CloneStatement(statement);
}
StatementPtr AstOptimizer::Optimise(StatementPtr& statement, UInt64 enabledConditions)
{
m_enabledConditions = enabledConditions;
return CloneStatement(statement);
}
void AstOptimizer::Visit(BinaryExpression& node)
{
auto lhs = CloneExpression(node.left);
auto rhs = CloneExpression(node.right);
if (lhs->GetType() == NodeType::ConstantExpression && rhs->GetType() == NodeType::ConstantExpression)
{
auto lhsConstant = static_unique_pointer_cast<ConstantExpression>(std::move(lhs));
auto rhsConstant = static_unique_pointer_cast<ConstantExpression>(std::move(rhs));
switch (node.op)
{
case BinaryType::Add:
return PropagateConstant<BinaryType::Add>(std::move(lhsConstant), std::move(rhsConstant));
case BinaryType::Subtract:
return PropagateConstant<BinaryType::Subtract>(std::move(lhsConstant), std::move(rhsConstant));
case BinaryType::Multiply:
return PropagateConstant<BinaryType::Multiply>(std::move(lhsConstant), std::move(rhsConstant));
case BinaryType::Divide:
return PropagateConstant<BinaryType::Divide>(std::move(lhsConstant), std::move(rhsConstant));
case BinaryType::CompEq:
return PropagateConstant<BinaryType::CompEq>(std::move(lhsConstant), std::move(rhsConstant));
case BinaryType::CompGe:
return PropagateConstant<BinaryType::CompGe>(std::move(lhsConstant), std::move(rhsConstant));
case BinaryType::CompGt:
return PropagateConstant<BinaryType::CompGt>(std::move(lhsConstant), std::move(rhsConstant));
case BinaryType::CompLe:
return PropagateConstant<BinaryType::CompLe>(std::move(lhsConstant), std::move(rhsConstant));
case BinaryType::CompLt:
return PropagateConstant<BinaryType::CompLt>(std::move(lhsConstant), std::move(rhsConstant));
case BinaryType::CompNe:
return PropagateConstant<BinaryType::CompNe>(std::move(lhsConstant), std::move(rhsConstant));
}
}
AstCloner::Visit(node);
}
void AstOptimizer::Visit(BranchStatement& node)
{
std::vector<BranchStatement::ConditionalStatement> statements;
StatementPtr elseStatement;
for (auto& condStatement : node.condStatements)
{
auto cond = CloneExpression(condStatement.condition);
if (cond->GetType() == NodeType::ConstantExpression)
{
auto& constant = static_cast<ConstantExpression&>(*cond);
assert(constant.cachedExpressionType);
const ExpressionType& constantType = constant.cachedExpressionType.value();
assert(IsPrimitiveType(constantType));
assert(std::get<PrimitiveType>(constantType) == PrimitiveType::Boolean);
bool cValue = std::get<bool>(constant.value);
if (!cValue)
continue;
if (statements.empty())
{
// First condition is true, dismiss the branch
condStatement.statement->Visit(*this);
return;
}
else
{
// Some condition after the first one is true, make it the else statement and stop there
elseStatement = CloneStatement(condStatement.statement);
break;
}
}
else
{
auto& c = statements.emplace_back();
c.condition = std::move(cond);
c.statement = CloneStatement(condStatement.statement);
}
}
if (statements.empty())
{
// All conditions have been removed, replace by else statement or no-op
if (node.elseStatement)
{
node.elseStatement->Visit(*this);
return;
}
else
return PushStatement(ShaderBuilder::NoOp());
}
if (!elseStatement)
elseStatement = CloneStatement(node.elseStatement);
PushStatement(ShaderBuilder::Branch(std::move(statements), std::move(elseStatement)));
}
void AstOptimizer::Visit(ConditionalExpression& node)
{
return AstCloner::Visit(node);
/*if (!m_shaderAst)
return ShaderAstCloner::Visit(node);
std::size_t conditionIndex = m_shaderAst->FindConditionByName(node.conditionName);
assert(conditionIndex != InvalidCondition);
if (TestBit<Nz::UInt64>(m_enabledConditions, conditionIndex))
Visit(node.truePath);
else
Visit(node.falsePath);*/
}
void AstOptimizer::Visit(ConditionalStatement& node)
{
return AstCloner::Visit(node);
/*if (!m_shaderAst)
return ShaderAstCloner::Visit(node);
std::size_t conditionIndex = m_shaderAst->FindConditionByName(node.conditionName);
assert(conditionIndex != InvalidCondition);
if (TestBit<Nz::UInt64>(m_enabledConditions, conditionIndex))
Visit(node.statement);*/
}
template<BinaryType Type>
void AstOptimizer::PropagateConstant(std::unique_ptr<ConstantExpression>&& lhs, std::unique_ptr<ConstantExpression>&& rhs)
{
ExpressionPtr optimized;
std::visit([&](auto&& arg1)
{
using T1 = std::decay_t<decltype(arg1)>;
std::visit([&](auto&& arg2)
{
using T2 = std::decay_t<decltype(arg2)>;
using PCType = PropagateConstantType<Type, T1, T2>;
if constexpr (is_complete_v<PCType>)
{
using Op = typename PCType::Op;
if constexpr (is_complete_v<Op>)
optimized = Op{}(arg1, arg2);
}
}, rhs->value);
}, lhs->value);
if (optimized)
PushExpression(std::move(optimized));
else
PushExpression(ShaderBuilder::Binary(Type, std::move(lhs), std::move(rhs)));
}
}

View File

@@ -0,0 +1,140 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Shader/Ast/AstRecursiveVisitor.hpp>
#include <Nazara/Shader/Debug.hpp>
namespace Nz::ShaderAst
{
void AstRecursiveVisitor::Visit(AccessMemberIdentifierExpression& node)
{
node.structExpr->Visit(*this);
}
void AstRecursiveVisitor::Visit(AccessMemberIndexExpression& node)
{
node.structExpr->Visit(*this);
}
void AstRecursiveVisitor::Visit(AssignExpression& node)
{
node.left->Visit(*this);
node.right->Visit(*this);
}
void AstRecursiveVisitor::Visit(BinaryExpression& node)
{
node.left->Visit(*this);
node.right->Visit(*this);
}
void AstRecursiveVisitor::Visit(CastExpression& node)
{
for (auto& expr : node.expressions)
{
if (!expr)
break;
expr->Visit(*this);
}
}
void AstRecursiveVisitor::Visit(ConditionalExpression& node)
{
node.truePath->Visit(*this);
node.falsePath->Visit(*this);
}
void AstRecursiveVisitor::Visit(ConstantExpression& /*node*/)
{
/* Nothing to do */
}
void AstRecursiveVisitor::Visit(IdentifierExpression& /*node*/)
{
/* Nothing to do */
}
void AstRecursiveVisitor::Visit(IntrinsicExpression& node)
{
for (auto& param : node.parameters)
param->Visit(*this);
}
void AstRecursiveVisitor::Visit(SwizzleExpression& node)
{
node.expression->Visit(*this);
}
void AstRecursiveVisitor::Visit(VariableExpression& node)
{
/* Nothing to do */
}
void AstRecursiveVisitor::Visit(BranchStatement& node)
{
for (auto& cond : node.condStatements)
{
cond.condition->Visit(*this);
cond.statement->Visit(*this);
}
if (node.elseStatement)
node.elseStatement->Visit(*this);
}
void AstRecursiveVisitor::Visit(ConditionalStatement& node)
{
node.statement->Visit(*this);
}
void AstRecursiveVisitor::Visit(DeclareExternalStatement& node)
{
/* Nothing to do */
}
void AstRecursiveVisitor::Visit(DeclareFunctionStatement& node)
{
for (auto& statement : node.statements)
statement->Visit(*this);
}
void AstRecursiveVisitor::Visit(DeclareStructStatement& /*node*/)
{
/* Nothing to do */
}
void AstRecursiveVisitor::Visit(DeclareVariableStatement& node)
{
if (node.initialExpression)
node.initialExpression->Visit(*this);
}
void AstRecursiveVisitor::Visit(DiscardStatement& /*node*/)
{
/* Nothing to do */
}
void AstRecursiveVisitor::Visit(ExpressionStatement& node)
{
node.expression->Visit(*this);
}
void AstRecursiveVisitor::Visit(MultiStatement& node)
{
for (auto& statement : node.statements)
statement->Visit(*this);
}
void AstRecursiveVisitor::Visit(NoOpStatement& /*node*/)
{
/* Nothing to do */
}
void AstRecursiveVisitor::Visit(ReturnStatement& node)
{
if (node.returnExpr)
node.returnExpr->Visit(*this);
}
}

View File

@@ -0,0 +1,709 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Shader/Ast/AstSerializer.hpp>
#include <Nazara/Shader/Ast/AstExpressionVisitor.hpp>
#include <Nazara/Shader/Ast/AstStatementVisitor.hpp>
#include <Nazara/Shader/Debug.hpp>
namespace Nz::ShaderAst
{
namespace
{
constexpr UInt32 s_magicNumber = 0x4E534852;
constexpr UInt32 s_currentVersion = 1;
class ShaderSerializerVisitor : public AstExpressionVisitor, public AstStatementVisitor
{
public:
ShaderSerializerVisitor(AstSerializerBase& serializer) :
m_serializer(serializer)
{
}
#define NAZARA_SHADERAST_NODE(Node) void Visit(Node& node) override \
{ \
m_serializer.Serialize(node); \
}
#include <Nazara/Shader/Ast/AstNodeList.hpp>
private:
AstSerializerBase& m_serializer;
};
}
void AstSerializerBase::Serialize(AccessMemberIdentifierExpression& node)
{
Node(node.structExpr);
Container(node.memberIdentifiers);
for (std::string& identifier : node.memberIdentifiers)
Value(identifier);
}
void AstSerializerBase::Serialize(AccessMemberIndexExpression& node)
{
Node(node.structExpr);
Container(node.memberIndices);
for (std::size_t& identifier : node.memberIndices)
SizeT(identifier);
}
void AstSerializerBase::Serialize(AssignExpression& node)
{
Enum(node.op);
Node(node.left);
Node(node.right);
}
void AstSerializerBase::Serialize(BinaryExpression& node)
{
Enum(node.op);
Node(node.left);
Node(node.right);
}
void AstSerializerBase::Serialize(CastExpression& node)
{
Type(node.targetType);
for (auto& expr : node.expressions)
Node(expr);
}
void AstSerializerBase::Serialize(ConditionalExpression& node)
{
Value(node.conditionName);
Node(node.truePath);
Node(node.falsePath);
}
void AstSerializerBase::Serialize(ConstantExpression& node)
{
UInt32 typeIndex;
if (IsWriting())
typeIndex = UInt32(node.value.index());
Value(typeIndex);
// Waiting for template lambda in C++20
auto SerializeValue = [&](auto dummyType)
{
using T = std::decay_t<decltype(dummyType)>;
auto& value = (IsWriting()) ? std::get<T>(node.value) : node.value.emplace<T>();
Value(value);
};
static_assert(std::variant_size_v<decltype(node.value)> == 10);
switch (typeIndex)
{
case 0: SerializeValue(bool()); break;
case 1: SerializeValue(float()); break;
case 2: SerializeValue(Int32()); break;
case 3: SerializeValue(UInt32()); break;
case 4: SerializeValue(Vector2f()); break;
case 5: SerializeValue(Vector3f()); break;
case 6: SerializeValue(Vector4f()); break;
case 7: SerializeValue(Vector2i32()); break;
case 8: SerializeValue(Vector3i32()); break;
case 9: SerializeValue(Vector4i32()); break;
default: throw std::runtime_error("unexpected data type");
}
}
void AstSerializerBase::Serialize(DeclareVariableStatement& node)
{
OptVal(node.varIndex);
Value(node.varName);
Type(node.varType);
Node(node.initialExpression);
}
void AstSerializerBase::Serialize(IdentifierExpression& node)
{
Value(node.identifier);
}
void AstSerializerBase::Serialize(IntrinsicExpression& node)
{
Enum(node.intrinsic);
Container(node.parameters);
for (auto& param : node.parameters)
Node(param);
}
void AstSerializerBase::Serialize(SwizzleExpression& node)
{
SizeT(node.componentCount);
Node(node.expression);
for (std::size_t i = 0; i < node.componentCount; ++i)
Enum(node.components[i]);
}
void AstSerializerBase::Serialize(VariableExpression& node)
{
SizeT(node.variableId);
}
void AstSerializerBase::Serialize(BranchStatement& node)
{
Container(node.condStatements);
for (auto& condStatement : node.condStatements)
{
Node(condStatement.condition);
Node(condStatement.statement);
}
Node(node.elseStatement);
}
void AstSerializerBase::Serialize(ConditionalStatement& node)
{
Value(node.conditionName);
Node(node.statement);
}
void AstSerializerBase::Serialize(DeclareExternalStatement& node)
{
OptVal(node.varIndex);
Container(node.externalVars);
for (auto& extVar : node.externalVars)
{
Value(extVar.name);
Type(extVar.type);
OptVal(extVar.bindingIndex);
}
}
void AstSerializerBase::Serialize(DeclareFunctionStatement& node)
{
Value(node.name);
Type(node.returnType);
OptEnum(node.entryStage);
OptVal(node.funcIndex);
OptVal(node.varIndex);
Container(node.parameters);
for (auto& parameter : node.parameters)
{
Value(parameter.name);
Type(parameter.type);
}
Container(node.statements);
for (auto& statement : node.statements)
Node(statement);
}
void AstSerializerBase::Serialize(DeclareStructStatement& node)
{
OptVal(node.structIndex);
Value(node.description.name);
OptEnum(node.description.layout);
Container(node.description.members);
for (auto& member : node.description.members)
{
Value(member.name);
Type(member.type);
OptEnum(member.builtin);
OptVal(member.locationIndex);
}
}
void AstSerializerBase::Serialize(DiscardStatement& /*node*/)
{
/* Nothing to do */
}
void AstSerializerBase::Serialize(ExpressionStatement& node)
{
Node(node.expression);
}
void AstSerializerBase::Serialize(MultiStatement& node)
{
Container(node.statements);
for (auto& statement : node.statements)
Node(statement);
}
void AstSerializerBase::Serialize(NoOpStatement& /*node*/)
{
/* Nothing to do */
}
void AstSerializerBase::Serialize(ReturnStatement& node)
{
Node(node.returnExpr);
}
void ShaderAstSerializer::Serialize(StatementPtr& shader)
{
m_stream << s_magicNumber << s_currentVersion;
Node(shader);
m_stream.FlushBits();
}
bool ShaderAstSerializer::IsWriting() const
{
return true;
}
void ShaderAstSerializer::Node(ExpressionPtr& node)
{
NodeType nodeType = (node) ? node->GetType() : NodeType::None;
m_stream << static_cast<Int32>(nodeType);
if (node)
{
ShaderSerializerVisitor visitor(*this);
node->Visit(visitor);
}
}
void ShaderAstSerializer::Node(StatementPtr& node)
{
NodeType nodeType = (node) ? node->GetType() : NodeType::None;
m_stream << static_cast<Int32>(nodeType);
if (node)
{
ShaderSerializerVisitor visitor(*this);
node->Visit(visitor);
}
}
void ShaderAstSerializer::Type(ExpressionType& type)
{
std::visit([&](auto&& arg)
{
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, NoType>)
m_stream << UInt8(0);
else if constexpr (std::is_same_v<T, PrimitiveType>)
{
m_stream << UInt8(1);
m_stream << UInt32(arg);
}
else if constexpr (std::is_same_v<T, IdentifierType>)
{
m_stream << UInt8(2);
m_stream << arg.name;
}
else if constexpr (std::is_same_v<T, MatrixType>)
{
m_stream << UInt8(3);
m_stream << UInt32(arg.columnCount);
m_stream << UInt32(arg.rowCount);
m_stream << UInt32(arg.type);
}
else if constexpr (std::is_same_v<T, SamplerType>)
{
m_stream << UInt8(4);
m_stream << UInt32(arg.dim);
m_stream << UInt32(arg.sampledType);
}
else if constexpr (std::is_same_v<T, StructType>)
{
m_stream << UInt8(5);
m_stream << UInt32(arg.structIndex);
}
else if constexpr (std::is_same_v<T, UniformType>)
{
m_stream << UInt8(6);
m_stream << std::get<IdentifierType>(arg.containedType).name;
}
else if constexpr (std::is_same_v<T, VectorType>)
{
m_stream << UInt8(7);
m_stream << UInt32(arg.componentCount);
m_stream << UInt32(arg.type);
}
else
static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor");
}, type);
}
void ShaderAstSerializer::Value(bool& val)
{
m_stream << val;
}
void ShaderAstSerializer::Value(float& val)
{
m_stream << val;
}
void ShaderAstSerializer::Value(std::string& val)
{
m_stream << val;
}
void ShaderAstSerializer::Value(Int32& val)
{
m_stream << val;
}
void ShaderAstSerializer::Value(Vector2f& val)
{
m_stream << val;
}
void ShaderAstSerializer::Value(Vector3f& val)
{
m_stream << val;
}
void ShaderAstSerializer::Value(Vector4f& val)
{
m_stream << val;
}
void ShaderAstSerializer::Value(Vector2i32& val)
{
m_stream << val;
}
void ShaderAstSerializer::Value(Vector3i32& val)
{
m_stream << val;
}
void ShaderAstSerializer::Value(Vector4i32& val)
{
m_stream << val;
}
void ShaderAstSerializer::Value(UInt8& val)
{
m_stream << val;
}
void ShaderAstSerializer::Value(UInt16& val)
{
m_stream << val;
}
void ShaderAstSerializer::Value(UInt32& val)
{
m_stream << val;
}
void ShaderAstSerializer::Value(UInt64& val)
{
m_stream << val;
}
StatementPtr ShaderAstUnserializer::Unserialize()
{
UInt32 magicNumber;
UInt32 version;
m_stream >> magicNumber;
if (magicNumber != s_magicNumber)
throw std::runtime_error("invalid shader file");
m_stream >> version;
if (version > s_currentVersion)
throw std::runtime_error("unsupported version");
StatementPtr node;
Node(node);
if (!node)
throw std::runtime_error("functions can only have statements");
return node;
}
bool ShaderAstUnserializer::IsWriting() const
{
return false;
}
void ShaderAstUnserializer::Node(ExpressionPtr& node)
{
Int32 nodeTypeInt;
m_stream >> nodeTypeInt;
if (nodeTypeInt < static_cast<Int32>(NodeType::None) || nodeTypeInt > static_cast<Int32>(NodeType::Max))
throw std::runtime_error("invalid node type");
NodeType nodeType = static_cast<NodeType>(nodeTypeInt);
switch (nodeType)
{
case NodeType::None: break;
#define NAZARA_SHADERAST_EXPRESSION(Node) case NodeType:: Node : node = std::make_unique<Node>(); break;
#include <Nazara/Shader/Ast/AstNodeList.hpp>
default: throw std::runtime_error("unexpected node type");
}
if (node)
{
ShaderSerializerVisitor visitor(*this);
node->Visit(visitor);
}
}
void ShaderAstUnserializer::Node(StatementPtr& node)
{
Int32 nodeTypeInt;
m_stream >> nodeTypeInt;
if (nodeTypeInt < static_cast<Int32>(NodeType::None) || nodeTypeInt > static_cast<Int32>(NodeType::Max))
throw std::runtime_error("invalid node type");
NodeType nodeType = static_cast<NodeType>(nodeTypeInt);
switch (nodeType)
{
case NodeType::None: break;
#define NAZARA_SHADERAST_STATEMENT(Node) case NodeType:: Node : node = std::make_unique<Node>(); break;
#include <Nazara/Shader/Ast/AstNodeList.hpp>
default: throw std::runtime_error("unexpected node type");
}
if (node)
{
ShaderSerializerVisitor visitor(*this);
node->Visit(visitor);
}
}
void ShaderAstUnserializer::Type(ExpressionType& type)
{
UInt8 typeIndex;
Value(typeIndex);
switch (typeIndex)
{
/*
if constexpr (std::is_same_v<T, NoType>)
m_stream << UInt8(0);
else if constexpr (std::is_same_v<T, PrimitiveType>)
{
m_stream << UInt8(1);
m_stream << UInt32(arg);
}
else if constexpr (std::is_same_v<T, IdentifierType>)
{
m_stream << UInt8(2);
m_stream << arg.name;
}
else if constexpr (std::is_same_v<T, MatrixType>)
{
m_stream << UInt8(3);
m_stream << UInt32(arg.columnCount);
m_stream << UInt32(arg.rowCount);
m_stream << UInt32(arg.type);
}
else if constexpr (std::is_same_v<T, SamplerType>)
{
m_stream << UInt8(4);
m_stream << UInt32(arg.dim);
m_stream << UInt32(arg.sampledType);
}
else if constexpr (std::is_same_v<T, VectorType>)
{
m_stream << UInt8(5);
m_stream << UInt32(arg.componentCount);
m_stream << UInt32(arg.type);
}
*/
case 0: //< NoType
type = NoType{};
break;
case 1: //< PrimitiveType
{
PrimitiveType primitiveType;
Enum(primitiveType);
type = primitiveType;
break;
}
case 2: //< Identifier
{
std::string identifier;
Value(identifier);
type = IdentifierType{ std::move(identifier) };
break;
}
case 3: //< MatrixType
{
UInt32 columnCount, rowCount;
PrimitiveType primitiveType;
Value(columnCount);
Value(rowCount);
Enum(primitiveType);
type = MatrixType {
columnCount,
rowCount,
primitiveType
};
break;
}
case 4: //< SamplerType
{
ImageType dim;
PrimitiveType sampledType;
Enum(dim);
Enum(sampledType);
type = SamplerType {
dim,
sampledType
};
break;
}
case 5: //< StructType
{
UInt32 structIndex;
Value(structIndex);
type = StructType{
structIndex
};
break;
}
case 6: //< UniformType
{
std::string containedType;
Value(containedType);
type = UniformType {
IdentifierType {
containedType
}
};
break;
}
case 7: //< VectorType
{
UInt32 componentCount;
PrimitiveType componentType;
Value(componentCount);
Enum(componentType);
type = VectorType{
componentCount,
componentType
};
break;
}
default:
break;
}
}
void ShaderAstUnserializer::Value(bool& val)
{
m_stream >> val;
}
void ShaderAstUnserializer::Value(float& val)
{
m_stream >> val;
}
void ShaderAstUnserializer::Value(std::string& val)
{
m_stream >> val;
}
void ShaderAstUnserializer::Value(Int32& val)
{
m_stream >> val;
}
void ShaderAstUnserializer::Value(Vector2f& val)
{
m_stream >> val;
}
void ShaderAstUnserializer::Value(Vector3f& val)
{
m_stream >> val;
}
void ShaderAstUnserializer::Value(Vector4f& val)
{
m_stream >> val;
}
void ShaderAstUnserializer::Value(Vector2i32& val)
{
m_stream >> val;
}
void ShaderAstUnserializer::Value(Vector3i32& val)
{
m_stream >> val;
}
void ShaderAstUnserializer::Value(Vector4i32& val)
{
m_stream >> val;
}
void ShaderAstUnserializer::Value(UInt8& val)
{
m_stream >> val;
}
void ShaderAstUnserializer::Value(UInt16& val)
{
m_stream >> val;
}
void ShaderAstUnserializer::Value(UInt32& val)
{
m_stream >> val;
}
void ShaderAstUnserializer::Value(UInt64& val)
{
m_stream >> val;
}
ByteArray SerializeShader(StatementPtr& shader)
{
ByteArray byteArray;
ByteStream stream(&byteArray, OpenModeFlags(OpenMode_WriteOnly));
ShaderAstSerializer serializer(stream);
serializer.Serialize(shader);
return byteArray;
}
StatementPtr UnserializeShader(ByteStream& stream)
{
ShaderAstUnserializer unserializer(stream);
return unserializer.Unserialize();
}
}

View File

@@ -0,0 +1,11 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Shader/Ast/AstStatementVisitor.hpp>
#include <Nazara/Shader/Debug.hpp>
namespace Nz::ShaderAst
{
AstStatementVisitor::~AstStatementVisitor() = default;
}

View File

@@ -0,0 +1,15 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Shader/Ast/AstStatementVisitorExcept.hpp>
#include <Nazara/Shader/Debug.hpp>
namespace Nz::ShaderAst
{
#define NAZARA_SHADERAST_STATEMENT(Node) void StatementVisitorExcept::Visit(ShaderAst::Node& /*node*/) \
{ \
throw std::runtime_error("unexpected " #Node " node"); \
}
#include <Nazara/Shader/Ast/AstNodeList.hpp>
}

View File

@@ -0,0 +1,79 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Shader/Ast/AstUtils.hpp>
#include <Nazara/Shader/Debug.hpp>
namespace Nz::ShaderAst
{
ExpressionCategory ShaderAstValueCategory::GetExpressionCategory(Expression& expression)
{
expression.Visit(*this);
return m_expressionCategory;
}
void ShaderAstValueCategory::Visit(AccessMemberIdentifierExpression& node)
{
node.structExpr->Visit(*this);
}
void ShaderAstValueCategory::Visit(AccessMemberIndexExpression& node)
{
node.structExpr->Visit(*this);
}
void ShaderAstValueCategory::Visit(AssignExpression& /*node*/)
{
m_expressionCategory = ExpressionCategory::RValue;
}
void ShaderAstValueCategory::Visit(BinaryExpression& /*node*/)
{
m_expressionCategory = ExpressionCategory::RValue;
}
void ShaderAstValueCategory::Visit(CastExpression& /*node*/)
{
m_expressionCategory = ExpressionCategory::RValue;
}
void ShaderAstValueCategory::Visit(ConditionalExpression& node)
{
node.truePath->Visit(*this);
ExpressionCategory trueExprCategory = m_expressionCategory;
node.falsePath->Visit(*this);
ExpressionCategory falseExprCategory = m_expressionCategory;
if (trueExprCategory == ExpressionCategory::RValue || falseExprCategory == ExpressionCategory::RValue)
m_expressionCategory = ExpressionCategory::RValue;
else
m_expressionCategory = ExpressionCategory::LValue;
}
void ShaderAstValueCategory::Visit(ConstantExpression& /*node*/)
{
m_expressionCategory = ExpressionCategory::RValue;
}
void ShaderAstValueCategory::Visit(IdentifierExpression& /*node*/)
{
m_expressionCategory = ExpressionCategory::LValue;
}
void ShaderAstValueCategory::Visit(IntrinsicExpression& /*node*/)
{
m_expressionCategory = ExpressionCategory::RValue;
}
void ShaderAstValueCategory::Visit(SwizzleExpression& node)
{
node.expression->Visit(*this);
}
void ShaderAstValueCategory::Visit(VariableExpression& node)
{
m_expressionCategory = ExpressionCategory::LValue;
}
}

View File

@@ -0,0 +1,32 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Shader/Ast/Nodes.hpp>
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Shader/Ast/AstExpressionVisitor.hpp>
#include <Nazara/Shader/Ast/AstStatementVisitor.hpp>
#include <Nazara/Shader/Debug.hpp>
namespace Nz::ShaderAst
{
Node::~Node() = default;
#define NAZARA_SHADERAST_NODE(Node) NodeType Node::GetType() const \
{ \
return NodeType:: Node; \
}
#include <Nazara/Shader/Ast/AstNodeList.hpp>
#define NAZARA_SHADERAST_EXPRESSION(Node) void Node::Visit(AstExpressionVisitor& visitor) \
{\
visitor.Visit(*this); \
}
#define NAZARA_SHADERAST_STATEMENT(Node) void Node::Visit(AstStatementVisitor& visitor) \
{\
visitor.Visit(*this); \
}
#include <Nazara/Shader/Ast/AstNodeList.hpp>
}

View File

@@ -5,7 +5,7 @@
#include <Nazara/Shader/Ast/SanitizeVisitor.hpp>
#include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Core/StackArray.hpp>
#include <Nazara/Shader/ShaderAstUtils.hpp>
#include <Nazara/Shader/Ast/AstUtils.hpp>
#include <stdexcept>
#include <unordered_set>
#include <Nazara/Shader/Debug.hpp>