Add ShaderAstCloner
This commit is contained in:
parent
74fb01af28
commit
d6d452d43d
|
|
@ -53,6 +53,7 @@
|
|||
#include <Nazara/Renderer/RenderWindowImpl.hpp>
|
||||
#include <Nazara/Renderer/RenderWindowParameters.hpp>
|
||||
#include <Nazara/Renderer/ShaderAst.hpp>
|
||||
#include <Nazara/Renderer/ShaderAstCloner.hpp>
|
||||
#include <Nazara/Renderer/ShaderAstRecursiveVisitor.hpp>
|
||||
#include <Nazara/Renderer/ShaderAstSerializer.hpp>
|
||||
#include <Nazara/Renderer/ShaderAstValidator.hpp>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
// Copyright (C) 2015 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Renderer module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SHADERASTCLONER_HPP
|
||||
#define NAZARA_SHADERASTCLONER_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Renderer/Config.hpp>
|
||||
#include <Nazara/Renderer/ShaderAstVisitor.hpp>
|
||||
#include <Nazara/Renderer/ShaderVarVisitor.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class NAZARA_RENDERER_API ShaderAstCloner : public ShaderAstVisitor, public ShaderVarVisitor
|
||||
{
|
||||
public:
|
||||
ShaderAstCloner() = default;
|
||||
ShaderAstCloner(const ShaderAstCloner&) = default;
|
||||
ShaderAstCloner(ShaderAstCloner&&) = default;
|
||||
~ShaderAstCloner() = default;
|
||||
|
||||
ShaderNodes::StatementPtr Clone(const ShaderNodes::StatementPtr& statement);
|
||||
|
||||
ShaderAstCloner& operator=(const ShaderAstCloner&) = default;
|
||||
ShaderAstCloner& operator=(ShaderAstCloner&&) = default;
|
||||
|
||||
private:
|
||||
void Visit(const ShaderNodes::ExpressionPtr& expr);
|
||||
void Visit(const ShaderNodes::StatementPtr& statement);
|
||||
|
||||
void Visit(const ShaderNodes::AccessMember& node) override;
|
||||
void Visit(const ShaderNodes::AssignOp& node) override;
|
||||
void Visit(const ShaderNodes::BinaryOp& node) override;
|
||||
void Visit(const ShaderNodes::Branch& node) override;
|
||||
void Visit(const ShaderNodes::Cast& node) override;
|
||||
void Visit(const ShaderNodes::Constant& node) override;
|
||||
void Visit(const ShaderNodes::DeclareVariable& node) override;
|
||||
void Visit(const ShaderNodes::ExpressionStatement& node) override;
|
||||
void Visit(const ShaderNodes::Identifier& node) override;
|
||||
void Visit(const ShaderNodes::IntrinsicCall& node) override;
|
||||
void Visit(const ShaderNodes::Sample2D& node) override;
|
||||
void Visit(const ShaderNodes::StatementBlock& node) override;
|
||||
void Visit(const ShaderNodes::SwizzleOp& node) override;
|
||||
|
||||
using ShaderVarVisitor::Visit;
|
||||
void Visit(const ShaderNodes::BuiltinVariable& var) override;
|
||||
void Visit(const ShaderNodes::InputVariable& var) override;
|
||||
void Visit(const ShaderNodes::LocalVariable& var) override;
|
||||
void Visit(const ShaderNodes::OutputVariable& var) override;
|
||||
void Visit(const ShaderNodes::ParameterVariable& var) override;
|
||||
void Visit(const ShaderNodes::UniformVariable& var) override;
|
||||
|
||||
void PushExpression(ShaderNodes::ExpressionPtr expression);
|
||||
void PushStatement(ShaderNodes::StatementPtr statement);
|
||||
void PushVariable(ShaderNodes::VariablePtr variable);
|
||||
|
||||
ShaderNodes::ExpressionPtr PopExpression();
|
||||
ShaderNodes::StatementPtr PopStatement();
|
||||
ShaderNodes::VariablePtr PopVariable();
|
||||
|
||||
std::vector<ShaderNodes::ExpressionPtr> m_expressionStack;
|
||||
std::vector<ShaderNodes::StatementPtr> m_statementStack;
|
||||
std::vector<ShaderNodes::VariablePtr> m_variableStack;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Renderer/ShaderAstCloner.inl>
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (C) 2020 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Renderer module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/ShaderAstCloner.hpp>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
}
|
||||
|
||||
#include <Nazara/Renderer/DebugOff.hpp>
|
||||
|
|
@ -106,6 +106,7 @@ namespace Nz
|
|||
|
||||
std::vector<StatementPtr> statements;
|
||||
|
||||
static inline std::shared_ptr<StatementBlock> Build(std::vector<StatementPtr> statements);
|
||||
template<typename... Args> static std::shared_ptr<StatementBlock> Build(Args&&... args);
|
||||
};
|
||||
|
||||
|
|
@ -115,10 +116,10 @@ namespace Nz
|
|||
|
||||
void Visit(ShaderAstVisitor& visitor) override;
|
||||
|
||||
LocalVariablePtr variable;
|
||||
ExpressionPtr expression;
|
||||
VariablePtr variable;
|
||||
|
||||
static inline std::shared_ptr<DeclareVariable> Build(LocalVariablePtr variable, ExpressionPtr expression = nullptr);
|
||||
static inline std::shared_ptr<DeclareVariable> Build(VariablePtr variable, ExpressionPtr expression = nullptr);
|
||||
};
|
||||
|
||||
struct NAZARA_RENDERER_API Identifier : public Expression
|
||||
|
|
@ -196,7 +197,8 @@ namespace Nz
|
|||
StatementPtr statement;
|
||||
};
|
||||
|
||||
inline std::shared_ptr<Branch> Build(ExpressionPtr condition, StatementPtr trueStatement, StatementPtr falseStatement = nullptr);
|
||||
static inline std::shared_ptr<Branch> Build(ExpressionPtr condition, StatementPtr trueStatement, StatementPtr falseStatement = nullptr);
|
||||
static inline std::shared_ptr<Branch> Build(std::vector<ConditionalStatement> statements, StatementPtr elseStatement = nullptr);
|
||||
};
|
||||
|
||||
struct NAZARA_RENDERER_API Cast : public Expression
|
||||
|
|
@ -246,6 +248,7 @@ namespace Nz
|
|||
ExpressionPtr expression;
|
||||
|
||||
static inline std::shared_ptr<SwizzleOp> Build(ExpressionPtr expressionPtr, std::initializer_list<SwizzleComponent> swizzleComponents);
|
||||
static inline std::shared_ptr<SwizzleOp> Build(ExpressionPtr expressionPtr, const SwizzleComponent* components, std::size_t componentCount);
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -107,6 +107,14 @@ namespace Nz::ShaderNodes
|
|||
{
|
||||
}
|
||||
|
||||
inline std::shared_ptr<StatementBlock> StatementBlock::Build(std::vector<StatementPtr> statements)
|
||||
{
|
||||
auto node = std::make_shared<StatementBlock>();
|
||||
node->statements = std::move(statements);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
std::shared_ptr<StatementBlock> StatementBlock::Build(Args&&... args)
|
||||
{
|
||||
|
|
@ -122,7 +130,7 @@ namespace Nz::ShaderNodes
|
|||
{
|
||||
}
|
||||
|
||||
inline std::shared_ptr<DeclareVariable> DeclareVariable::Build(LocalVariablePtr variable, ExpressionPtr expression)
|
||||
inline std::shared_ptr<DeclareVariable> DeclareVariable::Build(VariablePtr variable, ExpressionPtr expression)
|
||||
{
|
||||
auto node = std::make_shared<DeclareVariable>();
|
||||
node->expression = std::move(expression);
|
||||
|
|
@ -208,6 +216,15 @@ namespace Nz::ShaderNodes
|
|||
return node;
|
||||
}
|
||||
|
||||
inline std::shared_ptr<Branch> Branch::Build(std::vector<ConditionalStatement> statements, StatementPtr elseStatement)
|
||||
{
|
||||
auto node = std::make_shared<Branch>();
|
||||
node->condStatements = std::move(statements);
|
||||
node->elseStatement = std::move(elseStatement);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
inline Cast::Cast() :
|
||||
Expression(NodeType::Cast)
|
||||
|
|
@ -265,6 +282,20 @@ namespace Nz::ShaderNodes
|
|||
return node;
|
||||
}
|
||||
|
||||
inline std::shared_ptr<SwizzleOp> SwizzleOp::Build(ExpressionPtr expressionPtr, const SwizzleComponent* components, std::size_t componentCount)
|
||||
{
|
||||
auto node = std::make_shared<SwizzleOp>();
|
||||
|
||||
assert(componentCount < node->components.size());
|
||||
|
||||
node->componentCount = componentCount;
|
||||
node->expression = std::move(expressionPtr);
|
||||
|
||||
std::copy(components, components + componentCount, node->components.begin());
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
inline Sample2D::Sample2D() :
|
||||
Expression(NodeType::Sample2D)
|
||||
|
|
|
|||
|
|
@ -448,9 +448,13 @@ namespace Nz
|
|||
|
||||
void GlslWriter::Visit(const ShaderNodes::DeclareVariable& node)
|
||||
{
|
||||
Append(node.variable->type);
|
||||
assert(node.variable->GetType() == ShaderNodes::VariableType::LocalVariable);
|
||||
|
||||
const auto& localVar = static_cast<const ShaderNodes::LocalVariable&>(*node.variable);
|
||||
|
||||
Append(localVar.type);
|
||||
Append(" ");
|
||||
Append(node.variable->name);
|
||||
Append(localVar.name);
|
||||
if (node.expression)
|
||||
{
|
||||
Append(" = ");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,246 @@
|
|||
// Copyright (C) 2015 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Renderer module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/ShaderAstCloner.hpp>
|
||||
#include <stdexcept>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
ShaderNodes::StatementPtr ShaderAstCloner::Clone(const ShaderNodes::StatementPtr& statement)
|
||||
{
|
||||
ShaderAstVisitor::Visit(statement);
|
||||
|
||||
if (!m_expressionStack.empty() || !m_variableStack.empty() || m_statementStack.size() != 1)
|
||||
throw std::runtime_error("An error occured during clone");
|
||||
|
||||
return PopStatement();
|
||||
}
|
||||
|
||||
void ShaderAstCloner::Visit(const ShaderNodes::ExpressionPtr& expr)
|
||||
{
|
||||
if (expr)
|
||||
ShaderAstVisitor::Visit(expr);
|
||||
else
|
||||
PushExpression(nullptr);
|
||||
}
|
||||
|
||||
void ShaderAstCloner::Visit(const ShaderNodes::StatementPtr& statement)
|
||||
{
|
||||
if (statement)
|
||||
ShaderAstVisitor::Visit(statement);
|
||||
else
|
||||
PushStatement(nullptr);
|
||||
}
|
||||
|
||||
void ShaderAstCloner::Visit(const ShaderNodes::AccessMember& node)
|
||||
{
|
||||
Visit(node.structExpr);
|
||||
|
||||
PushExpression(ShaderNodes::AccessMember::Build(PopExpression(), node.memberIndex, node.exprType));
|
||||
}
|
||||
|
||||
void ShaderAstCloner::Visit(const ShaderNodes::AssignOp& node)
|
||||
{
|
||||
Visit(node.left);
|
||||
Visit(node.right);
|
||||
|
||||
auto right = PopExpression();
|
||||
auto left = PopExpression();
|
||||
|
||||
PushExpression(ShaderNodes::AssignOp::Build(node.op, std::move(left), std::move(right)));
|
||||
}
|
||||
|
||||
void ShaderAstCloner::Visit(const ShaderNodes::BinaryOp& node)
|
||||
{
|
||||
Visit(node.left);
|
||||
Visit(node.right);
|
||||
|
||||
auto right = PopExpression();
|
||||
auto left = PopExpression();
|
||||
|
||||
PushExpression(ShaderNodes::BinaryOp::Build(node.op, std::move(left), std::move(right)));
|
||||
}
|
||||
|
||||
void ShaderAstCloner::Visit(const ShaderNodes::Branch& node)
|
||||
{
|
||||
for (auto& cond : node.condStatements)
|
||||
{
|
||||
Visit(cond.condition);
|
||||
Visit(cond.statement);
|
||||
}
|
||||
|
||||
Visit(node.elseStatement);
|
||||
|
||||
auto elseStatement = PopStatement();
|
||||
|
||||
std::vector<ShaderNodes::Branch::ConditionalStatement> condStatements(node.condStatements.size());
|
||||
for (std::size_t i = 0; i < condStatements.size(); ++i)
|
||||
{
|
||||
auto& condStatement = condStatements[condStatements.size() - i - 1];
|
||||
condStatement.condition = PopExpression();
|
||||
condStatement.statement = PopStatement();
|
||||
}
|
||||
|
||||
PushStatement(ShaderNodes::Branch::Build(std::move(condStatements), std::move(elseStatement)));
|
||||
}
|
||||
|
||||
void ShaderAstCloner::Visit(const ShaderNodes::Cast& node)
|
||||
{
|
||||
std::size_t expressionCount = 0;
|
||||
std::array<ShaderNodes::ExpressionPtr, 4> expressions;
|
||||
for (const auto& expr : node.expressions)
|
||||
{
|
||||
Visit(expr);
|
||||
expressionCount++;
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < expressionCount; ++i)
|
||||
expressions[expressionCount - i - 1] = PopExpression();
|
||||
|
||||
PushExpression(ShaderNodes::Cast::Build(node.exprType, expressions.data(), expressionCount));
|
||||
}
|
||||
|
||||
void ShaderAstCloner::Visit(const ShaderNodes::Constant& node)
|
||||
{
|
||||
PushExpression(ShaderNodes::Constant::Build(node.value));
|
||||
}
|
||||
|
||||
void ShaderAstCloner::Visit(const ShaderNodes::DeclareVariable& node)
|
||||
{
|
||||
Visit(node.expression);
|
||||
Visit(node.variable);
|
||||
|
||||
PushStatement(ShaderNodes::DeclareVariable::Build(PopVariable(), PopExpression()));
|
||||
}
|
||||
|
||||
void ShaderAstCloner::Visit(const ShaderNodes::ExpressionStatement& node)
|
||||
{
|
||||
Visit(node.expression);
|
||||
|
||||
PushStatement(ShaderNodes::ExpressionStatement::Build(PopExpression()));
|
||||
}
|
||||
|
||||
void ShaderAstCloner::Visit(const ShaderNodes::Identifier& node)
|
||||
{
|
||||
Visit(node.var);
|
||||
|
||||
PushExpression(ShaderNodes::Identifier::Build(PopVariable()));
|
||||
}
|
||||
|
||||
void ShaderAstCloner::Visit(const ShaderNodes::IntrinsicCall& node)
|
||||
{
|
||||
for (auto& parameter : node.parameters)
|
||||
Visit(parameter);
|
||||
|
||||
std::vector<ShaderNodes::ExpressionPtr> parameters(node.parameters.size());
|
||||
for (std::size_t i = 0; i < parameters.size(); ++i)
|
||||
parameters[parameters.size() - i - 1] = PopExpression();
|
||||
|
||||
PushExpression(ShaderNodes::IntrinsicCall::Build(node.intrinsic, std::move(parameters)));
|
||||
}
|
||||
|
||||
void ShaderAstCloner::Visit(const ShaderNodes::Sample2D& node)
|
||||
{
|
||||
Visit(node.coordinates);
|
||||
Visit(node.sampler);
|
||||
|
||||
auto sampler = PopExpression();
|
||||
auto coordinates = PopExpression();
|
||||
|
||||
PushExpression(ShaderNodes::Sample2D::Build(std::move(sampler), std::move(coordinates)));
|
||||
}
|
||||
|
||||
void ShaderAstCloner::Visit(const ShaderNodes::StatementBlock& node)
|
||||
{
|
||||
for (auto& statement : node.statements)
|
||||
Visit(statement);
|
||||
|
||||
std::vector<ShaderNodes::StatementPtr> statements(node.statements.size());
|
||||
for (std::size_t i = 0; i < statements.size(); ++i)
|
||||
statements[statements.size() - i - 1] = PopStatement();
|
||||
|
||||
PushStatement(ShaderNodes::StatementBlock::Build(std::move(statements)));
|
||||
}
|
||||
|
||||
void ShaderAstCloner::Visit(const ShaderNodes::SwizzleOp& node)
|
||||
{
|
||||
PushExpression(ShaderNodes::SwizzleOp::Build(PopExpression(), node.components.data(), node.componentCount));
|
||||
}
|
||||
|
||||
void ShaderAstCloner::Visit(const ShaderNodes::BuiltinVariable& var)
|
||||
{
|
||||
PushVariable(ShaderNodes::BuiltinVariable::Build(var.entry, var.type));
|
||||
}
|
||||
|
||||
void ShaderAstCloner::Visit(const ShaderNodes::InputVariable& var)
|
||||
{
|
||||
PushVariable(ShaderNodes::InputVariable::Build(var.name, var.type));
|
||||
}
|
||||
|
||||
void ShaderAstCloner::Visit(const ShaderNodes::LocalVariable& var)
|
||||
{
|
||||
PushVariable(ShaderNodes::LocalVariable::Build(var.name, var.type));
|
||||
}
|
||||
|
||||
void ShaderAstCloner::Visit(const ShaderNodes::OutputVariable& var)
|
||||
{
|
||||
PushVariable(ShaderNodes::OutputVariable::Build(var.name, var.type));
|
||||
}
|
||||
|
||||
void ShaderAstCloner::Visit(const ShaderNodes::ParameterVariable& var)
|
||||
{
|
||||
PushVariable(ShaderNodes::ParameterVariable::Build(var.name, var.type));
|
||||
}
|
||||
|
||||
void ShaderAstCloner::Visit(const ShaderNodes::UniformVariable& var)
|
||||
{
|
||||
PushVariable(ShaderNodes::UniformVariable::Build(var.name, var.type));
|
||||
}
|
||||
|
||||
void ShaderAstCloner::PushExpression(ShaderNodes::ExpressionPtr expression)
|
||||
{
|
||||
m_expressionStack.emplace_back(std::move(expression));
|
||||
}
|
||||
|
||||
void ShaderAstCloner::PushStatement(ShaderNodes::StatementPtr statement)
|
||||
{
|
||||
m_statementStack.emplace_back(std::move(statement));
|
||||
}
|
||||
|
||||
void ShaderAstCloner::PushVariable(ShaderNodes::VariablePtr variable)
|
||||
{
|
||||
m_variableStack.emplace_back(std::move(variable));
|
||||
}
|
||||
|
||||
ShaderNodes::ExpressionPtr ShaderAstCloner::PopExpression()
|
||||
{
|
||||
assert(!m_expressionStack.empty());
|
||||
|
||||
ShaderNodes::ExpressionPtr expr = std::move(m_expressionStack.back());
|
||||
m_expressionStack.pop_back();
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
ShaderNodes::StatementPtr ShaderAstCloner::PopStatement()
|
||||
{
|
||||
assert(!m_statementStack.empty());
|
||||
|
||||
ShaderNodes::StatementPtr expr = std::move(m_statementStack.back());
|
||||
m_statementStack.pop_back();
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
ShaderNodes::VariablePtr ShaderAstCloner::PopVariable()
|
||||
{
|
||||
assert(!m_variableStack.empty());
|
||||
|
||||
ShaderNodes::VariablePtr var = std::move(m_variableStack.back());
|
||||
m_variableStack.pop_back();
|
||||
|
||||
return var;
|
||||
}
|
||||
}
|
||||
|
|
@ -230,9 +230,14 @@ namespace Nz
|
|||
{
|
||||
assert(m_context);
|
||||
|
||||
if (node.variable->GetType() != ShaderNodes::VariableType::LocalVariable)
|
||||
throw AstError{ "Only local variables can be declared in a statement" };
|
||||
|
||||
const auto& localVar = static_cast<const ShaderNodes::LocalVariable&>(*node.variable);
|
||||
|
||||
auto& local = m_context->declaredLocals.emplace_back();
|
||||
local.name = node.variable->name;
|
||||
local.type = node.variable->type;
|
||||
local.name = localVar.name;
|
||||
local.type = localVar.type;
|
||||
|
||||
ShaderAstRecursiveVisitor::Visit(node);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue