Shader: Cleanup and rename AST files
This commit is contained in:
321
src/Nazara/Shader/Ast/AstCloner.cpp
Normal file
321
src/Nazara/Shader/Ast/AstCloner.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
11
src/Nazara/Shader/Ast/AstExpressionVisitor.cpp
Normal file
11
src/Nazara/Shader/Ast/AstExpressionVisitor.cpp
Normal 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;
|
||||
}
|
||||
15
src/Nazara/Shader/Ast/AstExpressionVisitorExcept.cpp
Normal file
15
src/Nazara/Shader/Ast/AstExpressionVisitorExcept.cpp
Normal 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>
|
||||
}
|
||||
562
src/Nazara/Shader/Ast/AstOptimizer.cpp
Normal file
562
src/Nazara/Shader/Ast/AstOptimizer.cpp
Normal 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)));
|
||||
}
|
||||
}
|
||||
140
src/Nazara/Shader/Ast/AstRecursiveVisitor.cpp
Normal file
140
src/Nazara/Shader/Ast/AstRecursiveVisitor.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
709
src/Nazara/Shader/Ast/AstSerializer.cpp
Normal file
709
src/Nazara/Shader/Ast/AstSerializer.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
|
||||
11
src/Nazara/Shader/Ast/AstStatementVisitor.cpp
Normal file
11
src/Nazara/Shader/Ast/AstStatementVisitor.cpp
Normal 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;
|
||||
}
|
||||
15
src/Nazara/Shader/Ast/AstStatementVisitorExcept.cpp
Normal file
15
src/Nazara/Shader/Ast/AstStatementVisitorExcept.cpp
Normal 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>
|
||||
}
|
||||
79
src/Nazara/Shader/Ast/AstUtils.cpp
Normal file
79
src/Nazara/Shader/Ast/AstUtils.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
32
src/Nazara/Shader/Ast/Nodes.cpp
Normal file
32
src/Nazara/Shader/Ast/Nodes.cpp
Normal 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>
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user