ShaderAst: Big refactor + add binding/location support

This commit is contained in:
Lynix 2020-06-17 16:00:03 +02:00
parent 463b540739
commit f38bfdde8a
63 changed files with 2380 additions and 1603 deletions

View File

@ -0,0 +1,9 @@
// This file was automatically generated
#pragma once
#ifndef NDK_COMPONENTS_GLOBAL_HPP
#define NDK_COMPONENTS_GLOBAL_HPP
#endif // NDK_COMPONENTS_GLOBAL_HPP

View File

@ -0,0 +1,9 @@
// This file was automatically generated
#pragma once
#ifndef NDK_SYSTEMS_GLOBAL_HPP
#define NDK_SYSTEMS_GLOBAL_HPP
#endif // NDK_SYSTEMS_GLOBAL_HPP

View File

@ -0,0 +1,9 @@
// This file was automatically generated
#pragma once
#ifndef NDK_WIDGETS_GLOBAL_HPP
#define NDK_WIDGETS_GLOBAL_HPP
#endif // NDK_WIDGETS_GLOBAL_HPP

View File

@ -8,15 +8,19 @@
#define NAZARA_GLSLWRITER_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/StringStream.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/ShaderAst.hpp>
#include <Nazara/Renderer/ShaderVarVisitor.hpp>
#include <Nazara/Renderer/ShaderVisitor.hpp>
#include <Nazara/Renderer/ShaderWriter.hpp>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
namespace Nz
{
class NAZARA_RENDERER_API GlslWriter : public ShaderWriter
class NAZARA_RENDERER_API GlslWriter : public ShaderWriter, public ShaderVarVisitor, public ShaderVisitor
{
public:
GlslWriter();
@ -24,67 +28,65 @@ namespace Nz
GlslWriter(GlslWriter&&) = delete;
~GlslWriter() = default;
Nz::String Generate(const ShaderAst::StatementPtr& node) override;
void RegisterFunction(const String& name, ShaderAst::StatementPtr statement, std::initializer_list<ShaderAst::NamedVariablePtr> parameters, ShaderAst::ExpressionType ret) override;
void RegisterVariable(ShaderAst::VariableType kind, const String& name, ShaderAst::ExpressionType type) override;
std::string Generate(const ShaderAst& shader) override;
void SetGlslVersion(unsigned int version);
using ShaderWriter::Visit;
void Visit(const ShaderAst::AssignOp& node) override;
void Visit(const ShaderAst::Branch& node) override;
void Visit(const ShaderAst::BinaryFunc& node) override;
void Visit(const ShaderAst::BinaryOp& node) override;
void Visit(const ShaderAst::BuiltinVariable& node) override;
void Visit(const ShaderAst::Cast& node) override;
void Visit(const ShaderAst::Constant& node) override;
void Visit(const ShaderAst::DeclareVariable& node) override;
void Visit(const ShaderAst::ExpressionStatement& node) override;
void Visit(const ShaderAst::NamedVariable& node) override;
void Visit(const ShaderAst::Sample2D& node) override;
void Visit(const ShaderAst::StatementBlock& node) override;
void Visit(const ShaderAst::SwizzleOp& node) override;
private:
struct Function;
using VariableContainer = std::set<std::pair<ShaderAst::ExpressionType, String>>;
void Append(ShaderNodes::BuiltinEntry builtin);
void Append(ShaderNodes::ExpressionType type);
template<typename T> void Append(const T& param);
void AppendCommentSection(const std::string& section);
void AppendFunction(const ShaderAst::Function& func);
void AppendFunctionPrototype(const ShaderAst::Function& func);
void AppendLine(const std::string& txt = {});
void Append(ShaderAst::BuiltinEntry builtin);
void Append(ShaderAst::ExpressionType type);
void Append(const String& txt);
void AppendCommentSection(const String& section);
void AppendFunction(Function& func);
void AppendLine(const String& txt = String());
void DeclareVariables(const VariableContainer& variables, const String& keyword = String(), const String& section = String());
template<typename T> void DeclareVariables(const std::vector<T>& variables, const std::string& keyword = {}, const std::string& section = {});
void EnterScope();
void LeaveScope();
using ShaderVarVisitor::Visit;
using ShaderVisitor::Visit;
void Visit(const ShaderNodes::AssignOp& node) override;
void Visit(const ShaderNodes::Branch& node) override;
void Visit(const ShaderNodes::BinaryOp& node) override;
void Visit(const ShaderNodes::BuiltinVariable& var) 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::InputVariable& var) override;
void Visit(const ShaderNodes::IntrinsicCall& node) override;
void Visit(const ShaderNodes::LocalVariable& var) override;
void Visit(const ShaderNodes::ParameterVariable& var) override;
void Visit(const ShaderNodes::OutputVariable& var) override;
void Visit(const ShaderNodes::Sample2D& node) override;
void Visit(const ShaderNodes::StatementBlock& node) override;
void Visit(const ShaderNodes::SwizzleOp& node) override;
void Visit(const ShaderNodes::UniformVariable& var) override;
struct Function
static bool HasExplicitBinding(const ShaderAst& shader);
static bool HasExplicitLocation(const ShaderAst& shader);
struct Context
{
std::vector<ShaderAst::NamedVariablePtr> parameters;
ShaderAst::ExpressionType retType;
ShaderAst::StatementPtr node;
String name;
const ShaderAst::Function* currentFunction = nullptr;
};
struct State
{
VariableContainer inputs;
VariableContainer outputs;
VariableContainer uniforms;
StringStream stream;
std::stringstream stream;
unsigned int indentLevel = 0;
};
std::unordered_map<String, Function> m_functions;
Function* m_currentFunction;
Context m_context;
State* m_currentState;
unsigned int m_glslVersion;
};
}
#include <Nazara/Renderer/GlslWriter.inl>
#endif // NAZARA_GLSLWRITER_HPP

View File

@ -0,0 +1,65 @@
// 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/GlslWriter.hpp>
#include <type_traits>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz
{
template<typename T>
void GlslWriter::Append(const T& param)
{
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
m_currentState->stream << param;
}
template<typename T>
void GlslWriter::DeclareVariables(const std::vector<T>& variables, const std::string& keyword, const std::string& section)
{
if (!variables.empty())
{
if (!section.empty())
AppendCommentSection(section);
for (const auto& var : variables)
{
if constexpr (std::is_same_v<T, ShaderAst::InputOutput>)
{
if (var.locationIndex)
{
Append("layout(location = ");
Append(*var.locationIndex);
Append(") ");
}
}
else if constexpr (std::is_same_v<T, ShaderAst::Uniform>)
{
if (var.bindingIndex)
{
Append("layout(binding = ");
Append(*var.bindingIndex);
Append(") ");
}
}
if (!keyword.empty())
{
Append(keyword);
Append(" ");
}
Append(var.type);
Append(" ");
Append(var.name);
AppendLine(";");
}
AppendLine();
}
}
}
#include <Nazara/Renderer/DebugOff.hpp>

View File

@ -8,393 +8,77 @@
#define NAZARA_SHADER_AST_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Math/Vector2.hpp>
#include <Nazara/Math/Vector3.hpp>
#include <Nazara/Math/Vector4.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <array>
#include <Nazara/Renderer/ShaderNodes.hpp>
#include <optional>
#include <string>
#include <vector>
namespace Nz
{
class ByteStream;
class ShaderVisitor;
class ShaderWriter;
namespace ShaderAst
class NAZARA_RENDERER_API ShaderAst
{
enum class AssignType
{
Simple //< =
};
enum class BinaryIntrinsic
{
CrossProduct,
DotProduct
};
enum class BinaryType
{
Add, //< +
Substract, //< -
Multiply, //< *
Divide, //< /
Equality //< ==
};
enum class BuiltinEntry
{
VertexPosition, // gl_Position
};
enum class ExpressionCategory
{
LValue,
RValue
};
enum class ExpressionType
{
Boolean, // bool
Float1, // float
Float2, // vec2
Float3, // vec3
Float4, // vec4
Mat4x4, // mat4
Sampler2D, // sampler2D
Void // void
};
enum class NodeType
{
None = -1,
AssignOp,
BinaryFunc,
BinaryOp,
Branch,
BuiltinVariable,
Cast,
Constant,
ConditionalStatement,
DeclareVariable,
ExpressionStatement,
NamedVariable,
Sample2D,
SwizzleOp,
StatementBlock
};
enum class SwizzleComponent
{
First,
Second,
Third,
Fourth
};
enum class VariableType
{
Builtin,
Input,
Output,
Parameter,
Uniform,
Variable
};
//////////////////////////////////////////////////////////////////////////
class Node;
using NodePtr = std::shared_ptr<Node>;
class NAZARA_RENDERER_API Node
{
public:
virtual ~Node();
inline NodeType GetType() const;
virtual void Register(ShaderWriter& visitor) = 0;
virtual void Visit(ShaderVisitor& visitor) = 0;
static inline unsigned int GetComponentCount(ExpressionType type);
static inline ExpressionType GetComponentType(ExpressionType type);
protected:
inline Node(NodeType type);
private:
NodeType m_type;
};
class Statement;
using StatementPtr = std::shared_ptr<Statement>;
class NAZARA_RENDERER_API Statement : public Node
{
public:
using Node::Node;
};
class Expression;
using ExpressionPtr = std::shared_ptr<Expression>;
class NAZARA_RENDERER_API Expression : public Node
{
public:
using Node::Node;
virtual ExpressionCategory GetExpressionCategory() const;
virtual ExpressionType GetExpressionType() const = 0;
};
struct NAZARA_RENDERER_API ExpressionStatement : public Statement
{
inline ExpressionStatement();
void Register(ShaderWriter& visitor) override;
void Visit(ShaderVisitor& visitor) override;
ExpressionPtr expression;
static inline std::shared_ptr<ExpressionStatement> Build(ExpressionPtr expr);
};
//////////////////////////////////////////////////////////////////////////
struct NAZARA_RENDERER_API ConditionalStatement : public Statement
{
inline ConditionalStatement();
void Register(ShaderWriter& visitor) override;
void Visit(ShaderVisitor& visitor) override;
std::string conditionName;
StatementPtr statement;
static inline std::shared_ptr<ConditionalStatement> Build(std::string condition, StatementPtr statementPtr);
};
struct NAZARA_RENDERER_API StatementBlock : public Statement
{
inline StatementBlock();
void Register(ShaderWriter& visitor) override;
void Visit(ShaderVisitor& visitor) override;
std::vector<StatementPtr> statements;
template<typename... Args> static std::shared_ptr<StatementBlock> Build(Args&&... args);
};
struct Variable;
using VariablePtr = std::shared_ptr<Variable>;
struct NAZARA_RENDERER_API Variable : public Expression
{
using Expression::Expression;
ExpressionCategory GetExpressionCategory() const override;
ExpressionType GetExpressionType() const override;
ExpressionType type;
VariableType kind;
};
struct NAZARA_RENDERER_API BuiltinVariable : public Variable
{
inline BuiltinVariable();
void Register(ShaderWriter& visitor) override;
void Visit(ShaderVisitor& visitor) override;
BuiltinEntry var;
static inline std::shared_ptr<BuiltinVariable> Build(BuiltinEntry variable, ExpressionType varType);
};
struct NamedVariable;
using NamedVariablePtr = std::shared_ptr<NamedVariable>;
struct NAZARA_RENDERER_API NamedVariable : public Variable
{
inline NamedVariable();
void Register(ShaderWriter& visitor) override;
void Visit(ShaderVisitor& visitor) override;
std::string name;
static inline std::shared_ptr<NamedVariable> Build(VariableType varType, std::string varName, ExpressionType expressionType);
};
struct NAZARA_RENDERER_API DeclareVariable : public Statement
{
inline DeclareVariable();
void Register(ShaderWriter& visitor) override;
void Visit(ShaderVisitor& visitor) override;
NamedVariablePtr variable;
ExpressionPtr expression;
static inline std::shared_ptr<DeclareVariable> Build(NamedVariablePtr variable, ExpressionPtr expression = nullptr);
};
//////////////////////////////////////////////////////////////////////////
struct NAZARA_RENDERER_API AssignOp : public Expression
{
inline AssignOp();
ExpressionType GetExpressionType() const override;
void Register(ShaderWriter& visitor) override;
void Visit(ShaderVisitor& visitor) override;
AssignType op;
ExpressionPtr left;
ExpressionPtr right;
static inline std::shared_ptr<AssignOp> Build(AssignType op, ExpressionPtr left, ExpressionPtr right);
};
struct NAZARA_RENDERER_API BinaryOp : public Expression
{
inline BinaryOp();
ExpressionType GetExpressionType() const override;
void Register(ShaderWriter& visitor) override;
void Visit(ShaderVisitor& visitor) override;
BinaryType op;
ExpressionPtr left;
ExpressionPtr right;
static inline std::shared_ptr<BinaryOp> Build(BinaryType op, ExpressionPtr left, ExpressionPtr right);
};
struct NAZARA_RENDERER_API Branch : public Statement
{
struct ConditionalStatement;
inline Branch();
void Register(ShaderWriter& visitor) override;
void Visit(ShaderVisitor& visitor) override;
std::vector<ConditionalStatement> condStatements;
StatementPtr elseStatement;
struct ConditionalStatement
public:
struct Function;
struct FunctionParameter;
struct InputOutput;
struct VariableBase;
struct Uniform;
ShaderAst() = default;
~ShaderAst() = default;
void AddFunction(std::string name, ShaderNodes::StatementPtr statement, std::vector<FunctionParameter> parameters = {}, ShaderNodes::ExpressionType returnType = ShaderNodes::ExpressionType::Void);
void AddInput(std::string name, ShaderNodes::ExpressionType type, std::optional<std::size_t> locationIndex);
void AddOutput(std::string name, ShaderNodes::ExpressionType type, std::optional<std::size_t> locationIndex);
void AddUniform(std::string name, ShaderNodes::ExpressionType type, std::optional<std::size_t> bindingIndex);
inline const Function& GetFunction(std::size_t i) const;
inline std::size_t GetFunctionCount() const;
inline const std::vector<Function>& GetFunctions() const;
inline const InputOutput& GetInput(std::size_t i) const;
inline std::size_t GetInputCount() const;
inline const std::vector<InputOutput>& GetInputs() const;
inline const InputOutput& GetOutput(std::size_t i) const;
inline std::size_t GetOutputCount() const;
inline const std::vector<InputOutput>& GetOutputs() const;
inline const Uniform& GetUniform(std::size_t i) const;
inline std::size_t GetUniformCount() const;
inline const std::vector<Uniform>& GetUniforms() const;
struct VariableBase
{
ExpressionPtr condition;
StatementPtr statement;
std::string name;
ShaderNodes::ExpressionType type;
};
inline std::shared_ptr<Branch> Build(ExpressionPtr condition, StatementPtr trueStatement, StatementPtr falseStatement = nullptr);
};
struct NAZARA_RENDERER_API Cast : public Expression
{
inline Cast();
ExpressionType GetExpressionType() const override;
void Register(ShaderWriter& visitor) override;
void Visit(ShaderVisitor& visitor) override;
ExpressionType exprType;
std::array<ExpressionPtr, 4> expressions;
static inline std::shared_ptr<Cast> Build(ExpressionType castTo, ExpressionPtr first, ExpressionPtr second = nullptr, ExpressionPtr third = nullptr, ExpressionPtr fourth = nullptr);
static inline std::shared_ptr<Cast> Build(ExpressionType castTo, ExpressionPtr* expressions, std::size_t expressionCount);
};
struct NAZARA_RENDERER_API Constant : public Expression
{
inline Constant();
ExpressionType GetExpressionType() const override;
void Register(ShaderWriter& visitor) override;
void Visit(ShaderVisitor& visitor) override;
ExpressionType exprType;
union
struct FunctionParameter : VariableBase
{
bool bool1;
float vec1;
Vector2f vec2;
Vector3f vec3;
Vector4f vec4;
} values;
};
static inline std::shared_ptr<Constant> Build(bool value);
static inline std::shared_ptr<Constant> Build(float value);
static inline std::shared_ptr<Constant> Build(const Vector2f& value);
static inline std::shared_ptr<Constant> Build(const Vector3f& value);
static inline std::shared_ptr<Constant> Build(const Vector4f& value);
};
struct Function
{
std::string name;
std::vector<FunctionParameter> parameters;
ShaderNodes::ExpressionType returnType;
ShaderNodes::StatementPtr statement;
};
struct NAZARA_RENDERER_API SwizzleOp : public Expression
{
inline SwizzleOp();
struct InputOutput : VariableBase
{
std::optional<std::size_t> locationIndex;
};
ExpressionCategory GetExpressionCategory() const override;
ExpressionType GetExpressionType() const override;
void Register(ShaderWriter& visitor) override;
void Visit(ShaderVisitor& visitor) override;
struct Uniform : VariableBase
{
std::optional<std::size_t> bindingIndex;
};
std::array<SwizzleComponent, 4> components;
std::size_t componentCount;
ExpressionPtr expression;
static inline std::shared_ptr<SwizzleOp> Build(ExpressionPtr expressionPtr, std::initializer_list<SwizzleComponent> swizzleComponents);
};
//////////////////////////////////////////////////////////////////////////
struct NAZARA_RENDERER_API Sample2D : public Expression
{
inline Sample2D();
ExpressionType GetExpressionType() const override;
void Register(ShaderWriter& visitor) override;
void Visit(ShaderVisitor& visitor) override;
ExpressionPtr sampler;
ExpressionPtr coordinates;
static inline std::shared_ptr<Sample2D> Build(ExpressionPtr samplerPtr, ExpressionPtr coordinatesPtr);
};
//////////////////////////////////////////////////////////////////////////
struct NAZARA_RENDERER_API BinaryFunc : public Expression
{
inline BinaryFunc();
ExpressionType GetExpressionType() const override;
void Register(ShaderWriter& visitor) override;
void Visit(ShaderVisitor& visitor) override;
BinaryIntrinsic intrinsic;
ExpressionPtr left;
ExpressionPtr right;
static inline std::shared_ptr<BinaryFunc> Build(BinaryIntrinsic intrinsic, ExpressionPtr left, ExpressionPtr right);
};
}
private:
std::vector<Function> m_functions;
std::vector<InputOutput> m_inputs;
std::vector<InputOutput> m_outputs;
std::vector<Uniform> m_uniforms;
};
}
#include <Nazara/Renderer/ShaderAst.inl>

View File

@ -7,315 +7,68 @@
namespace Nz
{
namespace ShaderAst
inline auto ShaderAst::GetFunction(std::size_t i) const -> const Function&
{
inline Node::Node(NodeType type) :
m_type(type)
{
}
inline NodeType ShaderAst::Node::GetType() const
{
return m_type;
}
inline unsigned int Node::GetComponentCount(ExpressionType type)
{
switch (type)
{
case ExpressionType::Float2:
return 2;
case ExpressionType::Float3:
return 3;
case ExpressionType::Float4:
return 4;
case ExpressionType::Mat4x4:
return 4;
default:
return 1;
}
}
inline ExpressionType Node::GetComponentType(ExpressionType type)
{
switch (type)
{
case ExpressionType::Float2:
case ExpressionType::Float3:
case ExpressionType::Float4:
return ExpressionType::Float1;
case ExpressionType::Mat4x4:
return ExpressionType::Float4;
default:
return type;
}
}
inline ExpressionStatement::ExpressionStatement() :
Statement(NodeType::ExpressionStatement)
{
}
inline std::shared_ptr<ExpressionStatement> ExpressionStatement::Build(ExpressionPtr expr)
{
auto node = std::make_shared<ExpressionStatement>();
node->expression = std::move(expr);
return node;
}
inline ConditionalStatement::ConditionalStatement() :
Statement(NodeType::ConditionalStatement)
{
}
inline std::shared_ptr<ConditionalStatement> ConditionalStatement::Build(std::string condition, StatementPtr statementPtr)
{
auto node = std::make_shared<ConditionalStatement>();
node->conditionName = std::move(condition);
node->statement = std::move(statementPtr);
return node;
}
inline StatementBlock::StatementBlock() :
Statement(NodeType::StatementBlock)
{
}
template<typename... Args>
std::shared_ptr<StatementBlock> StatementBlock::Build(Args&&... args)
{
auto node = std::make_shared<StatementBlock>();
node->statements = std::vector<StatementPtr>({ std::forward<Args>(args)... });
return node;
}
inline BuiltinVariable::BuiltinVariable() :
Variable(NodeType::BuiltinVariable)
{
kind = VariableType::Builtin;
}
inline std::shared_ptr<BuiltinVariable> BuiltinVariable::Build(BuiltinEntry variable, ExpressionType varType)
{
auto node = std::make_shared<BuiltinVariable>();
node->type = varType;
node->var = variable;
return node;
}
inline NamedVariable::NamedVariable() :
Variable(NodeType::NamedVariable)
{
}
inline std::shared_ptr<NamedVariable> NamedVariable::Build(VariableType type, std::string varName, ExpressionType expressionType)
{
auto node = std::make_shared<NamedVariable>();
node->kind = type;
node->name = std::move(varName);
node->type = expressionType;
return node;
}
inline DeclareVariable::DeclareVariable() :
Statement(NodeType::DeclareVariable)
{
}
inline std::shared_ptr<DeclareVariable> DeclareVariable::Build(NamedVariablePtr variable, ExpressionPtr expression)
{
auto node = std::make_shared<DeclareVariable>();
node->expression = std::move(expression);
node->variable = std::move(variable);
return node;
}
inline AssignOp::AssignOp() :
Expression(NodeType::AssignOp)
{
}
inline std::shared_ptr<AssignOp> AssignOp::Build(AssignType op, ExpressionPtr left, ExpressionPtr right)
{
auto node = std::make_shared<AssignOp>();
node->op = op;
node->left = std::move(left);
node->right = std::move(right);
return node;
}
inline BinaryOp::BinaryOp() :
Expression(NodeType::BinaryOp)
{
}
inline std::shared_ptr<BinaryOp> BinaryOp::Build(BinaryType op, ExpressionPtr left, ExpressionPtr right)
{
auto node = std::make_shared<BinaryOp>();
node->op = op;
node->left = std::move(left);
node->right = std::move(right);
return node;
}
inline Branch::Branch() :
Statement(NodeType::Branch)
{
}
inline std::shared_ptr<Branch> Branch::Build(ExpressionPtr condition, StatementPtr trueStatement, StatementPtr falseStatement)
{
auto node = std::make_shared<Branch>();
node->condStatements.emplace_back(ConditionalStatement{ std::move(condition), std::move(trueStatement) });
node->elseStatement = std::move(falseStatement);
return node;
}
inline Cast::Cast() :
Expression(NodeType::Cast)
{
}
inline std::shared_ptr<Cast> Cast::Build(ExpressionType castTo, ExpressionPtr first, ExpressionPtr second, ExpressionPtr third, ExpressionPtr fourth)
{
auto node = std::make_shared<Cast>();
node->exprType = castTo;
node->expressions = { {first, second, third, fourth} };
return node;
}
inline std::shared_ptr<Cast> Cast::Build(ExpressionType castTo, ExpressionPtr* Expressions, std::size_t expressionCount)
{
auto node = std::make_shared<Cast>();
node->exprType = castTo;
for (std::size_t i = 0; i < expressionCount; ++i)
node->expressions[i] = Expressions[i];
return node;
}
inline Constant::Constant() :
Expression(NodeType::Constant)
{
}
inline std::shared_ptr<Constant> Constant::Build(bool value)
{
auto node = std::make_shared<Constant>();
node->exprType = ExpressionType::Boolean;
node->values.bool1 = value;
return node;
}
inline std::shared_ptr<Constant> Constant::Build(float value)
{
auto node = std::make_shared<Constant>();
node->exprType = ExpressionType::Float1;
node->values.vec1 = value;
return node;
}
inline std::shared_ptr<Constant> Constant::Build(const Vector2f& value)
{
auto node = std::make_shared<Constant>();
node->exprType = ExpressionType::Float2;
node->values.vec2 = value;
return node;
}
inline std::shared_ptr<Constant> Constant::Build(const Vector3f& value)
{
auto node = std::make_shared<Constant>();
node->exprType = ExpressionType::Float3;
node->values.vec3 = value;
return node;
}
inline std::shared_ptr<Constant> Constant::Build(const Vector4f& value)
{
auto node = std::make_shared<Constant>();
node->exprType = ExpressionType::Float4;
node->values.vec4 = value;
return node;
}
inline SwizzleOp::SwizzleOp() :
Expression(NodeType::SwizzleOp)
{
}
inline std::shared_ptr<SwizzleOp> SwizzleOp::Build(ExpressionPtr expressionPtr, std::initializer_list<SwizzleComponent> swizzleComponents)
{
auto node = std::make_shared<SwizzleOp>();
node->componentCount = swizzleComponents.size();
node->expression = std::move(expressionPtr);
std::copy(swizzleComponents.begin(), swizzleComponents.end(), node->components.begin());
return node;
}
inline Sample2D::Sample2D() :
Expression(NodeType::Sample2D)
{
}
inline std::shared_ptr<Sample2D> Sample2D::Build(ExpressionPtr samplerPtr, ExpressionPtr coordinatesPtr)
{
auto node = std::make_shared<Sample2D>();
node->coordinates = std::move(coordinatesPtr);
node->sampler = std::move(samplerPtr);
return node;
}
inline BinaryFunc::BinaryFunc() :
Expression(NodeType::BinaryFunc)
{
}
inline std::shared_ptr<BinaryFunc> BinaryFunc::Build(BinaryIntrinsic intrinsic, ExpressionPtr left, ExpressionPtr right)
{
auto node = std::make_shared<BinaryFunc>();
node->intrinsic = intrinsic;
node->left = std::move(left);
node->right = std::move(right);
return node;
}
assert(i < m_functions.size());
return m_functions[i];
}
inline std::size_t ShaderAst::GetFunctionCount() const
{
return m_functions.size();
}
inline auto ShaderAst::GetFunctions() const -> const std::vector<Function>&
{
return m_functions;
}
inline auto ShaderAst::GetInput(std::size_t i) const -> const InputOutput&
{
assert(i < m_inputs.size());
return m_inputs[i];
}
inline std::size_t ShaderAst::GetInputCount() const
{
return m_inputs.size();
}
inline auto ShaderAst::GetInputs() const -> const std::vector<InputOutput>&
{
return m_inputs;
}
inline auto ShaderAst::GetOutput(std::size_t i) const -> const InputOutput&
{
assert(i < m_outputs.size());
return m_outputs[i];
}
inline std::size_t ShaderAst::GetOutputCount() const
{
return m_outputs.size();
}
inline auto ShaderAst::GetOutputs() const -> const std::vector<InputOutput>&
{
return m_outputs;
}
inline auto ShaderAst::GetUniform(std::size_t i) const -> const Uniform&
{
assert(i < m_uniforms.size());
return m_uniforms[i];
}
inline std::size_t ShaderAst::GetUniformCount() const
{
return m_uniforms.size();
}
inline auto ShaderAst::GetUniforms() const -> const std::vector<Uniform>&
{
return m_uniforms;
}
}

View File

@ -8,72 +8,66 @@
#define NAZARA_SHADER_BUILDER_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Renderer/ShaderAst.hpp>
#include <Nazara/Renderer/ShaderNodes.hpp>
#include <memory>
namespace Nz::ShaderBuilder
{
template<ShaderAst::AssignType op>
template<ShaderNodes::AssignType op>
struct AssignOpBuilder
{
constexpr AssignOpBuilder() {}
constexpr AssignOpBuilder() = default;
std::shared_ptr<ShaderAst::AssignOp> operator()(const ShaderAst::ExpressionPtr& left, const ShaderAst::ExpressionPtr& right) const;
std::shared_ptr<ShaderNodes::AssignOp> operator()(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right) const;
};
template<ShaderAst::BinaryType op>
template<ShaderNodes::BinaryType op>
struct BinOpBuilder
{
constexpr BinOpBuilder() {}
constexpr BinOpBuilder() = default;
std::shared_ptr<ShaderAst::BinaryOp> operator()(const ShaderAst::ExpressionPtr& left, const ShaderAst::ExpressionPtr& right) const;
std::shared_ptr<ShaderNodes::BinaryOp> operator()(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right) const;
};
struct BuiltinBuilder
{
constexpr BuiltinBuilder() {}
constexpr BuiltinBuilder() = default;
inline std::shared_ptr<ShaderAst::Variable> operator()(ShaderAst::BuiltinEntry builtin) const;
inline std::shared_ptr<ShaderNodes::Variable> operator()(ShaderNodes::BuiltinEntry builtin) const;
};
template<typename T>
struct GenBuilder
{
constexpr GenBuilder() {}
constexpr GenBuilder() = default;
template<typename... Args> std::shared_ptr<T> operator()(Args&&... args) const;
};
template<ShaderAst::VariableType type>
struct VarBuilder
{
constexpr VarBuilder() {}
template<typename... Args> ShaderAst::NamedVariablePtr operator()(Args&&... args) const;
};
constexpr BinOpBuilder<ShaderAst::BinaryType::Add> Add;
constexpr AssignOpBuilder<ShaderAst::AssignType::Simple> Assign;
constexpr BinOpBuilder<ShaderNodes::BinaryType::Add> Add;
constexpr AssignOpBuilder<ShaderNodes::AssignType::Simple> Assign;
constexpr BuiltinBuilder Builtin;
constexpr GenBuilder<ShaderAst::StatementBlock> Block;
constexpr GenBuilder<ShaderAst::Branch> Branch;
constexpr GenBuilder<ShaderAst::ConditionalStatement> ConditionalStatement;
constexpr GenBuilder<ShaderAst::Constant> Constant;
constexpr GenBuilder<ShaderAst::DeclareVariable> DeclareVariable;
constexpr BinOpBuilder<ShaderAst::BinaryType::Divide> Divide;
constexpr BinOpBuilder<ShaderAst::BinaryType::Equality> Equal;
constexpr GenBuilder<ShaderAst::ExpressionStatement> ExprStatement;
constexpr VarBuilder<ShaderAst::VariableType::Input> Input;
constexpr BinOpBuilder<ShaderAst::BinaryType::Multiply> Multiply;
constexpr VarBuilder<ShaderAst::VariableType::Output> Output;
constexpr VarBuilder<ShaderAst::VariableType::Parameter> Parameter;
constexpr GenBuilder<ShaderAst::Sample2D> Sample2D;
constexpr GenBuilder<ShaderAst::SwizzleOp> Swizzle;
constexpr BinOpBuilder<ShaderAst::BinaryType::Substract> Substract;
constexpr VarBuilder<ShaderAst::VariableType::Uniform> Uniform;
constexpr VarBuilder<ShaderAst::VariableType::Variable> Variable;
constexpr GenBuilder<ShaderNodes::StatementBlock> Block;
constexpr GenBuilder<ShaderNodes::Branch> Branch;
constexpr GenBuilder<ShaderNodes::ConditionalStatement> ConditionalStatement;
constexpr GenBuilder<ShaderNodes::Constant> Constant;
constexpr GenBuilder<ShaderNodes::DeclareVariable> DeclareVariable;
constexpr BinOpBuilder<ShaderNodes::BinaryType::Divide> Divide;
constexpr BinOpBuilder<ShaderNodes::BinaryType::Equality> Equal;
constexpr GenBuilder<ShaderNodes::ExpressionStatement> ExprStatement;
constexpr GenBuilder<ShaderNodes::Identifier> Identifier;
constexpr GenBuilder<ShaderNodes::IntrinsicCall> IntrinsicCall;
constexpr GenBuilder<ShaderNodes::InputVariable> Input;
constexpr GenBuilder<ShaderNodes::LocalVariable> Local;
constexpr BinOpBuilder<ShaderNodes::BinaryType::Multiply> Multiply;
constexpr GenBuilder<ShaderNodes::OutputVariable> Output;
constexpr GenBuilder<ShaderNodes::ParameterVariable> Parameter;
constexpr GenBuilder<ShaderNodes::Sample2D> Sample2D;
constexpr GenBuilder<ShaderNodes::SwizzleOp> Swizzle;
constexpr BinOpBuilder<ShaderNodes::BinaryType::Substract> Substract;
constexpr GenBuilder<ShaderNodes::UniformVariable> Uniform;
template<ShaderAst::ExpressionType Type, typename... Args> std::shared_ptr<ShaderAst::Cast> Cast(Args&&... args);
template<ShaderNodes::ExpressionType Type, typename... Args> std::shared_ptr<ShaderNodes::Cast> Cast(Args&&... args);
}
#include <Nazara/Renderer/ShaderBuilder.inl>

View File

@ -14,45 +14,38 @@ namespace Nz::ShaderBuilder
return T::Build(std::forward<Args>(args)...);
}
template<ShaderAst::AssignType op>
std::shared_ptr<ShaderAst::AssignOp> AssignOpBuilder<op>::operator()(const ShaderAst::ExpressionPtr& left, const ShaderAst::ExpressionPtr& right) const
template<ShaderNodes::AssignType op>
std::shared_ptr<ShaderNodes::AssignOp> AssignOpBuilder<op>::operator()(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right) const
{
return ShaderAst::AssignOp::Build(op, left, right);
return ShaderNodes::AssignOp::Build(op, left, right);
}
template<ShaderAst::BinaryType op>
std::shared_ptr<ShaderAst::BinaryOp> BinOpBuilder<op>::operator()(const ShaderAst::ExpressionPtr& left, const ShaderAst::ExpressionPtr& right) const
template<ShaderNodes::BinaryType op>
std::shared_ptr<ShaderNodes::BinaryOp> BinOpBuilder<op>::operator()(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right) const
{
return ShaderAst::BinaryOp::Build(op, left, right);
return ShaderNodes::BinaryOp::Build(op, left, right);
}
inline std::shared_ptr<ShaderAst::Variable> BuiltinBuilder::operator()(ShaderAst::BuiltinEntry builtin) const
inline std::shared_ptr<ShaderNodes::Variable> BuiltinBuilder::operator()(ShaderNodes::BuiltinEntry builtin) const
{
ShaderAst::ExpressionType exprType = ShaderAst::ExpressionType::Void;
ShaderNodes::ExpressionType exprType = ShaderNodes::ExpressionType::Void;
switch (builtin)
{
case ShaderAst::BuiltinEntry::VertexPosition:
exprType = ShaderAst::ExpressionType::Float4;
case ShaderNodes::BuiltinEntry::VertexPosition:
exprType = ShaderNodes::ExpressionType::Float4;
break;
}
NazaraAssert(exprType != ShaderAst::ExpressionType::Void, "Unhandled builtin");
NazaraAssert(exprType != ShaderNodes::ExpressionType::Void, "Unhandled builtin");
return ShaderAst::BuiltinVariable::Build(builtin, exprType);
return ShaderNodes::BuiltinVariable::Build(builtin, exprType);
}
template<ShaderAst::VariableType type>
template<typename... Args>
ShaderAst::NamedVariablePtr VarBuilder<type>::operator()(Args&&... args) const
template<ShaderNodes::ExpressionType Type, typename... Args>
std::shared_ptr<ShaderNodes::Cast> Cast(Args&&... args)
{
return ShaderAst::NamedVariable::Build(type, std::forward<Args>(args)...);
}
template<ShaderAst::ExpressionType Type, typename... Args>
std::shared_ptr<ShaderAst::Cast> Cast(Args&&... args)
{
return ShaderAst::Cast::Build(Type, std::forward<Args>(args)...);
return ShaderNodes::Cast::Build(Type, std::forward<Args>(args)...);
}
}

View File

@ -0,0 +1,99 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_SHADER_ENUMS_HPP
#define NAZARA_SHADER_ENUMS_HPP
#include <Nazara/Prerequisites.hpp>
namespace Nz::ShaderNodes
{
enum class AssignType
{
Simple //< =
};
enum class BinaryType
{
Add, //< +
Substract, //< -
Multiply, //< *
Divide, //< /
Equality //< ==
};
enum class BuiltinEntry
{
VertexPosition, // gl_Position
};
enum class ExpressionCategory
{
LValue,
RValue
};
enum class ExpressionType
{
Boolean, // bool
Float1, // float
Float2, // vec2
Float3, // vec3
Float4, // vec4
Mat4x4, // mat4
Sampler2D, // sampler2D
Void // void
};
enum class IntrinsicType
{
CrossProduct,
DotProduct
};
enum class NodeType
{
None = -1,
AssignOp,
BinaryOp,
Branch,
Cast,
Constant,
ConditionalStatement,
DeclareVariable,
ExpressionStatement,
Identifier,
IntrinsicCall,
Sample2D,
SwizzleOp,
StatementBlock
};
enum class SwizzleComponent
{
First,
Second,
Third,
Fourth
};
enum class VariableType
{
None = -1,
BuiltinVariable,
InputVariable,
LocalVariable,
OutputVariable,
ParameterVariable,
UniformVariable
};
}
#endif // NAZARA_SHADER_ENUMS_HPP

View File

@ -0,0 +1,272 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_SHADER_NODES_HPP
#define NAZARA_SHADER_NODES_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Math/Vector2.hpp>
#include <Nazara/Math/Vector3.hpp>
#include <Nazara/Math/Vector4.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/ShaderEnums.hpp>
#include <Nazara/Renderer/ShaderVariables.hpp>
#include <array>
#include <optional>
#include <string>
namespace Nz
{
class ShaderVisitor;
namespace ShaderNodes
{
class Node;
using NodePtr = std::shared_ptr<Node>;
class NAZARA_RENDERER_API Node
{
public:
virtual ~Node();
inline NodeType GetType() const;
virtual void Visit(ShaderVisitor& visitor) = 0;
static inline unsigned int GetComponentCount(ExpressionType type);
static inline ExpressionType GetComponentType(ExpressionType type);
protected:
inline Node(NodeType type);
private:
NodeType m_type;
};
class Statement;
using StatementPtr = std::shared_ptr<Statement>;
class NAZARA_RENDERER_API Statement : public Node
{
public:
using Node::Node;
};
class Expression;
using ExpressionPtr = std::shared_ptr<Expression>;
class NAZARA_RENDERER_API Expression : public Node
{
public:
using Node::Node;
virtual ExpressionCategory GetExpressionCategory() const;
virtual ExpressionType GetExpressionType() const = 0;
};
struct NAZARA_RENDERER_API ExpressionStatement : public Statement
{
inline ExpressionStatement();
void Visit(ShaderVisitor& visitor) override;
ExpressionPtr expression;
static inline std::shared_ptr<ExpressionStatement> Build(ExpressionPtr expr);
};
//////////////////////////////////////////////////////////////////////////
struct NAZARA_RENDERER_API ConditionalStatement : public Statement
{
inline ConditionalStatement();
void Visit(ShaderVisitor& visitor) override;
std::string conditionName;
StatementPtr statement;
static inline std::shared_ptr<ConditionalStatement> Build(std::string condition, StatementPtr statementPtr);
};
struct NAZARA_RENDERER_API StatementBlock : public Statement
{
inline StatementBlock();
void Visit(ShaderVisitor& visitor) override;
std::vector<StatementPtr> statements;
template<typename... Args> static std::shared_ptr<StatementBlock> Build(Args&&... args);
};
struct NAZARA_RENDERER_API DeclareVariable : public Statement
{
inline DeclareVariable();
void Visit(ShaderVisitor& visitor) override;
LocalVariablePtr variable;
ExpressionPtr expression;
static inline std::shared_ptr<DeclareVariable> Build(LocalVariablePtr variable, ExpressionPtr expression = nullptr);
};
struct NAZARA_RENDERER_API Identifier : public Expression
{
inline Identifier();
ExpressionCategory GetExpressionCategory() const override;
ExpressionType GetExpressionType() const override;
void Visit(ShaderVisitor& visitor) override;
VariablePtr var;
static inline std::shared_ptr<Identifier> Build(VariablePtr variable);
};
//////////////////////////////////////////////////////////////////////////
struct NAZARA_RENDERER_API AssignOp : public Expression
{
inline AssignOp();
ExpressionType GetExpressionType() const override;
void Visit(ShaderVisitor& visitor) override;
AssignType op;
ExpressionPtr left;
ExpressionPtr right;
static inline std::shared_ptr<AssignOp> Build(AssignType op, ExpressionPtr left, ExpressionPtr right);
};
struct NAZARA_RENDERER_API BinaryOp : public Expression
{
inline BinaryOp();
ExpressionType GetExpressionType() const override;
void Visit(ShaderVisitor& visitor) override;
BinaryType op;
ExpressionPtr left;
ExpressionPtr right;
static inline std::shared_ptr<BinaryOp> Build(BinaryType op, ExpressionPtr left, ExpressionPtr right);
};
struct NAZARA_RENDERER_API Branch : public Statement
{
struct ConditionalStatement;
inline Branch();
void Visit(ShaderVisitor& visitor) override;
std::vector<ConditionalStatement> condStatements;
StatementPtr elseStatement;
struct ConditionalStatement
{
ExpressionPtr condition;
StatementPtr statement;
};
inline std::shared_ptr<Branch> Build(ExpressionPtr condition, StatementPtr trueStatement, StatementPtr falseStatement = nullptr);
};
struct NAZARA_RENDERER_API Cast : public Expression
{
inline Cast();
ExpressionType GetExpressionType() const override;
void Visit(ShaderVisitor& visitor) override;
ExpressionType exprType;
std::array<ExpressionPtr, 4> expressions;
static inline std::shared_ptr<Cast> Build(ExpressionType castTo, ExpressionPtr first, ExpressionPtr second = nullptr, ExpressionPtr third = nullptr, ExpressionPtr fourth = nullptr);
static inline std::shared_ptr<Cast> Build(ExpressionType castTo, ExpressionPtr* expressions, std::size_t expressionCount);
};
struct NAZARA_RENDERER_API Constant : public Expression
{
inline Constant();
ExpressionType GetExpressionType() const override;
void Visit(ShaderVisitor& visitor) override;
ExpressionType exprType;
union
{
bool bool1;
float vec1;
Vector2f vec2;
Vector3f vec3;
Vector4f vec4;
} values;
static inline std::shared_ptr<Constant> Build(bool value);
static inline std::shared_ptr<Constant> Build(float value);
static inline std::shared_ptr<Constant> Build(const Vector2f& value);
static inline std::shared_ptr<Constant> Build(const Vector3f& value);
static inline std::shared_ptr<Constant> Build(const Vector4f& value);
};
struct NAZARA_RENDERER_API SwizzleOp : public Expression
{
inline SwizzleOp();
ExpressionCategory GetExpressionCategory() const override;
ExpressionType GetExpressionType() const override;
void Visit(ShaderVisitor& visitor) override;
std::array<SwizzleComponent, 4> components;
std::size_t componentCount;
ExpressionPtr expression;
static inline std::shared_ptr<SwizzleOp> Build(ExpressionPtr expressionPtr, std::initializer_list<SwizzleComponent> swizzleComponents);
};
//////////////////////////////////////////////////////////////////////////
struct NAZARA_RENDERER_API Sample2D : public Expression
{
inline Sample2D();
ExpressionType GetExpressionType() const override;
void Visit(ShaderVisitor& visitor) override;
ExpressionPtr sampler;
ExpressionPtr coordinates;
static inline std::shared_ptr<Sample2D> Build(ExpressionPtr samplerPtr, ExpressionPtr coordinatesPtr);
};
//////////////////////////////////////////////////////////////////////////
struct NAZARA_RENDERER_API IntrinsicCall : public Expression
{
inline IntrinsicCall();
ExpressionType GetExpressionType() const override;
void Visit(ShaderVisitor& visitor) override;
IntrinsicType intrinsic;
std::vector<ExpressionPtr> parameters;
static inline std::shared_ptr<IntrinsicCall> Build(IntrinsicType intrinsic, std::vector<ExpressionPtr> parameters);
};
}
}
#include <Nazara/Renderer/ShaderNodes.inl>
#endif

View File

@ -0,0 +1,300 @@
// 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/ShaderNodes.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz::ShaderNodes
{
inline Node::Node(NodeType type) :
m_type(type)
{
}
inline NodeType ShaderNodes::Node::GetType() const
{
return m_type;
}
inline unsigned int Node::GetComponentCount(ExpressionType type)
{
switch (type)
{
case ExpressionType::Float2:
return 2;
case ExpressionType::Float3:
return 3;
case ExpressionType::Float4:
return 4;
case ExpressionType::Mat4x4:
return 4;
default:
return 1;
}
}
inline ExpressionType Node::GetComponentType(ExpressionType type)
{
switch (type)
{
case ExpressionType::Float2:
case ExpressionType::Float3:
case ExpressionType::Float4:
return ExpressionType::Float1;
case ExpressionType::Mat4x4:
return ExpressionType::Float4;
default:
return type;
}
}
inline ExpressionStatement::ExpressionStatement() :
Statement(NodeType::ExpressionStatement)
{
}
inline std::shared_ptr<ExpressionStatement> ExpressionStatement::Build(ExpressionPtr expr)
{
auto node = std::make_shared<ExpressionStatement>();
node->expression = std::move(expr);
return node;
}
inline ConditionalStatement::ConditionalStatement() :
Statement(NodeType::ConditionalStatement)
{
}
inline std::shared_ptr<ConditionalStatement> ConditionalStatement::Build(std::string condition, StatementPtr statementPtr)
{
auto node = std::make_shared<ConditionalStatement>();
node->conditionName = std::move(condition);
node->statement = std::move(statementPtr);
return node;
}
inline StatementBlock::StatementBlock() :
Statement(NodeType::StatementBlock)
{
}
template<typename... Args>
std::shared_ptr<StatementBlock> StatementBlock::Build(Args&&... args)
{
auto node = std::make_shared<StatementBlock>();
node->statements = std::vector<StatementPtr>({ std::forward<Args>(args)... });
return node;
}
inline DeclareVariable::DeclareVariable() :
Statement(NodeType::DeclareVariable)
{
}
inline std::shared_ptr<DeclareVariable> DeclareVariable::Build(LocalVariablePtr variable, ExpressionPtr expression)
{
auto node = std::make_shared<DeclareVariable>();
node->expression = std::move(expression);
node->variable = std::move(variable);
return node;
}
inline Identifier::Identifier() :
Expression(NodeType::Identifier)
{
}
inline std::shared_ptr<Identifier> Identifier::Build(VariablePtr variable)
{
auto node = std::make_shared<Identifier>();
node->var = std::move(variable);
return node;
}
inline AssignOp::AssignOp() :
Expression(NodeType::AssignOp)
{
}
inline std::shared_ptr<AssignOp> AssignOp::Build(AssignType op, ExpressionPtr left, ExpressionPtr right)
{
auto node = std::make_shared<AssignOp>();
node->op = op;
node->left = std::move(left);
node->right = std::move(right);
return node;
}
inline BinaryOp::BinaryOp() :
Expression(NodeType::BinaryOp)
{
}
inline std::shared_ptr<BinaryOp> BinaryOp::Build(BinaryType op, ExpressionPtr left, ExpressionPtr right)
{
auto node = std::make_shared<BinaryOp>();
node->op = op;
node->left = std::move(left);
node->right = std::move(right);
return node;
}
inline Branch::Branch() :
Statement(NodeType::Branch)
{
}
inline std::shared_ptr<Branch> Branch::Build(ExpressionPtr condition, StatementPtr trueStatement, StatementPtr falseStatement)
{
auto node = std::make_shared<Branch>();
node->condStatements.emplace_back(ConditionalStatement{ std::move(condition), std::move(trueStatement) });
node->elseStatement = std::move(falseStatement);
return node;
}
inline Cast::Cast() :
Expression(NodeType::Cast)
{
}
inline std::shared_ptr<Cast> Cast::Build(ExpressionType castTo, ExpressionPtr first, ExpressionPtr second, ExpressionPtr third, ExpressionPtr fourth)
{
auto node = std::make_shared<Cast>();
node->exprType = castTo;
node->expressions = { {first, second, third, fourth} };
return node;
}
inline std::shared_ptr<Cast> Cast::Build(ExpressionType castTo, ExpressionPtr* Expressions, std::size_t expressionCount)
{
auto node = std::make_shared<Cast>();
node->exprType = castTo;
for (std::size_t i = 0; i < expressionCount; ++i)
node->expressions[i] = Expressions[i];
return node;
}
inline Constant::Constant() :
Expression(NodeType::Constant)
{
}
inline std::shared_ptr<Constant> Constant::Build(bool value)
{
auto node = std::make_shared<Constant>();
node->exprType = ExpressionType::Boolean;
node->values.bool1 = value;
return node;
}
inline std::shared_ptr<Constant> Constant::Build(float value)
{
auto node = std::make_shared<Constant>();
node->exprType = ExpressionType::Float1;
node->values.vec1 = value;
return node;
}
inline std::shared_ptr<Constant> Constant::Build(const Vector2f& value)
{
auto node = std::make_shared<Constant>();
node->exprType = ExpressionType::Float2;
node->values.vec2 = value;
return node;
}
inline std::shared_ptr<Constant> Constant::Build(const Vector3f& value)
{
auto node = std::make_shared<Constant>();
node->exprType = ExpressionType::Float3;
node->values.vec3 = value;
return node;
}
inline std::shared_ptr<Constant> Constant::Build(const Vector4f& value)
{
auto node = std::make_shared<Constant>();
node->exprType = ExpressionType::Float4;
node->values.vec4 = value;
return node;
}
inline SwizzleOp::SwizzleOp() :
Expression(NodeType::SwizzleOp)
{
}
inline std::shared_ptr<SwizzleOp> SwizzleOp::Build(ExpressionPtr expressionPtr, std::initializer_list<SwizzleComponent> swizzleComponents)
{
auto node = std::make_shared<SwizzleOp>();
node->componentCount = swizzleComponents.size();
node->expression = std::move(expressionPtr);
std::copy(swizzleComponents.begin(), swizzleComponents.end(), node->components.begin());
return node;
}
inline Sample2D::Sample2D() :
Expression(NodeType::Sample2D)
{
}
inline std::shared_ptr<Sample2D> Sample2D::Build(ExpressionPtr samplerPtr, ExpressionPtr coordinatesPtr)
{
auto node = std::make_shared<Sample2D>();
node->coordinates = std::move(coordinatesPtr);
node->sampler = std::move(samplerPtr);
return node;
}
inline IntrinsicCall::IntrinsicCall() :
Expression(NodeType::IntrinsicCall)
{
}
inline std::shared_ptr<IntrinsicCall> IntrinsicCall::Build(IntrinsicType intrinsic, std::vector<ExpressionPtr> parameters)
{
auto node = std::make_shared<IntrinsicCall>();
node->intrinsic = intrinsic;
node->parameters = std::move(parameters);
return node;
}
}
#include <Nazara/Renderer/DebugOff.hpp>

View File

@ -11,9 +11,10 @@
#include <Nazara/Core/ByteArray.hpp>
#include <Nazara/Core/ByteStream.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/ShaderVisitor.hpp>
#include <Nazara/Renderer/ShaderNodes.hpp>
#include <Nazara/Renderer/ShaderVariables.hpp>
namespace Nz::ShaderAst
namespace Nz::ShaderNodes
{
class NAZARA_RENDERER_API ShaderSerializerBase
{
@ -24,15 +25,16 @@ namespace Nz::ShaderAst
~ShaderSerializerBase() = default;
void Serialize(AssignOp& node);
void Serialize(BinaryFunc& node);
void Serialize(BinaryOp& node);
void Serialize(BuiltinVariable& var);
void Serialize(Branch& node);
void Serialize(BuiltinVariable& node);
void Serialize(Cast& node);
void Serialize(Constant& node);
void Serialize(DeclareVariable& node);
void Serialize(ExpressionStatement& node);
void Serialize(NamedVariable& node);
void Serialize(Identifier& node);
void Serialize(IntrinsicCall& node);
void Serialize(NamedVariable& var);
void Serialize(Sample2D& node);
void Serialize(StatementBlock& node);
void Serialize(SwizzleOp& node);
@ -54,6 +56,9 @@ namespace Nz::ShaderAst
virtual void Value(Vector4f& val) = 0;
virtual void Value(UInt32& val) = 0;
inline void Value(std::size_t& val);
virtual void Variable(VariablePtr& var) = 0;
template<typename T> void Variable(std::shared_ptr<T>& var);
};
class NAZARA_RENDERER_API ShaderSerializer final : public ShaderSerializerBase
@ -74,6 +79,7 @@ namespace Nz::ShaderAst
void Value(Vector3f& val) override;
void Value(Vector4f& val) override;
void Value(UInt32& val) override;
void Variable(VariablePtr& var) override;
ByteArray& m_byteArray;
ByteStream m_stream;
@ -89,7 +95,7 @@ namespace Nz::ShaderAst
private:
bool IsWriting() const override;
void Node(NodePtr & node) override;
void Node(NodePtr& node) override;
void Value(bool& val) override;
void Value(float& val) override;
void Value(std::string& val) override;
@ -97,6 +103,7 @@ namespace Nz::ShaderAst
void Value(Vector3f& val) override;
void Value(Vector4f& val) override;
void Value(UInt32& val) override;
void Variable(VariablePtr& var) override;
const ByteArray& m_byteArray;
ByteStream m_stream;

View File

@ -5,7 +5,7 @@
#include <Nazara/Renderer/ShaderSerializer.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz::ShaderAst
namespace Nz::ShaderNodes
{
template<typename T>
void ShaderSerializerBase::Container(T& container)
@ -37,7 +37,7 @@ namespace Nz::ShaderAst
}
template<typename T>
inline void ShaderSerializerBase::Node(std::shared_ptr<T>& node)
void ShaderSerializerBase::Node(std::shared_ptr<T>& node)
{
bool isWriting = IsWriting();
@ -50,6 +50,20 @@ namespace Nz::ShaderAst
node = std::static_pointer_cast<T>(value);
}
template<typename T>
void ShaderSerializerBase::Variable(std::shared_ptr<T>& var)
{
bool isWriting = IsWriting();
VariablePtr value;
if (isWriting)
value = var;
Variable(value);
if (!isWriting)
var = std::static_pointer_cast<T>(value);
}
inline void ShaderSerializerBase::Value(std::size_t& val)
{
bool isWriting = IsWriting();

View File

@ -13,40 +13,47 @@
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/ShaderVisitor.hpp>
namespace Nz::ShaderAst
namespace Nz
{
class ShaderAst;
class NAZARA_RENDERER_API ShaderValidator : public ShaderVisitor
{
public:
ShaderValidator() = default;
inline ShaderValidator(const ShaderAst& shader);
ShaderValidator(const ShaderValidator&) = delete;
ShaderValidator(ShaderValidator&&) = delete;
~ShaderValidator() = default;
bool Validate(const StatementPtr& shader, std::string* error = nullptr);
bool Validate(std::string* error = nullptr);
private:
const ExpressionPtr& MandatoryExpr(const ExpressionPtr& node);
const NodePtr& MandatoryNode(const NodePtr& node);
void TypeMustMatch(const ExpressionPtr& left, const ExpressionPtr& right);
const ShaderNodes::ExpressionPtr& MandatoryExpr(const ShaderNodes::ExpressionPtr& node);
const ShaderNodes::NodePtr& MandatoryNode(const ShaderNodes::NodePtr& node);
void TypeMustMatch(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right);
void TypeMustMatch(ShaderNodes::ExpressionType left, ShaderNodes::ExpressionType right);
using ShaderVisitor::Visit;
void Visit(const AssignOp& node) override;
void Visit(const BinaryFunc& node) override;
void Visit(const BinaryOp& node) override;
void Visit(const Branch& node) override;
void Visit(const BuiltinVariable& node) override;
void Visit(const Cast& node) override;
void Visit(const Constant& node) override;
void Visit(const DeclareVariable& node) override;
void Visit(const ExpressionStatement& node) override;
void Visit(const NamedVariable& node) override;
void Visit(const Sample2D& node) override;
void Visit(const StatementBlock& node) override;
void Visit(const SwizzleOp& 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;
struct Context;
const ShaderAst& m_shader;
Context* m_context;
};
NAZARA_RENDERER_API bool Validate(const StatementPtr& shader, std::string* error = nullptr);
NAZARA_RENDERER_API bool ValidateShader(const ShaderAst& shader, std::string* error = nullptr);
}
#include <Nazara/Renderer/ShaderValidator.inl>

View File

@ -5,8 +5,12 @@
#include <Nazara/Renderer/ShaderValidator.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz::ShaderAst
namespace Nz
{
ShaderValidator::ShaderValidator(const ShaderAst& shader) :
m_shader(shader)
{
}
}
#include <Nazara/Renderer/DebugOff.hpp>

View File

@ -0,0 +1,34 @@
// 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_SHADERVARVISITOR_HPP
#define NAZARA_SHADERVARVISITOR_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/ShaderVariables.hpp>
namespace Nz
{
class NAZARA_RENDERER_API ShaderVarVisitor
{
public:
ShaderVarVisitor() = default;
ShaderVarVisitor(const ShaderVarVisitor&) = delete;
ShaderVarVisitor(ShaderVarVisitor&&) = delete;
virtual ~ShaderVarVisitor();
virtual void Visit(const ShaderNodes::BuiltinVariable& var) = 0;
virtual void Visit(const ShaderNodes::InputVariable& var) = 0;
virtual void Visit(const ShaderNodes::LocalVariable& var) = 0;
virtual void Visit(const ShaderNodes::OutputVariable& var) = 0;
virtual void Visit(const ShaderNodes::ParameterVariable& var) = 0;
virtual void Visit(const ShaderNodes::UniformVariable& var) = 0;
void Visit(const ShaderNodes::VariablePtr& node);
};
}
#endif

View File

@ -0,0 +1,127 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_SHADER_VARIABLES_HPP
#define NAZARA_SHADER_VARIABLES_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Math/Vector2.hpp>
#include <Nazara/Math/Vector3.hpp>
#include <Nazara/Math/Vector4.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/ShaderEnums.hpp>
#include <array>
#include <optional>
#include <string>
namespace Nz
{
class ShaderVarVisitor;
namespace ShaderNodes
{
struct Variable;
using VariablePtr = std::shared_ptr<Variable>;
struct NAZARA_RENDERER_API Variable
{
virtual ~Variable();
virtual VariableType GetType() const = 0;
virtual void Visit(ShaderVarVisitor& visitor) = 0;
ExpressionType type;
};
struct BuiltinVariable;
using BuiltinVariablePtr = std::shared_ptr<BuiltinVariable>;
struct NAZARA_RENDERER_API BuiltinVariable : public Variable
{
BuiltinEntry entry;
VariableType GetType() const override;
void Visit(ShaderVarVisitor& visitor) override;
static inline std::shared_ptr<BuiltinVariable> Build(BuiltinEntry entry, ExpressionType varType);
};
struct NamedVariable;
using NamedVariablePtr = std::shared_ptr<NamedVariable>;
struct NAZARA_RENDERER_API NamedVariable : public Variable
{
std::string name;
};
struct InputVariable;
using InputVariablePtr = std::shared_ptr<InputVariable>;
struct NAZARA_RENDERER_API InputVariable : public NamedVariable
{
VariableType GetType() const override;
void Visit(ShaderVarVisitor& visitor) override;
static inline std::shared_ptr<InputVariable> Build(std::string varName, ExpressionType varType);
};
struct LocalVariable;
using LocalVariablePtr = std::shared_ptr<LocalVariable>;
struct NAZARA_RENDERER_API LocalVariable : public NamedVariable
{
VariableType GetType() const override;
void Visit(ShaderVarVisitor& visitor) override;
static inline std::shared_ptr<LocalVariable> Build(std::string varName, ExpressionType varType);
};
struct OutputVariable;
using OutputVariablePtr = std::shared_ptr<OutputVariable>;
struct NAZARA_RENDERER_API OutputVariable : public NamedVariable
{
VariableType GetType() const override;
void Visit(ShaderVarVisitor& visitor) override;
static inline std::shared_ptr<OutputVariable> Build(std::string varName, ExpressionType varType);
};
struct ParameterVariable;
using ParameterVariablePtr = std::shared_ptr<ParameterVariable>;
struct NAZARA_RENDERER_API ParameterVariable : public NamedVariable
{
VariableType GetType() const override;
void Visit(ShaderVarVisitor& visitor) override;
static inline std::shared_ptr<ParameterVariable> Build(std::string varName, ExpressionType varType);
};
struct UniformVariable;
using UniformVariablePtr = std::shared_ptr<UniformVariable>;
struct NAZARA_RENDERER_API UniformVariable : public NamedVariable
{
VariableType GetType() const override;
void Visit(ShaderVarVisitor& visitor) override;
static inline std::shared_ptr<UniformVariable> Build(std::string varName, ExpressionType varType);
};
}
}
#include <Nazara/Renderer/ShaderVariables.inl>
#endif

View File

@ -0,0 +1,65 @@
// 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/ShaderVariables.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz::ShaderNodes
{
inline std::shared_ptr<BuiltinVariable> BuiltinVariable::Build(BuiltinEntry variable, ExpressionType varType)
{
auto node = std::make_shared<BuiltinVariable>();
node->entry = variable;
node->type = varType;
return node;
}
inline std::shared_ptr<InputVariable> InputVariable::Build(std::string varName, ExpressionType varType)
{
auto node = std::make_shared<InputVariable>();
node->name = std::move(varName);
node->type = varType;
return node;
}
inline std::shared_ptr<LocalVariable> LocalVariable::Build(std::string varName, ExpressionType varType)
{
auto node = std::make_shared<LocalVariable>();
node->name = std::move(varName);
node->type = varType;
return node;
}
inline std::shared_ptr<OutputVariable> OutputVariable::Build(std::string varName, ExpressionType varType)
{
auto node = std::make_shared<OutputVariable>();
node->name = std::move(varName);
node->type = varType;
return node;
}
inline std::shared_ptr<ParameterVariable> ParameterVariable::Build(std::string varName, ExpressionType varType)
{
auto node = std::make_shared<ParameterVariable>();
node->name = std::move(varName);
node->type = varType;
return node;
}
inline std::shared_ptr<UniformVariable> UniformVariable::Build(std::string varName, ExpressionType varType)
{
auto node = std::make_shared<UniformVariable>();
node->name = std::move(varName);
node->type = varType;
return node;
}
}
#include <Nazara/Renderer/DebugOff.hpp>

View File

@ -8,9 +8,9 @@
#define NAZARA_SHADERVISITOR_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/ShaderAst.hpp>
#include <Nazara/Renderer/ShaderNodes.hpp>
#include <string>
#include <unordered_set>
namespace Nz
@ -23,27 +23,26 @@ namespace Nz
ShaderVisitor(ShaderVisitor&&) = delete;
virtual ~ShaderVisitor();
void EnableCondition(const String& name, bool cond);
void EnableCondition(const std::string& name, bool cond);
bool IsConditionEnabled(const String& name) const;
bool IsConditionEnabled(const std::string& name) const;
virtual void Visit(const ShaderAst::AssignOp& node) = 0;
virtual void Visit(const ShaderAst::BinaryFunc& node) = 0;
virtual void Visit(const ShaderAst::BinaryOp& node) = 0;
virtual void Visit(const ShaderAst::Branch& node) = 0;
virtual void Visit(const ShaderAst::BuiltinVariable& node) = 0;
virtual void Visit(const ShaderAst::Cast& node) = 0;
virtual void Visit(const ShaderAst::Constant& node) = 0;
virtual void Visit(const ShaderAst::DeclareVariable& node) = 0;
virtual void Visit(const ShaderAst::ExpressionStatement& node) = 0;
virtual void Visit(const ShaderAst::NamedVariable& node) = 0;
void Visit(const ShaderAst::NodePtr& node);
virtual void Visit(const ShaderAst::Sample2D& node) = 0;
virtual void Visit(const ShaderAst::StatementBlock& node) = 0;
virtual void Visit(const ShaderAst::SwizzleOp& node) = 0;
virtual void Visit(const ShaderNodes::AssignOp& node) = 0;
virtual void Visit(const ShaderNodes::BinaryOp& node) = 0;
virtual void Visit(const ShaderNodes::Branch& node) = 0;
virtual void Visit(const ShaderNodes::Cast& node) = 0;
virtual void Visit(const ShaderNodes::Constant& node) = 0;
virtual void Visit(const ShaderNodes::DeclareVariable& node) = 0;
virtual void Visit(const ShaderNodes::ExpressionStatement& node) = 0;
virtual void Visit(const ShaderNodes::Identifier& node) = 0;
virtual void Visit(const ShaderNodes::IntrinsicCall& node) = 0;
void Visit(const ShaderNodes::NodePtr& node);
virtual void Visit(const ShaderNodes::Sample2D& node) = 0;
virtual void Visit(const ShaderNodes::StatementBlock& node) = 0;
virtual void Visit(const ShaderNodes::SwizzleOp& node) = 0;
private:
std::unordered_set<String> m_conditions;
std::unordered_set<std::string> m_conditions;
};
}

View File

@ -8,24 +8,22 @@
#define NAZARA_SHADERWRITER_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/ShaderVisitor.hpp>
#include <string>
namespace Nz
{
class NAZARA_RENDERER_API ShaderWriter : public ShaderVisitor
class ShaderAst;
class NAZARA_RENDERER_API ShaderWriter
{
public:
ShaderWriter() = default;
ShaderWriter(const ShaderWriter&) = delete;
ShaderWriter(ShaderWriter&&) = delete;
~ShaderWriter() = default;
virtual ~ShaderWriter();
virtual Nz::String Generate(const ShaderAst::StatementPtr& node) = 0;
virtual void RegisterFunction(const String& name, ShaderAst::StatementPtr node, std::initializer_list<ShaderAst::NamedVariablePtr> parameters, ShaderAst::ExpressionType ret) = 0;
virtual void RegisterVariable(ShaderAst::VariableType kind, const String& name, ShaderAst::ExpressionType type) = 0;
virtual std::string Generate(const ShaderAst& shader) = 0;
};
}

View File

@ -11,16 +11,15 @@
namespace Nz
{
GlslWriter::GlslWriter() :
m_currentFunction(nullptr),
m_currentState(nullptr),
m_glslVersion(110)
{
}
String GlslWriter::Generate(const ShaderAst::StatementPtr& node)
std::string GlslWriter::Generate(const ShaderAst& shader)
{
std::string error;
if (!ShaderAst::Validate(node, &error))
if (!ValidateShader(shader, &error))
throw std::runtime_error("Invalid shader AST: " + error);
State state;
@ -30,91 +29,54 @@ namespace Nz
m_currentState = nullptr;
});
// Register global variables (uniforms, varying, ..)
node->Register(*this);
// Header
Append("#version ");
AppendLine(String::Number(m_glslVersion));
AppendLine(std::to_string(m_glslVersion));
AppendLine();
// Global variables (uniforms, input and outputs)
DeclareVariables(state.uniforms, "uniform", "Uniforms");
DeclareVariables(state.inputs, "in", "Inputs");
DeclareVariables(state.outputs, "out", "Outputs");
// Extensions
Function entryPoint;
entryPoint.name = "main"; //< GLSL has only one entry point name possible
entryPoint.node = node;
entryPoint.retType = ShaderAst::ExpressionType::Void;
std::vector<std::string> requiredExtensions;
AppendFunction(entryPoint);
// GL_ARB_shading_language_420pack (required for layout(binding = X))
if (m_glslVersion < 420 && HasExplicitBinding(shader))
requiredExtensions.emplace_back("GL_ARB_shading_language_420pack");
return state.stream;
}
// GL_ARB_explicit_uniform_location (required for layout(location = X))
if (m_glslVersion < 430 && HasExplicitLocation(shader))
requiredExtensions.emplace_back("GL_ARB_explicit_uniform_location");
void GlslWriter::RegisterFunction(const String& name, ShaderAst::StatementPtr statement, std::initializer_list<ShaderAst::NamedVariablePtr> parameters, ShaderAst::ExpressionType retType)
{
Function func;
func.retType = retType;
func.name = name;
func.node = std::move(statement);
func.parameters.assign(parameters);
m_functions[name] = std::move(func);
}
void GlslWriter::RegisterVariable(ShaderAst::VariableType kind, const String& name, ShaderAst::ExpressionType type)
{
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
NazaraAssert(kind != ShaderAst::VariableType::Builtin, "Builtin variables should not be registered");
switch (kind)
if (!requiredExtensions.empty())
{
case ShaderAst::VariableType::Builtin: //< Only there to make compiler happy
case ShaderAst::VariableType::Variable:
break;
for (const std::string& ext : requiredExtensions)
AppendLine("#extension " + ext + " : require");
case ShaderAst::VariableType::Input:
m_currentState->inputs.emplace(type, name);
break;
case ShaderAst::VariableType::Output:
m_currentState->outputs.emplace(type, name);
break;
case ShaderAst::VariableType::Parameter:
{
if (m_currentFunction)
{
bool found = false;
for (const auto& varPtr : m_currentFunction->parameters)
{
if (varPtr->name == name)
{
found = true;
if (varPtr->type != type)
{
//TODO: AstParseError
throw std::runtime_error("Function uses parameter \"" + name.ToStdString() + "\" with a different type than specified in the function arguments");
}
break;
}
}
if (!found)
//TODO: AstParseError
throw std::runtime_error("Function has no parameter \"" + name.ToStdString() + "\"");
}
break;
}
case ShaderAst::VariableType::Uniform:
m_currentState->uniforms.emplace(type, name);
break;
AppendLine();
}
// Global variables (uniforms, input and outputs)
DeclareVariables(shader.GetUniforms(), "uniform", "Uniforms");
DeclareVariables(shader.GetInputs(), "in", "Inputs");
DeclareVariables(shader.GetOutputs(), "out", "Outputs");
std::size_t functionCount = shader.GetFunctionCount();
if (functionCount > 1)
{
AppendCommentSection("Prototypes");
for (const auto& func : shader.GetFunctions())
{
if (func.name != "main")
{
AppendFunctionPrototype(func);
AppendLine(";");
}
}
}
for (const auto& func : shader.GetFunctions())
AppendFunction(func);
return state.stream.str();
}
void GlslWriter::SetGlslVersion(unsigned int version)
@ -122,22 +84,127 @@ namespace Nz
m_glslVersion = version;
}
void GlslWriter::Visit(const ShaderAst::Sample2D& node)
void GlslWriter::Append(ShaderNodes::BuiltinEntry builtin)
{
Append("texture(");
Visit(node.sampler);
Append(", ");
Visit(node.coordinates);
Append(")");
switch (builtin)
{
case ShaderNodes::BuiltinEntry::VertexPosition:
Append("gl_Position");
break;
}
}
void GlslWriter::Visit(const ShaderAst::AssignOp& node)
void GlslWriter::Append(ShaderNodes::ExpressionType type)
{
switch (type)
{
case ShaderNodes::ExpressionType::Boolean:
Append("bool");
break;
case ShaderNodes::ExpressionType::Float1:
Append("float");
break;
case ShaderNodes::ExpressionType::Float2:
Append("vec2");
break;
case ShaderNodes::ExpressionType::Float3:
Append("vec3");
break;
case ShaderNodes::ExpressionType::Float4:
Append("vec4");
break;
case ShaderNodes::ExpressionType::Mat4x4:
Append("mat4");
break;
case ShaderNodes::ExpressionType::Sampler2D:
Append("sampler2D");
break;
case ShaderNodes::ExpressionType::Void:
Append("void");
break;
}
}
void GlslWriter::AppendCommentSection(const std::string& section)
{
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
String stars((section.size() < 33) ? (36 - section.size()) / 2 : 3, '*');
m_currentState->stream << "/*" << stars << ' ' << section << ' ' << stars << "*/";
AppendLine();
}
void GlslWriter::AppendFunction(const ShaderAst::Function& func)
{
NazaraAssert(!m_context.currentFunction, "A function is already being processed");
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
AppendFunctionPrototype(func);
m_context.currentFunction = &func;
CallOnExit onExit([this] ()
{
m_context.currentFunction = nullptr;
});
EnterScope();
{
Visit(func.statement);
}
LeaveScope();
}
void GlslWriter::AppendFunctionPrototype(const ShaderAst::Function& func)
{
Append(func.returnType);
Append(" ");
Append(func.name);
Append("(");
for (std::size_t i = 0; i < func.parameters.size(); ++i)
{
if (i != 0)
Append(", ");
Append(func.parameters[i].type);
Append(" ");
Append(func.parameters[i].name);
}
Append(")\n");
}
void GlslWriter::AppendLine(const std::string& txt)
{
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
m_currentState->stream << txt << '\n' << std::string(m_currentState->indentLevel, '\t');
}
void GlslWriter::EnterScope()
{
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
m_currentState->indentLevel++;
AppendLine("{");
}
void GlslWriter::LeaveScope()
{
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
m_currentState->indentLevel--;
AppendLine();
AppendLine("}");
}
void GlslWriter::Visit(const ShaderNodes::AssignOp& node)
{
Visit(node.left);
switch (node.op)
{
case ShaderAst::AssignType::Simple:
case ShaderNodes::AssignType::Simple:
Append(" = ");
break;
}
@ -145,7 +212,7 @@ namespace Nz
Visit(node.right);
}
void GlslWriter::Visit(const ShaderAst::Branch& node)
void GlslWriter::Visit(const ShaderNodes::Branch& node)
{
bool first = true;
for (const auto& statement : node.condStatements)
@ -174,45 +241,25 @@ namespace Nz
}
}
void GlslWriter::Visit(const ShaderAst::BinaryFunc& node)
{
switch (node.intrinsic)
{
case ShaderAst::BinaryIntrinsic::CrossProduct:
Append("cross");
break;
case ShaderAst::BinaryIntrinsic::DotProduct:
Append("dot");
break;
}
Append("(");
Visit(node.left);
Append(", ");
Visit(node.right);
Append(")");
}
void GlslWriter::Visit(const ShaderAst::BinaryOp& node)
void GlslWriter::Visit(const ShaderNodes::BinaryOp& node)
{
Visit(node.left);
switch (node.op)
{
case ShaderAst::BinaryType::Add:
case ShaderNodes::BinaryType::Add:
Append(" + ");
break;
case ShaderAst::BinaryType::Substract:
case ShaderNodes::BinaryType::Substract:
Append(" - ");
break;
case ShaderAst::BinaryType::Multiply:
case ShaderNodes::BinaryType::Multiply:
Append(" * ");
break;
case ShaderAst::BinaryType::Divide:
case ShaderNodes::BinaryType::Divide:
Append(" / ");
break;
case ShaderAst::BinaryType::Equality:
case ShaderNodes::BinaryType::Equality:
Append(" == ");
break;
}
@ -220,18 +267,18 @@ namespace Nz
Visit(node.right);
}
void GlslWriter::Visit(const ShaderAst::BuiltinVariable& node)
void GlslWriter::Visit(const ShaderNodes::BuiltinVariable& var)
{
Append(node.var);
Append(var.type);
}
void GlslWriter::Visit(const ShaderAst::Cast& node)
void GlslWriter::Visit(const ShaderNodes::Cast& node)
{
Append(node.exprType);
Append("(");
unsigned int i = 0;
unsigned int requiredComponents = ShaderAst::Node::GetComponentCount(node.exprType);
unsigned int requiredComponents = ShaderNodes::Node::GetComponentCount(node.exprType);
while (requiredComponents > 0)
{
if (i != 0)
@ -241,34 +288,34 @@ namespace Nz
NazaraAssert(exprPtr, "Invalid expression");
Visit(exprPtr);
requiredComponents -= ShaderAst::Node::GetComponentCount(exprPtr->GetExpressionType());
requiredComponents -= ShaderNodes::Node::GetComponentCount(exprPtr->GetExpressionType());
}
Append(")");
}
void GlslWriter::Visit(const ShaderAst::Constant& node)
void GlslWriter::Visit(const ShaderNodes::Constant& node)
{
switch (node.exprType)
{
case ShaderAst::ExpressionType::Boolean:
case ShaderNodes::ExpressionType::Boolean:
Append((node.values.bool1) ? "true" : "false");
break;
case ShaderAst::ExpressionType::Float1:
Append(String::Number(node.values.vec1));
case ShaderNodes::ExpressionType::Float1:
Append(std::to_string(node.values.vec1));
break;
case ShaderAst::ExpressionType::Float2:
Append("vec2(" + String::Number(node.values.vec2.x) + ", " + String::Number(node.values.vec2.y) + ")");
case ShaderNodes::ExpressionType::Float2:
Append("vec2(" + std::to_string(node.values.vec2.x) + ", " + std::to_string(node.values.vec2.y) + ")");
break;
case ShaderAst::ExpressionType::Float3:
Append("vec3(" + String::Number(node.values.vec3.x) + ", " + String::Number(node.values.vec3.y) + ", " + String::Number(node.values.vec3.z) + ")");
case ShaderNodes::ExpressionType::Float3:
Append("vec3(" + std::to_string(node.values.vec3.x) + ", " + std::to_string(node.values.vec3.y) + ", " + std::to_string(node.values.vec3.z) + ")");
break;
case ShaderAst::ExpressionType::Float4:
Append("vec4(" + String::Number(node.values.vec4.x) + ", " + String::Number(node.values.vec4.y) + ", " + String::Number(node.values.vec4.z) + ", " + String::Number(node.values.vec4.w) + ")");
case ShaderNodes::ExpressionType::Float4:
Append("vec4(" + std::to_string(node.values.vec4.x) + ", " + std::to_string(node.values.vec4.y) + ", " + std::to_string(node.values.vec4.z) + ", " + std::to_string(node.values.vec4.w) + ")");
break;
default:
@ -276,9 +323,9 @@ namespace Nz
}
}
void GlslWriter::Visit(const ShaderAst::DeclareVariable& node)
void GlslWriter::Visit(const ShaderNodes::DeclareVariable& node)
{
Append(node.variable->GetExpressionType());
Append(node.variable->type);
Append(" ");
Append(node.variable->name);
if (node.expression)
@ -292,21 +339,76 @@ namespace Nz
AppendLine(";");
}
void GlslWriter::Visit(const ShaderAst::ExpressionStatement& node)
void GlslWriter::Visit(const ShaderNodes::ExpressionStatement& node)
{
Visit(node.expression);
Append(";");
}
void GlslWriter::Visit(const ShaderAst::NamedVariable& node)
void GlslWriter::Visit(const ShaderNodes::Identifier& node)
{
Append(node.name);
Visit(node.var);
}
void GlslWriter::Visit(const ShaderAst::StatementBlock& node)
void GlslWriter::Visit(const ShaderNodes::InputVariable& var)
{
Append(var.name);
}
void GlslWriter::Visit(const ShaderNodes::IntrinsicCall& node)
{
switch (node.intrinsic)
{
case ShaderNodes::IntrinsicType::CrossProduct:
Append("cross");
break;
case ShaderNodes::IntrinsicType::DotProduct:
Append("dot");
break;
}
m_currentState->stream << '(';
for (std::size_t i = 0; i < node.parameters.size(); ++i)
{
if (i != 0)
m_currentState->stream << ", ";
Visit(node.parameters[i]);
m_currentState->stream << ' ';
Visit(node.parameters[i]);
}
m_currentState->stream << ")\n";
}
void GlslWriter::Visit(const ShaderNodes::LocalVariable& var)
{
Append(var.name);
}
void GlslWriter::Visit(const ShaderNodes::ParameterVariable& var)
{
Append(var.name);
}
void GlslWriter::Visit(const ShaderNodes::OutputVariable& var)
{
Append(var.name);
}
void GlslWriter::Visit(const ShaderNodes::Sample2D& node)
{
Append("texture(");
Visit(node.sampler);
Append(", ");
Visit(node.coordinates);
Append(")");
}
void GlslWriter::Visit(const ShaderNodes::StatementBlock& node)
{
bool first = true;
for (const ShaderAst::StatementPtr& statement : node.statements)
for (const ShaderNodes::StatementPtr& statement : node.statements)
{
if (!first)
AppendLine();
@ -317,7 +419,7 @@ namespace Nz
}
}
void GlslWriter::Visit(const ShaderAst::SwizzleOp& node)
void GlslWriter::Visit(const ShaderNodes::SwizzleOp& node)
{
Visit(node.expression);
Append(".");
@ -326,166 +428,55 @@ namespace Nz
{
switch (node.components[i])
{
case ShaderAst::SwizzleComponent::First:
case ShaderNodes::SwizzleComponent::First:
Append("x");
break;
case ShaderAst::SwizzleComponent::Second:
case ShaderNodes::SwizzleComponent::Second:
Append("y");
break;
case ShaderAst::SwizzleComponent::Third:
case ShaderNodes::SwizzleComponent::Third:
Append("z");
break;
case ShaderAst::SwizzleComponent::Fourth:
case ShaderNodes::SwizzleComponent::Fourth:
Append("w");
break;
}
}
}
void GlslWriter::Append(ShaderAst::BuiltinEntry builtin)
void GlslWriter::Visit(const ShaderNodes::UniformVariable& var)
{
switch (builtin)
Append(var.name);
}
bool GlslWriter::HasExplicitBinding(const ShaderAst& shader)
{
for (const auto& uniform : shader.GetUniforms())
{
case ShaderAst::BuiltinEntry::VertexPosition:
Append("gl_Position");
break;
if (uniform.bindingIndex.has_value())
return true;
}
return false;
}
void GlslWriter::Append(ShaderAst::ExpressionType type)
bool GlslWriter::HasExplicitLocation(const ShaderAst& shader)
{
switch (type)
for (const auto& input : shader.GetInputs())
{
case ShaderAst::ExpressionType::Boolean:
Append("bool");
break;
case ShaderAst::ExpressionType::Float1:
Append("float");
break;
case ShaderAst::ExpressionType::Float2:
Append("vec2");
break;
case ShaderAst::ExpressionType::Float3:
Append("vec3");
break;
case ShaderAst::ExpressionType::Float4:
Append("vec4");
break;
case ShaderAst::ExpressionType::Mat4x4:
Append("mat4");
break;
case ShaderAst::ExpressionType::Sampler2D:
Append("sampler2D");
break;
case ShaderAst::ExpressionType::Void:
Append("void");
break;
if (input.locationIndex.has_value())
return true;
}
}
void GlslWriter::Append(const String& txt)
{
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
m_currentState->stream << txt;
}
void GlslWriter::AppendCommentSection(const String& section)
{
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
String stars((section.GetSize() < 33) ? (36 - section.GetSize()) / 2 : 3, '*');
m_currentState->stream << "/*" << stars << ' ' << section << ' ' << stars << "*/";
AppendLine();
}
void GlslWriter::AppendFunction(Function& func)
{
NazaraAssert(!m_currentFunction, "A function is already being processed");
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
m_currentFunction = &func;
CallOnExit onExit([this] ()
for (const auto& output : shader.GetOutputs())
{
m_currentFunction = nullptr;
});
func.node->Register(*this);
Append(func.retType);
m_currentState->stream << ' ';
Append(func.name);
m_currentState->stream << '(';
for (std::size_t i = 0; i < func.parameters.size(); ++i)
{
if (i != 0)
m_currentState->stream << ", ";
Append(func.parameters[i]->type);
m_currentState->stream << ' ';
Append(func.parameters[i]->name);
if (output.locationIndex.has_value())
return true;
}
m_currentState->stream << ")\n";
EnterScope();
{
Visit(func.node);
}
LeaveScope();
return false;
}
void GlslWriter::AppendLine(const String& txt)
{
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
m_currentState->stream << txt << '\n' << String(m_currentState->indentLevel, '\t');
}
void GlslWriter::DeclareVariables(const VariableContainer& variables, const String& keyword, const String& section)
{
if (!variables.empty())
{
if (!section.IsEmpty())
AppendCommentSection(section);
for (const auto& pair : variables)
{
if (!keyword.IsEmpty())
{
Append(keyword);
Append(" ");
}
Append(pair.first);
Append(" ");
Append(pair.second);
AppendLine(";");
}
AppendLine();
}
}
void GlslWriter::EnterScope()
{
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
m_currentState->indentLevel++;
AppendLine("{");
}
void GlslWriter::LeaveScope()
{
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
m_currentState->indentLevel--;
AppendLine();
AppendLine("}");
}
}

View File

@ -3,275 +3,40 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/ShaderAst.hpp>
#include <Nazara/Core/ByteStream.hpp>
#include <Nazara/Renderer/ShaderSerializer.hpp>
#include <Nazara/Renderer/ShaderWriter.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz::ShaderAst
namespace Nz
{
Node::~Node() = default;
ExpressionCategory Expression::GetExpressionCategory() const
void ShaderAst::AddFunction(std::string name, ShaderNodes::StatementPtr statement, std::vector<FunctionParameter> parameters, ShaderNodes::ExpressionType returnType)
{
return ExpressionCategory::RValue;
auto& functionEntry = m_functions.emplace_back();
functionEntry.name = std::move(name);
functionEntry.parameters = std::move(parameters);
functionEntry.returnType = returnType;
functionEntry.statement = std::move(statement);
}
void ExpressionStatement::Register(ShaderWriter& visitor)
void ShaderAst::AddInput(std::string name, ShaderNodes::ExpressionType type, std::optional<std::size_t> locationIndex)
{
expression->Register(visitor);
auto& inputEntry = m_inputs.emplace_back();
inputEntry.name = std::move(name);
inputEntry.locationIndex = std::move(locationIndex);
inputEntry.type = type;
}
void ExpressionStatement::Visit(ShaderVisitor& visitor)
void ShaderAst::AddOutput(std::string name, ShaderNodes::ExpressionType type, std::optional<std::size_t> locationIndex)
{
visitor.Visit(*this);
auto& outputEntry = m_outputs.emplace_back();
outputEntry.name = std::move(name);
outputEntry.locationIndex = std::move(locationIndex);
outputEntry.type = type;
}
void ConditionalStatement::Register(ShaderWriter& visitor)
void ShaderAst::AddUniform(std::string name, ShaderNodes::ExpressionType type, std::optional<std::size_t> bindingIndex)
{
if (visitor.IsConditionEnabled(conditionName))
statement->Register(visitor);
}
void ConditionalStatement::Visit(ShaderVisitor& visitor)
{
if (visitor.IsConditionEnabled(conditionName))
statement->Visit(visitor);
}
void StatementBlock::Register(ShaderWriter& visitor)
{
for (auto& statementPtr : statements)
statementPtr->Register(visitor);
}
void StatementBlock::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionCategory Variable::GetExpressionCategory() const
{
return ExpressionCategory::LValue;
}
ExpressionType Variable::GetExpressionType() const
{
return type;
}
void BuiltinVariable::Register(ShaderWriter& /*visitor*/)
{
}
void BuiltinVariable::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
void NamedVariable::Register(ShaderWriter& visitor)
{
visitor.RegisterVariable(kind, name, type);
}
void NamedVariable::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
void DeclareVariable::Register(ShaderWriter& visitor)
{
variable->Register(visitor);
if (expression)
expression->Register(visitor);
}
void DeclareVariable::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType AssignOp::GetExpressionType() const
{
return left->GetExpressionType();
}
void AssignOp::Register(ShaderWriter& visitor)
{
left->Register(visitor);
right->Register(visitor);
}
void AssignOp::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType BinaryOp::GetExpressionType() const
{
ShaderAst::ExpressionType exprType = ShaderAst::ExpressionType::Void;
switch (op)
{
case ShaderAst::BinaryType::Add:
case ShaderAst::BinaryType::Substract:
exprType = left->GetExpressionType();
break;
case ShaderAst::BinaryType::Divide:
case ShaderAst::BinaryType::Multiply:
//FIXME
exprType = static_cast<ExpressionType>(std::max(UnderlyingCast(left->GetExpressionType()), UnderlyingCast(right->GetExpressionType())));
break;
case ShaderAst::BinaryType::Equality:
exprType = ExpressionType::Boolean;
break;
}
NazaraAssert(exprType != ShaderAst::ExpressionType::Void, "Unhandled builtin");
return exprType;
}
void BinaryOp::Register(ShaderWriter& visitor)
{
left->Register(visitor);
right->Register(visitor);
}
void BinaryOp::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
void Branch::Register(ShaderWriter& visitor)
{
for (ConditionalStatement& statement : condStatements)
{
statement.condition->Register(visitor);
statement.statement->Register(visitor);
}
if (elseStatement)
elseStatement->Register(visitor);
}
void Branch::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType Constant::GetExpressionType() const
{
return exprType;
}
void Constant::Register(ShaderWriter&)
{
}
void Constant::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType Cast::GetExpressionType() const
{
return exprType;
}
void Cast::Register(ShaderWriter& visitor)
{
auto it = expressions.begin();
(*it)->Register(visitor);
for (; it != expressions.end(); ++it)
{
if (!*it)
break;
(*it)->Register(visitor);
}
}
void Cast::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionCategory SwizzleOp::GetExpressionCategory() const
{
return ExpressionCategory::LValue;
}
ExpressionType SwizzleOp::GetExpressionType() const
{
return static_cast<ExpressionType>(UnderlyingCast(GetComponentType(expression->GetExpressionType())) + componentCount - 1);
}
void SwizzleOp::Register(ShaderWriter& visitor)
{
expression->Register(visitor);
}
void SwizzleOp::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType Sample2D::GetExpressionType() const
{
return ExpressionType::Float4;
}
void Sample2D::Register(ShaderWriter& visitor)
{
sampler->Register(visitor);
coordinates->Register(visitor);
}
void Sample2D::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType BinaryFunc::GetExpressionType() const
{
switch (intrinsic)
{
case BinaryIntrinsic::CrossProduct:
return left->GetExpressionType();
case BinaryIntrinsic::DotProduct:
return ExpressionType::Float1;
}
NazaraAssert(false, "Unhandled builtin");
return ExpressionType::Void;
}
void BinaryFunc::Register(ShaderWriter& visitor)
{
left->Register(visitor);
right->Register(visitor);
}
void BinaryFunc::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
auto& uniformEntry = m_uniforms.emplace_back();
uniformEntry.bindingIndex = std::move(bindingIndex);
uniformEntry.name = std::move(name);
uniformEntry.type = type;
}
}

View File

@ -0,0 +1,179 @@
// 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/ShaderNodes.hpp>
#include <Nazara/Renderer/ShaderSerializer.hpp>
#include <Nazara/Renderer/ShaderVisitor.hpp>
#include <Nazara/Renderer/ShaderWriter.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz::ShaderNodes
{
Node::~Node() = default;
ExpressionCategory Expression::GetExpressionCategory() const
{
return ExpressionCategory::RValue;
}
void ExpressionStatement::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
void ConditionalStatement::Visit(ShaderVisitor& visitor)
{
if (visitor.IsConditionEnabled(conditionName))
statement->Visit(visitor);
}
void StatementBlock::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
void DeclareVariable::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionCategory Identifier::GetExpressionCategory() const
{
return ExpressionCategory::LValue;
}
ExpressionType Identifier::GetExpressionType() const
{
assert(var);
return var->type;
}
void Identifier::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType AssignOp::GetExpressionType() const
{
return left->GetExpressionType();
}
void AssignOp::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType BinaryOp::GetExpressionType() const
{
ShaderNodes::ExpressionType exprType = ShaderNodes::ExpressionType::Void;
switch (op)
{
case ShaderNodes::BinaryType::Add:
case ShaderNodes::BinaryType::Substract:
exprType = left->GetExpressionType();
break;
case ShaderNodes::BinaryType::Divide:
case ShaderNodes::BinaryType::Multiply:
//FIXME
exprType = static_cast<ExpressionType>(std::max(UnderlyingCast(left->GetExpressionType()), UnderlyingCast(right->GetExpressionType())));
break;
case ShaderNodes::BinaryType::Equality:
exprType = ExpressionType::Boolean;
break;
}
NazaraAssert(exprType != ShaderNodes::ExpressionType::Void, "Unhandled builtin");
return exprType;
}
void BinaryOp::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
void Branch::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType Constant::GetExpressionType() const
{
return exprType;
}
void Constant::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType Cast::GetExpressionType() const
{
return exprType;
}
void Cast::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionCategory SwizzleOp::GetExpressionCategory() const
{
return ExpressionCategory::LValue;
}
ExpressionType SwizzleOp::GetExpressionType() const
{
return static_cast<ExpressionType>(UnderlyingCast(GetComponentType(expression->GetExpressionType())) + componentCount - 1);
}
void SwizzleOp::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType Sample2D::GetExpressionType() const
{
return ExpressionType::Float4;
}
void Sample2D::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
ExpressionType IntrinsicCall::GetExpressionType() const
{
switch (intrinsic)
{
case IntrinsicType::CrossProduct:
return parameters.front()->GetExpressionType();
case IntrinsicType::DotProduct:
return ExpressionType::Float1;
}
NazaraAssert(false, "Unhandled builtin");
return ExpressionType::Void;
}
void IntrinsicCall::Visit(ShaderVisitor& visitor)
{
visitor.Visit(*this);
}
}

View File

@ -3,13 +3,15 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/ShaderSerializer.hpp>
#include <Nazara/Renderer/ShaderVarVisitor.hpp>
#include <Nazara/Renderer/ShaderVisitor.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz::ShaderAst
namespace Nz::ShaderNodes
{
namespace
{
class ShaderSerializerVisitor : public ShaderVisitor
class ShaderSerializerVisitor : public ShaderVisitor, public ShaderVarVisitor
{
public:
ShaderSerializerVisitor(ShaderSerializerBase& serializer) :
@ -22,11 +24,6 @@ namespace Nz::ShaderAst
Serialize(node);
}
void Visit(const BinaryFunc& node) override
{
Serialize(node);
}
void Visit(const BinaryOp& node) override
{
Serialize(node);
@ -37,11 +34,6 @@ namespace Nz::ShaderAst
Serialize(node);
}
void Visit(const BuiltinVariable& node) override
{
Serialize(node);
}
void Visit(const Cast& node) override
{
Serialize(node);
@ -62,7 +54,12 @@ namespace Nz::ShaderAst
Serialize(node);
}
void Visit(const NamedVariable& node) override
void Visit(const Identifier& node) override
{
Serialize(node);
}
void Visit(const IntrinsicCall& node) override
{
Serialize(node);
}
@ -82,6 +79,37 @@ namespace Nz::ShaderAst
Serialize(node);
}
void Visit(const ShaderNodes::BuiltinVariable& var) override
{
Serialize(var);
}
void Visit(const ShaderNodes::InputVariable& var) override
{
Serialize(var);
}
void Visit(const ShaderNodes::LocalVariable& var) override
{
Serialize(var);
}
void Visit(const ShaderNodes::OutputVariable& var) override
{
Serialize(var);
}
void Visit(const ShaderNodes::ParameterVariable& var) override
{
Serialize(var);
}
void Visit(const ShaderNodes::UniformVariable& var) override
{
Serialize(var);
}
private:
template<typename T>
void Serialize(const T& node)
@ -101,13 +129,6 @@ namespace Nz::ShaderAst
Node(node.right);
}
void ShaderSerializerBase::Serialize(BinaryFunc& node)
{
Enum(node.intrinsic);
Node(node.left);
Node(node.right);
}
void ShaderSerializerBase::Serialize(BinaryOp& node)
{
Enum(node.op);
@ -129,7 +150,7 @@ namespace Nz::ShaderAst
void ShaderSerializerBase::Serialize(BuiltinVariable& node)
{
Enum(node.var);
Enum(node.type);
Enum(node.type);
}
@ -170,7 +191,7 @@ namespace Nz::ShaderAst
void ShaderSerializerBase::Serialize(DeclareVariable& node)
{
Node(node.variable);
Variable(node.variable);
Node(node.expression);
}
@ -179,10 +200,22 @@ namespace Nz::ShaderAst
Node(node.expression);
}
void ShaderSerializerBase::Serialize(Identifier& node)
{
Variable(node.var);
}
void ShaderSerializerBase::Serialize(IntrinsicCall& node)
{
Enum(node.intrinsic);
Container(node.parameters);
for (auto& param : node.parameters)
Node(param);
}
void ShaderSerializerBase::Serialize(NamedVariable& node)
{
Value(node.name);
Enum(node.kind);
Enum(node.type);
}
@ -272,6 +305,18 @@ namespace Nz::ShaderAst
m_stream << val;
}
void ShaderSerializer::Variable(VariablePtr& var)
{
VariableType nodeType = (var) ? var->GetType() : VariableType::None;
m_stream << static_cast<Int32>(nodeType);
if (var)
{
ShaderSerializerVisitor visitor(*this);
var->Visit(visitor);
}
}
ByteArray Serialize(const StatementPtr& shader)
{
ByteArray byteArray;
@ -309,27 +354,26 @@ namespace Nz::ShaderAst
NodeType nodeType = static_cast<NodeType>(nodeTypeInt);
#define HandleNodeType(Type) case NodeType:: Type : node = std::make_shared<Type>(); break
#define HandleType(Type) case NodeType:: Type : node = std::make_shared<Type>(); break
switch (nodeType)
{
case NodeType::None: break;
HandleNodeType(AssignOp);
HandleNodeType(BinaryFunc);
HandleNodeType(BinaryOp);
HandleNodeType(Branch);
HandleNodeType(BuiltinVariable);
HandleNodeType(Cast);
HandleNodeType(Constant);
HandleNodeType(ConditionalStatement);
HandleNodeType(DeclareVariable);
HandleNodeType(ExpressionStatement);
HandleNodeType(NamedVariable);
HandleNodeType(Sample2D);
HandleNodeType(SwizzleOp);
HandleNodeType(StatementBlock);
HandleType(AssignOp);
HandleType(BinaryOp);
HandleType(Branch);
HandleType(Cast);
HandleType(Constant);
HandleType(ConditionalStatement);
HandleType(DeclareVariable);
HandleType(ExpressionStatement);
HandleType(Identifier);
HandleType(IntrinsicCall);
HandleType(Sample2D);
HandleType(SwizzleOp);
HandleType(StatementBlock);
}
#undef HandleNodeType
#undef HandleType
if (node)
{
@ -372,5 +416,32 @@ namespace Nz::ShaderAst
{
m_stream >> val;
}
void ShaderUnserializer::Variable(VariablePtr& var)
{
Int32 nodeTypeInt;
m_stream >> nodeTypeInt;
VariableType nodeType = static_cast<VariableType>(nodeTypeInt);
#define HandleType(Type) case VariableType:: Type : var = std::make_shared<Type>(); break
switch (nodeType)
{
case VariableType::None: break;
HandleType(BuiltinVariable);
HandleType(InputVariable);
HandleType(LocalVariable);
HandleType(OutputVariable);
HandleType(UniformVariable);
}
#undef HandleType
if (var)
{
ShaderSerializerVisitor visitor(*this);
var->Visit(visitor);
}
}
}

View File

@ -3,20 +3,49 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/ShaderValidator.hpp>
#include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Renderer/ShaderAst.hpp>
#include <Nazara/Renderer/ShaderVariables.hpp>
#include <vector>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz::ShaderAst
namespace Nz
{
struct AstError
{
std::string errMsg;
};
bool ShaderValidator::Validate(const StatementPtr& shader, std::string* error)
struct ShaderValidator::Context
{
struct Local
{
std::string name;
ShaderNodes::ExpressionType type;
};
const ShaderAst::Function* currentFunction;
std::vector<Local> declaredLocals;
std::vector<std::size_t> blockLocalIndex;
};
bool ShaderValidator::Validate(std::string* error)
{
try
{
shader->Visit(*this);
for (std::size_t i = 0; i < m_shader.GetFunctionCount(); ++i)
{
const auto& func = m_shader.GetFunction(i);
Context currentContext;
currentContext.currentFunction = &func;
m_context = &currentContext;
CallOnExit resetContext([&] { m_context = nullptr; });
func.statement->Visit(*this);
}
return true;
}
catch (const AstError& e)
@ -28,14 +57,14 @@ namespace Nz::ShaderAst
}
}
const ExpressionPtr& ShaderValidator::MandatoryExpr(const ExpressionPtr& node)
const ShaderNodes::ExpressionPtr& ShaderValidator::MandatoryExpr(const ShaderNodes::ExpressionPtr& node)
{
MandatoryNode(node);
return node;
}
const NodePtr& ShaderValidator::MandatoryNode(const NodePtr& node)
const ShaderNodes::NodePtr& ShaderValidator::MandatoryNode(const ShaderNodes::NodePtr& node)
{
if (!node)
throw AstError{ "Invalid node" };
@ -43,90 +72,76 @@ namespace Nz::ShaderAst
return node;
}
void ShaderValidator::TypeMustMatch(const ExpressionPtr& left, const ExpressionPtr& right)
void ShaderValidator::TypeMustMatch(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right)
{
if (left->GetExpressionType() != right->GetExpressionType())
return TypeMustMatch(left->GetExpressionType(), right->GetExpressionType());
}
void ShaderValidator::TypeMustMatch(ShaderNodes::ExpressionType left, ShaderNodes::ExpressionType right)
{
if (left != right)
throw AstError{ "Left expression type must match right expression type" };
}
void ShaderValidator::Visit(const AssignOp& node)
void ShaderValidator::Visit(const ShaderNodes::AssignOp& node)
{
MandatoryNode(node.left);
MandatoryNode(node.right);
TypeMustMatch(node.left, node.right);
Visit(node.left);
Visit(node.right);
}
void ShaderValidator::Visit(const BinaryFunc& node)
{
MandatoryNode(node.left);
MandatoryNode(node.right);
TypeMustMatch(node.left, node.right);
switch (node.intrinsic)
{
case BinaryIntrinsic::CrossProduct:
{
if (node.left->GetExpressionType() != ExpressionType::Float3)
throw AstError{ "CrossProduct only works with Float3 expressions" };
}
case BinaryIntrinsic::DotProduct:
break;
}
if (node.left->GetExpressionCategory() != ShaderNodes::ExpressionCategory::LValue)
throw AstError { "Assignation is only possible with a l-value" };
Visit(node.left);
Visit(node.right);
}
void ShaderValidator::Visit(const BinaryOp& node)
void ShaderValidator::Visit(const ShaderNodes::BinaryOp& node)
{
MandatoryNode(node.left);
MandatoryNode(node.right);
ExpressionType leftType = node.left->GetExpressionType();
ExpressionType rightType = node.right->GetExpressionType();
ShaderNodes::ExpressionType leftType = node.left->GetExpressionType();
ShaderNodes::ExpressionType rightType = node.right->GetExpressionType();
switch (node.op)
{
case BinaryType::Add:
case BinaryType::Equality:
case BinaryType::Substract:
case ShaderNodes::BinaryType::Add:
case ShaderNodes::BinaryType::Equality:
case ShaderNodes::BinaryType::Substract:
TypeMustMatch(node.left, node.right);
break;
case BinaryType::Multiply:
case BinaryType::Divide:
case ShaderNodes::BinaryType::Multiply:
case ShaderNodes::BinaryType::Divide:
{
switch (leftType)
{
case ExpressionType::Float1:
case ShaderNodes::ExpressionType::Float1:
{
if (Node::GetComponentType(rightType) != ExpressionType::Float1)
if (ShaderNodes::Node::GetComponentType(rightType) != ShaderNodes::ExpressionType::Float1)
throw AstError{ "Left expression type is not compatible with right expression type" };
break;
}
case ExpressionType::Float2:
case ExpressionType::Float3:
case ExpressionType::Float4:
case ShaderNodes::ExpressionType::Float2:
case ShaderNodes::ExpressionType::Float3:
case ShaderNodes::ExpressionType::Float4:
{
if (leftType != rightType && rightType != ExpressionType::Float1)
if (leftType != rightType && rightType != ShaderNodes::ExpressionType::Float1)
throw AstError{ "Left expression type is not compatible with right expression type" };
break;
}
case ExpressionType::Mat4x4:
case ShaderNodes::ExpressionType::Mat4x4:
{
switch (rightType)
{
case ExpressionType::Float1:
case ExpressionType::Float4:
case ExpressionType::Mat4x4:
case ShaderNodes::ExpressionType::Float1:
case ShaderNodes::ExpressionType::Float4:
case ShaderNodes::ExpressionType::Mat4x4:
break;
default:
@ -146,7 +161,7 @@ namespace Nz::ShaderAst
Visit(node.right);
}
void ShaderValidator::Visit(const Branch& node)
void ShaderValidator::Visit(const ShaderNodes::Branch& node)
{
for (const auto& condStatement : node.condStatements)
{
@ -155,11 +170,7 @@ namespace Nz::ShaderAst
}
}
void ShaderValidator::Visit(const BuiltinVariable& /*node*/)
{
}
void ShaderValidator::Visit(const Cast& node)
void ShaderValidator::Visit(const ShaderNodes::Cast& node)
{
unsigned int componentCount = 0;
unsigned int requiredComponents = node.GetComponentCount(node.exprType);
@ -176,55 +187,203 @@ namespace Nz::ShaderAst
throw AstError{ "Component count doesn't match required component count" };
}
void ShaderValidator::Visit(const Constant& /*node*/)
void ShaderValidator::Visit(const ShaderNodes::Constant& /*node*/)
{
}
void ShaderValidator::Visit(const DeclareVariable& node)
void ShaderValidator::Visit(const ShaderNodes::DeclareVariable& node)
{
assert(m_context);
if (node.expression)
Visit(node.expression);
auto& local = m_context->declaredLocals.emplace_back();
local.name = node.variable->name;
local.type = node.variable->type;
}
void ShaderValidator::Visit(const ShaderNodes::ExpressionStatement& node)
{
Visit(MandatoryNode(node.expression));
}
void ShaderValidator::Visit(const ExpressionStatement& node)
void ShaderValidator::Visit(const ShaderNodes::Identifier& node)
{
Visit(MandatoryNode(node.expression));
assert(m_context);
if (!node.var)
throw AstError{ "Invalid variable" };
//< FIXME: Use variable visitor
switch (node.var->GetType())
{
case ShaderNodes::VariableType::BuiltinVariable:
break;
case ShaderNodes::VariableType::InputVariable:
{
auto& namedVar = static_cast<ShaderNodes::InputVariable&>(*node.var);
for (std::size_t i = 0; i < m_shader.GetInputCount(); ++i)
{
const auto& input = m_shader.GetInput(i);
if (input.name == namedVar.name)
{
TypeMustMatch(input.type, namedVar.type);
return;
}
}
throw AstError{ "Input not found" };
}
case ShaderNodes::VariableType::LocalVariable:
{
auto& localVar = static_cast<ShaderNodes::LocalVariable&>(*node.var);
const auto& vars = m_context->declaredLocals;
auto it = std::find_if(vars.begin(), vars.end(), [&](const auto& var) { return var.name == localVar.name; });
if (it == vars.end())
throw AstError{ "Local variable not found in this block" };
TypeMustMatch(it->type, localVar.type);
break;
}
case ShaderNodes::VariableType::OutputVariable:
{
auto& outputVar = static_cast<ShaderNodes::OutputVariable&>(*node.var);
for (std::size_t i = 0; i < m_shader.GetOutputCount(); ++i)
{
const auto& input = m_shader.GetOutput(i);
if (input.name == outputVar.name)
{
TypeMustMatch(input.type, outputVar.type);
return;
}
}
throw AstError{ "Output not found" };
}
case ShaderNodes::VariableType::ParameterVariable:
{
assert(m_context->currentFunction);
auto& parameter = static_cast<ShaderNodes::ParameterVariable&>(*node.var);
const auto& parameters = m_context->currentFunction->parameters;
auto it = std::find_if(parameters.begin(), parameters.end(), [&](const auto& parameter) { return parameter.name == parameter.name; });
if (it == parameters.end())
throw AstError{ "Parameter not found in function" };
TypeMustMatch(it->type, parameter.type);
break;
}
case ShaderNodes::VariableType::UniformVariable:
{
auto& uniformVar = static_cast<ShaderNodes::UniformVariable&>(*node.var);
for (std::size_t i = 0; i < m_shader.GetUniformCount(); ++i)
{
const auto& uniform = m_shader.GetUniform(i);
if (uniform.name == uniformVar.name)
{
TypeMustMatch(uniform.type, uniformVar.type);
return;
}
}
throw AstError{ "Uniform not found" };
}
default:
break;
}
}
void ShaderValidator::Visit(const NamedVariable& node)
void ShaderValidator::Visit(const ShaderNodes::IntrinsicCall& node)
{
if (node.name.empty())
throw AstError{ "Variable has empty name" };
switch (node.intrinsic)
{
case ShaderNodes::IntrinsicType::CrossProduct:
case ShaderNodes::IntrinsicType::DotProduct:
{
if (node.parameters.size() != 2)
throw AstError { "Expected 2 parameters" };
for (auto& param : node.parameters)
MandatoryNode(param);
ShaderNodes::ExpressionType type = node.parameters.front()->GetExpressionType();
for (std::size_t i = 1; i < node.parameters.size(); ++i)
{
if (type != node.parameters[i]->GetExpressionType())
throw AstError{ "All type must match" };
}
break;
}
}
switch (node.intrinsic)
{
case ShaderNodes::IntrinsicType::CrossProduct:
{
if (node.parameters[0]->GetExpressionType() != ShaderNodes::ExpressionType::Float3)
throw AstError{ "CrossProduct only works with Float3 expressions" };
break;
}
case ShaderNodes::IntrinsicType::DotProduct:
break;
}
for (auto& param : node.parameters)
Visit(param);
}
void ShaderValidator::Visit(const Sample2D& node)
void ShaderValidator::Visit(const ShaderNodes::Sample2D& node)
{
if (MandatoryExpr(node.sampler)->GetExpressionType() != ExpressionType::Sampler2D)
if (MandatoryExpr(node.sampler)->GetExpressionType() != ShaderNodes::ExpressionType::Sampler2D)
throw AstError{ "Sampler must be a Sampler2D" };
if (MandatoryExpr(node.coordinates)->GetExpressionType() != ExpressionType::Float2)
if (MandatoryExpr(node.coordinates)->GetExpressionType() != ShaderNodes::ExpressionType::Float2)
throw AstError{ "Coordinates must be a Float2" };
Visit(node.sampler);
Visit(node.coordinates);
}
void ShaderValidator::Visit(const StatementBlock& node)
void ShaderValidator::Visit(const ShaderNodes::StatementBlock& node)
{
assert(m_context);
m_context->blockLocalIndex.push_back(m_context->declaredLocals.size());
for (const auto& statement : node.statements)
Visit(MandatoryNode(statement));
assert(m_context->declaredLocals.size() >= m_context->blockLocalIndex.back());
m_context->declaredLocals.resize(m_context->blockLocalIndex.back());
m_context->blockLocalIndex.pop_back();
}
void ShaderValidator::Visit(const SwizzleOp& node)
void ShaderValidator::Visit(const ShaderNodes::SwizzleOp& node)
{
if (node.componentCount > 4)
throw AstError{ "Cannot swizzle more than four elements" };
switch (MandatoryExpr(node.expression)->GetExpressionType())
{
case ExpressionType::Float1:
case ExpressionType::Float2:
case ExpressionType::Float3:
case ExpressionType::Float4:
case ShaderNodes::ExpressionType::Float1:
case ShaderNodes::ExpressionType::Float2:
case ShaderNodes::ExpressionType::Float3:
case ShaderNodes::ExpressionType::Float4:
break;
default:
@ -234,9 +393,9 @@ namespace Nz::ShaderAst
Visit(node.expression);
}
bool Validate(const StatementPtr& shader, std::string* error)
bool ValidateShader(const ShaderAst& shader, std::string* error)
{
ShaderValidator validator;
return validator.Validate(shader, error);
ShaderValidator validator(shader);
return validator.Validate(error);
}
}

View File

@ -0,0 +1,16 @@
// 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/ShaderVarVisitor.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz
{
ShaderVarVisitor::~ShaderVarVisitor() = default;
void ShaderVarVisitor::Visit(const ShaderNodes::VariablePtr& node)
{
node->Visit(*this);
}
}

View File

@ -0,0 +1,77 @@
// 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/ShaderVariables.hpp>
#include <Nazara/Renderer/ShaderVarVisitor.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz::ShaderNodes
{
ShaderNodes::Variable::~Variable() = default;
VariableType BuiltinVariable::GetType() const
{
return VariableType::BuiltinVariable;
}
void BuiltinVariable::Visit(ShaderVarVisitor& visitor)
{
visitor.Visit(*this);
}
VariableType InputVariable::GetType() const
{
return VariableType::InputVariable;
}
void InputVariable::Visit(ShaderVarVisitor& visitor)
{
visitor.Visit(*this);
}
VariableType LocalVariable::GetType() const
{
return VariableType::LocalVariable;
}
void LocalVariable::Visit(ShaderVarVisitor& visitor)
{
visitor.Visit(*this);
}
VariableType OutputVariable::GetType() const
{
return VariableType::OutputVariable;
}
void OutputVariable::Visit(ShaderVarVisitor& visitor)
{
visitor.Visit(*this);
}
VariableType ParameterVariable::GetType() const
{
return VariableType::ParameterVariable;
}
void ParameterVariable::Visit(ShaderVarVisitor& visitor)
{
visitor.Visit(*this);
}
VariableType UniformVariable::GetType() const
{
return VariableType::UniformVariable;
}
void UniformVariable::Visit(ShaderVarVisitor& visitor)
{
visitor.Visit(*this);
}
}

View File

@ -9,7 +9,7 @@ namespace Nz
{
ShaderVisitor::~ShaderVisitor() = default;
void ShaderVisitor::EnableCondition(const String& name, bool cond)
void ShaderVisitor::EnableCondition(const std::string& name, bool cond)
{
if (cond)
m_conditions.insert(name);
@ -17,12 +17,12 @@ namespace Nz
m_conditions.erase(name);
}
bool ShaderVisitor::IsConditionEnabled(const String& name) const
bool ShaderVisitor::IsConditionEnabled(const std::string& name) const
{
return m_conditions.count(name) != 0;
}
void ShaderVisitor::Visit(const ShaderAst::NodePtr& node)
void ShaderVisitor::Visit(const ShaderNodes::NodePtr& node)
{
node->Visit(*this);
}

View File

@ -7,4 +7,5 @@
namespace Nz
{
ShaderWriter::~ShaderWriter() = default;
}

View File

@ -19,7 +19,7 @@ class CastVec : public ShaderNode
void BuildNodeEdition(QFormLayout* layout) override;
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override;
QString caption() const override;
QString name() const override;

View File

@ -49,7 +49,7 @@ void CastVec<ToComponentCount>::BuildNodeEdition(QFormLayout* layout)
}
template<std::size_t ToComponentCount>
Nz::ShaderAst::ExpressionPtr CastVec<ToComponentCount>::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
Nz::ShaderNodes::ExpressionPtr CastVec<ToComponentCount>::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const
{
assert(m_input);
assert(count == 1);
@ -60,7 +60,7 @@ Nz::ShaderAst::ExpressionPtr CastVec<ToComponentCount>::GetExpression(Nz::Shader
{
std::size_t overflowComponentCount = ToComponentCount - fromComponentCount;
std::array<Nz::ShaderAst::ExpressionPtr, 4> expr;
std::array<Nz::ShaderNodes::ExpressionPtr, 4> expr;
expr[0] = expressions[0];
for (std::size_t i = 0; i < overflowComponentCount; ++i)
expr[i + 1] = Nz::ShaderBuilder::Constant(m_overflowComponents[i]);
@ -71,13 +71,13 @@ Nz::ShaderAst::ExpressionPtr CastVec<ToComponentCount>::GetExpression(Nz::Shader
}
else if (ToComponentCount < fromComponentCount)
{
std::array<Nz::ShaderAst::SwizzleComponent, ToComponentCount> swizzleComponents;
std::array<Nz::ShaderNodes::SwizzleComponent, ToComponentCount> swizzleComponents;
for (std::size_t i = 0; i < ToComponentCount; ++i)
swizzleComponents[i] = static_cast<Nz::ShaderAst::SwizzleComponent>(static_cast<std::size_t>(Nz::ShaderAst::SwizzleComponent::First) + i);
swizzleComponents[i] = static_cast<Nz::ShaderNodes::SwizzleComponent>(static_cast<std::size_t>(Nz::ShaderNodes::SwizzleComponent::First) + i);
return std::apply([&](auto... components)
{
std::initializer_list<Nz::ShaderAst::SwizzleComponent> componentList{ components... };
std::initializer_list<Nz::ShaderNodes::SwizzleComponent> componentList{ components... };
return Nz::ShaderBuilder::Swizzle(expressions[0], componentList);
}, swizzleComponents);
}

View File

@ -71,7 +71,7 @@ void FloatValue::BuildNodeEdition(QFormLayout* layout)
layout->addRow(tr("Value"), spinbox);
}
Nz::ShaderAst::ExpressionPtr FloatValue::GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const
Nz::ShaderNodes::ExpressionPtr FloatValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const
{
assert(count == 0);

View File

@ -28,7 +28,7 @@ class FloatValue : public ShaderNode
void BuildNodeEdition(QFormLayout* layout) override;
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override;
private:
bool ComputePreview(QPixmap& pixmap) override;

View File

@ -107,7 +107,7 @@ void InputValue::BuildNodeEdition(QFormLayout* layout)
layout->addRow(tr("Input"), inputSelection);
}
Nz::ShaderAst::ExpressionPtr InputValue::GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const
Nz::ShaderNodes::ExpressionPtr InputValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const
{
assert(count == 0);
@ -116,22 +116,22 @@ Nz::ShaderAst::ExpressionPtr InputValue::GetExpression(Nz::ShaderAst::Expression
const auto& inputEntry = GetGraph().GetInput(*m_currentInputIndex);
Nz::ShaderAst::ExpressionType expression = [&]
Nz::ShaderNodes::ExpressionType expression = [&]
{
switch (inputEntry.type)
{
case InOutType::Bool: return Nz::ShaderAst::ExpressionType::Boolean;
case InOutType::Float1: return Nz::ShaderAst::ExpressionType::Float1;
case InOutType::Float2: return Nz::ShaderAst::ExpressionType::Float2;
case InOutType::Float3: return Nz::ShaderAst::ExpressionType::Float3;
case InOutType::Float4: return Nz::ShaderAst::ExpressionType::Float4;
case InOutType::Bool: return Nz::ShaderNodes::ExpressionType::Boolean;
case InOutType::Float1: return Nz::ShaderNodes::ExpressionType::Float1;
case InOutType::Float2: return Nz::ShaderNodes::ExpressionType::Float2;
case InOutType::Float3: return Nz::ShaderNodes::ExpressionType::Float3;
case InOutType::Float4: return Nz::ShaderNodes::ExpressionType::Float4;
}
assert(false);
throw std::runtime_error("Unhandled input type");
}();
return Nz::ShaderBuilder::Input(inputEntry.name, expression);
return Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Input(inputEntry.name, expression));
}
auto InputValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType
@ -145,7 +145,7 @@ auto InputValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portInd
const auto& inputEntry = GetGraph().GetInput(*m_currentInputIndex);
switch (inputEntry.type)
{
//case InputType::Bool: return Nz::ShaderAst::ExpressionType::Boolean;
//case InputType::Bool: return Nz::ShaderNodes::ExpressionType::Boolean;
case InOutType::Float1:
return FloatData::Type();

View File

@ -19,7 +19,7 @@ class InputValue : public ShaderNode
void BuildNodeEdition(QFormLayout* layout) override;
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const override;
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const override;
QString caption() const override { return "Input"; }
QString name() const override { return "Input"; }

View File

@ -51,10 +51,10 @@ void OutputValue::BuildNodeEdition(QFormLayout* layout)
layout->addRow(tr("Output"), outputSelection);
}
Nz::ShaderAst::ExpressionPtr OutputValue::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
Nz::ShaderNodes::ExpressionPtr OutputValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const
{
using namespace Nz::ShaderAst;
using namespace Nz::ShaderBuilder;
using namespace Nz::ShaderNodes;
assert(count == 1);
@ -63,22 +63,22 @@ Nz::ShaderAst::ExpressionPtr OutputValue::GetExpression(Nz::ShaderAst::Expressio
const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex);
Nz::ShaderAst::ExpressionType expression = [&]
Nz::ShaderNodes::ExpressionType expression = [&]
{
switch (outputEntry.type)
{
case InOutType::Bool: return Nz::ShaderAst::ExpressionType::Boolean;
case InOutType::Float1: return Nz::ShaderAst::ExpressionType::Float1;
case InOutType::Float2: return Nz::ShaderAst::ExpressionType::Float2;
case InOutType::Float3: return Nz::ShaderAst::ExpressionType::Float3;
case InOutType::Float4: return Nz::ShaderAst::ExpressionType::Float4;
case InOutType::Bool: return Nz::ShaderNodes::ExpressionType::Boolean;
case InOutType::Float1: return Nz::ShaderNodes::ExpressionType::Float1;
case InOutType::Float2: return Nz::ShaderNodes::ExpressionType::Float2;
case InOutType::Float3: return Nz::ShaderNodes::ExpressionType::Float3;
case InOutType::Float4: return Nz::ShaderNodes::ExpressionType::Float4;
}
assert(false);
throw std::runtime_error("Unhandled output type");
}();
auto output = Nz::ShaderBuilder::Output(outputEntry.name, expression);
auto output = Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Output(outputEntry.name, expression));
return Nz::ShaderBuilder::Assign(std::move(output), *expressions);
}
@ -94,8 +94,8 @@ QtNodes::NodeDataType OutputValue::dataType(QtNodes::PortType portType, QtNodes:
const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex);
switch (outputEntry.type)
{
//case InOutType::Bool: return Nz::ShaderAst::ExpressionType::Boolean;
//case InOutType::Float1: return Nz::ShaderAst::ExpressionType::Float1;
//case InOutType::Bool: return Nz::ShaderNodes::ExpressionType::Boolean;
//case InOutType::Float1: return Nz::ShaderNodes::ExpressionType::Float1;
case InOutType::Float2:
case InOutType::Float3:
case InOutType::Float4:

View File

@ -16,7 +16,7 @@ class OutputValue : public ShaderNode
void BuildNodeEdition(QFormLayout* layout) override;
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override;
QString caption() const override { return "Output"; }
QString name() const override { return "Output"; }

View File

@ -91,7 +91,7 @@ bool SampleTexture::ComputePreview(QPixmap& pixmap)
return true;
}
Nz::ShaderAst::ExpressionPtr SampleTexture::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
Nz::ShaderNodes::ExpressionPtr SampleTexture::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const
{
assert(m_texture);
assert(m_uv);

View File

@ -17,7 +17,7 @@ class SampleTexture : public ShaderNode
SampleTexture(ShaderGraph& graph);
~SampleTexture() = default;
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const override;
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const override;
QString caption() const override { return "Sample texture"; }
QString name() const override { return "SampleTexture"; }

View File

@ -4,7 +4,7 @@
#define NAZARA_SHADERNODES_SHADERNODE_HPP
#include <Nazara/Math/Vector2.hpp>
#include <Nazara/Renderer/ShaderAst.hpp>
#include <Nazara/Renderer/ShaderNodes.hpp>
#include <nodes/NodeDataModel>
#include <QtGui/QPixmap>
#include <optional>
@ -23,7 +23,7 @@ class ShaderNode : public QtNodes::NodeDataModel
inline void DisablePreview();
void EnablePreview(bool enable = true);
virtual Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const = 0;
virtual Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const = 0;
inline ShaderGraph& GetGraph();
inline const ShaderGraph& GetGraph() const;
inline const std::string& GetVariableName() const;

View File

@ -106,7 +106,7 @@ void TextureValue::BuildNodeEdition(QFormLayout* layout)
layout->addRow(tr("Texture"), textureSelection);
}
Nz::ShaderAst::ExpressionPtr TextureValue::GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const
Nz::ShaderNodes::ExpressionPtr TextureValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const
{
if (!m_currentTextureIndex)
throw std::runtime_error("invalid texture input");
@ -115,18 +115,18 @@ Nz::ShaderAst::ExpressionPtr TextureValue::GetExpression(Nz::ShaderAst::Expressi
const auto& textureEntry = GetGraph().GetTexture(*m_currentTextureIndex);
Nz::ShaderAst::ExpressionType expression = [&]
Nz::ShaderNodes::ExpressionType expression = [&]
{
switch (textureEntry.type)
{
case TextureType::Sampler2D: return Nz::ShaderAst::ExpressionType::Sampler2D;
case TextureType::Sampler2D: return Nz::ShaderNodes::ExpressionType::Sampler2D;
}
assert(false);
throw std::runtime_error("Unhandled texture type");
}();
return Nz::ShaderBuilder::Uniform(textureEntry.name, expression);
return Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Uniform(textureEntry.name, expression));
}
auto TextureValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType

View File

@ -18,7 +18,7 @@ class TextureValue : public ShaderNode
void BuildNodeEdition(QFormLayout* layout) override;
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const override;
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const override;
QString caption() const override { return "Texture"; }
QString name() const override { return "Texture"; }

View File

@ -6,14 +6,14 @@
#include <ShaderNode/DataModels/ShaderNode.hpp>
#include <ShaderNode/DataTypes/VecData.hpp>
template<Nz::ShaderAst::BinaryType BinOp>
template<Nz::ShaderNodes::BinaryType BinOp>
class VecBinOp : public ShaderNode
{
public:
VecBinOp(ShaderGraph& graph);
~VecBinOp() = default;
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override;
unsigned int nPorts(QtNodes::PortType portType) const override;
@ -37,10 +37,10 @@ class VecBinOp : public ShaderNode
std::shared_ptr<VecData> m_output;
};
class VecAdd : public VecBinOp<Nz::ShaderAst::BinaryType::Add>
class VecAdd : public VecBinOp<Nz::ShaderNodes::BinaryType::Add>
{
public:
using VecBinOp<Nz::ShaderAst::BinaryType::Add>::VecBinOp;
using VecBinOp<Nz::ShaderNodes::BinaryType::Add>::VecBinOp;
QString caption() const override;
QString name() const override;
@ -48,10 +48,10 @@ class VecAdd : public VecBinOp<Nz::ShaderAst::BinaryType::Add>
void ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount) override;
};
class VecMul : public VecBinOp<Nz::ShaderAst::BinaryType::Multiply>
class VecMul : public VecBinOp<Nz::ShaderNodes::BinaryType::Multiply>
{
public:
using VecBinOp<Nz::ShaderAst::BinaryType::Multiply>::VecBinOp;
using VecBinOp<Nz::ShaderNodes::BinaryType::Multiply>::VecBinOp;
QString caption() const override;
QString name() const override;
@ -59,10 +59,10 @@ class VecMul : public VecBinOp<Nz::ShaderAst::BinaryType::Multiply>
void ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount) override;
};
class VecSub : public VecBinOp<Nz::ShaderAst::BinaryType::Substract>
class VecSub : public VecBinOp<Nz::ShaderNodes::BinaryType::Substract>
{
public:
using VecBinOp<Nz::ShaderAst::BinaryType::Substract>::VecBinOp;
using VecBinOp<Nz::ShaderNodes::BinaryType::Substract>::VecBinOp;
QString caption() const override;
QString name() const override;
@ -70,10 +70,10 @@ class VecSub : public VecBinOp<Nz::ShaderAst::BinaryType::Substract>
void ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount) override;
};
class VecDiv : public VecBinOp<Nz::ShaderAst::BinaryType::Divide>
class VecDiv : public VecBinOp<Nz::ShaderNodes::BinaryType::Divide>
{
public:
using VecBinOp<Nz::ShaderAst::BinaryType::Divide>::VecBinOp;
using VecBinOp<Nz::ShaderNodes::BinaryType::Divide>::VecBinOp;
QString caption() const override;
QString name() const override;

View File

@ -1,15 +1,15 @@
#include <ShaderNode/DataModels/VecBinOp.hpp>
#include <Nazara/Renderer/ShaderBuilder.hpp>
template<Nz::ShaderAst::BinaryType BinOp>
template<Nz::ShaderNodes::BinaryType BinOp>
VecBinOp<BinOp>::VecBinOp(ShaderGraph& graph) :
ShaderNode(graph)
{
UpdateOutput();
}
template<Nz::ShaderAst::BinaryType BinOp>
Nz::ShaderAst::ExpressionPtr VecBinOp<BinOp>::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
template<Nz::ShaderNodes::BinaryType BinOp>
Nz::ShaderNodes::ExpressionPtr VecBinOp<BinOp>::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const
{
assert(count == 2);
using BuilderType = typename Nz::ShaderBuilder::template BinOpBuilder<BinOp>;
@ -17,7 +17,7 @@ Nz::ShaderAst::ExpressionPtr VecBinOp<BinOp>::GetExpression(Nz::ShaderAst::Expre
return builder(expressions[0], expressions[1]);
}
template<Nz::ShaderAst::BinaryType BinOp>
template<Nz::ShaderNodes::BinaryType BinOp>
QtNodes::NodeDataType VecBinOp<BinOp>::dataType(QtNodes::PortType /*portType*/, QtNodes::PortIndex portIndex) const
{
assert(portIndex == 0 || portIndex == 1);
@ -25,7 +25,7 @@ QtNodes::NodeDataType VecBinOp<BinOp>::dataType(QtNodes::PortType /*portType*/,
return VecData::Type();
}
template<Nz::ShaderAst::BinaryType BinOp>
template<Nz::ShaderNodes::BinaryType BinOp>
unsigned int VecBinOp<BinOp>::nPorts(QtNodes::PortType portType) const
{
switch (portType)
@ -37,14 +37,14 @@ unsigned int VecBinOp<BinOp>::nPorts(QtNodes::PortType portType) const
return 0;
}
template<Nz::ShaderAst::BinaryType BinOp>
template<Nz::ShaderNodes::BinaryType BinOp>
std::shared_ptr<QtNodes::NodeData> VecBinOp<BinOp>::outData(QtNodes::PortIndex port)
{
assert(port == 0);
return m_output;
}
template<Nz::ShaderAst::BinaryType BinOp>
template<Nz::ShaderNodes::BinaryType BinOp>
void VecBinOp<BinOp>::setInData(std::shared_ptr<QtNodes::NodeData> value, int index)
{
assert(index == 0 || index == 1);
@ -65,7 +65,7 @@ void VecBinOp<BinOp>::setInData(std::shared_ptr<QtNodes::NodeData> value, int in
UpdateOutput();
}
template<Nz::ShaderAst::BinaryType BinOp>
template<Nz::ShaderNodes::BinaryType BinOp>
QtNodes::NodeValidationState VecBinOp<BinOp>::validationState() const
{
if (!m_lhs || !m_rhs)
@ -77,7 +77,7 @@ QtNodes::NodeValidationState VecBinOp<BinOp>::validationState() const
return QtNodes::NodeValidationState::Valid;
}
template<Nz::ShaderAst::BinaryType BinOp>
template<Nz::ShaderNodes::BinaryType BinOp>
QString VecBinOp<BinOp>::validationMessage() const
{
if (!m_lhs || !m_rhs)
@ -89,7 +89,7 @@ QString VecBinOp<BinOp>::validationMessage() const
return QString();
}
template<Nz::ShaderAst::BinaryType BinOp>
template<Nz::ShaderNodes::BinaryType BinOp>
bool VecBinOp<BinOp>::ComputePreview(QPixmap& pixmap)
{
if (!m_lhs || !m_rhs)
@ -99,7 +99,7 @@ bool VecBinOp<BinOp>::ComputePreview(QPixmap& pixmap)
return true;
}
template<Nz::ShaderAst::BinaryType BinOp>
template<Nz::ShaderNodes::BinaryType BinOp>
void VecBinOp<BinOp>::UpdateOutput()
{
if (validationState() != QtNodes::NodeValidationState::Valid)

View File

@ -1,5 +1,5 @@
#include <ShaderNode/DataModels/VecDot.hpp>
#include <Nazara/Renderer/ShaderAst.hpp>
#include <Nazara/Renderer/ShaderNodes.hpp>
VecDot::VecDot(ShaderGraph& graph) :
ShaderNode(graph)
@ -8,11 +8,11 @@ ShaderNode(graph)
UpdateOutput();
}
Nz::ShaderAst::ExpressionPtr VecDot::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
Nz::ShaderNodes::ExpressionPtr VecDot::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const
{
assert(count == 2);
using namespace Nz::ShaderAst;
return BinaryFunc::Build(BinaryIntrinsic::DotProduct, expressions[0], expressions[1]);
using namespace Nz::ShaderNodes;
return IntrinsicCall::Build(IntrinsicType::DotProduct, { expressions[0], expressions[1] });
}
QString VecDot::caption() const

View File

@ -13,7 +13,7 @@ class VecDot : public ShaderNode
VecDot(ShaderGraph& graph);
~VecDot() = default;
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override;
QString caption() const override;
QString name() const override;

View File

@ -1,5 +1,5 @@
#include <ShaderNode/DataModels/VecFloatMul.hpp>
#include <Nazara/Renderer/ShaderAst.hpp>
#include <Nazara/Renderer/ShaderNodes.hpp>
VecFloatMul::VecFloatMul(ShaderGraph& graph) :
ShaderNode(graph)
@ -7,10 +7,10 @@ ShaderNode(graph)
UpdateOutput();
}
Nz::ShaderAst::ExpressionPtr VecFloatMul::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
Nz::ShaderNodes::ExpressionPtr VecFloatMul::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const
{
assert(count == 2);
using namespace Nz::ShaderAst;
using namespace Nz::ShaderNodes;
return BinaryOp::Build(BinaryType::Multiply, expressions[0], expressions[1]);
}

View File

@ -13,7 +13,7 @@ class VecFloatMul : public ShaderNode
VecFloatMul(ShaderGraph& graph);
~VecFloatMul() = default;
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override;
QString caption() const override;
QString name() const override;

View File

@ -29,7 +29,7 @@ class VecValue : public ShaderNode
void BuildNodeEdition(QFormLayout* layout) override;
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
Nz::ShaderNodes::ExpressionPtr GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const override;
private:
bool ComputePreview(QPixmap& pixmap) override;

View File

@ -94,7 +94,7 @@ void VecValue<ComponentCount>::BuildNodeEdition(QFormLayout* layout)
}
template<std::size_t ComponentCount>
Nz::ShaderAst::ExpressionPtr VecValue<ComponentCount>::GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const
Nz::ShaderNodes::ExpressionPtr VecValue<ComponentCount>::GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const
{
assert(count == 0);

View File

@ -3,7 +3,7 @@
#ifndef NAZARA_SHADERNODES_TEXTUREDATA_HPP
#define NAZARA_SHADERNODES_TEXTUREDATA_HPP
#include <Nazara/Renderer/ShaderAst.hpp>
#include <Nazara/Renderer/ShaderNodes.hpp>
#include <nodes/NodeData>
#include <QtGui/QImage>

View File

@ -2,13 +2,13 @@
#include <cassert>
#include <stdexcept>
Nz::ShaderAst::ExpressionType VecData::GetExpressionType() const
Nz::ShaderNodes::ExpressionType VecData::GetExpressionType() const
{
switch (componentCount)
{
case 2: return Nz::ShaderAst::ExpressionType::Float2;
case 3: return Nz::ShaderAst::ExpressionType::Float3;
case 4: return Nz::ShaderAst::ExpressionType::Float4;
case 2: return Nz::ShaderNodes::ExpressionType::Float2;
case 3: return Nz::ShaderNodes::ExpressionType::Float3;
case 4: return Nz::ShaderNodes::ExpressionType::Float4;
default:
break;
}

View File

@ -3,7 +3,7 @@
#ifndef NAZARA_SHADERNODES_VECDATA_HPP
#define NAZARA_SHADERNODES_VECDATA_HPP
#include <Nazara/Renderer/ShaderAst.hpp>
#include <Nazara/Renderer/ShaderNodes.hpp>
#include <nodes/NodeData>
#include <QtGui/QImage>
@ -13,7 +13,7 @@ struct VecData : public QtNodes::NodeData
inline QtNodes::NodeDataType type() const override;
Nz::ShaderAst::ExpressionType GetExpressionType() const;
Nz::ShaderNodes::ExpressionType GetExpressionType() const;
static inline QtNodes::NodeDataType Type();
@ -27,28 +27,28 @@ struct VecExpressionTypeHelper;
template<>
struct VecExpressionTypeHelper<1>
{
static constexpr Nz::ShaderAst::ExpressionType ExpressionType = Nz::ShaderAst::ExpressionType::Float1;
static constexpr Nz::ShaderNodes::ExpressionType ExpressionType = Nz::ShaderNodes::ExpressionType::Float1;
};
template<>
struct VecExpressionTypeHelper<2>
{
static constexpr Nz::ShaderAst::ExpressionType ExpressionType = Nz::ShaderAst::ExpressionType::Float2;
static constexpr Nz::ShaderNodes::ExpressionType ExpressionType = Nz::ShaderNodes::ExpressionType::Float2;
};
template<>
struct VecExpressionTypeHelper<3>
{
static constexpr Nz::ShaderAst::ExpressionType ExpressionType = Nz::ShaderAst::ExpressionType::Float3;
static constexpr Nz::ShaderNodes::ExpressionType ExpressionType = Nz::ShaderNodes::ExpressionType::Float3;
};
template<>
struct VecExpressionTypeHelper<4>
{
static constexpr Nz::ShaderAst::ExpressionType ExpressionType = Nz::ShaderAst::ExpressionType::Float4;
static constexpr Nz::ShaderNodes::ExpressionType ExpressionType = Nz::ShaderNodes::ExpressionType::Float4;
};
template<std::size_t N> constexpr Nz::ShaderAst::ExpressionType VecExpressionType = VecExpressionTypeHelper<N>::template ExpressionType;
template<std::size_t N> constexpr Nz::ShaderNodes::ExpressionType VecExpressionType = VecExpressionTypeHelper<N>::template ExpressionType;
struct VecTypeDummy {};

View File

@ -46,9 +46,9 @@ m_flowScene(BuildRegistry())
});
// Test
AddInput("UV", InOutType::Float2, InputRole::TexCoord, 0);
AddOutput("RenderTarget0", InOutType::Float4);
AddTexture("Potato", TextureType::Sampler2D);
AddInput("UV", InOutType::Float2, InputRole::TexCoord, 0, 0);
AddOutput("RenderTarget0", InOutType::Float4, 0);
AddTexture("Potato", TextureType::Sampler2D, 1);
UpdateTexturePreview(0, QImage(R"(C:\Users\Lynix\Pictures\potatavril.png)"));
@ -79,10 +79,11 @@ ShaderGraph::~ShaderGraph()
m_flowScene.clearScene();
}
std::size_t ShaderGraph::AddInput(std::string name, InOutType type, InputRole role, std::size_t roleIndex)
std::size_t ShaderGraph::AddInput(std::string name, InOutType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex)
{
std::size_t index = m_inputs.size();
auto& inputEntry = m_inputs.emplace_back();
inputEntry.locationIndex = locationIndex;
inputEntry.name = std::move(name);
inputEntry.role = role;
inputEntry.roleIndex = roleIndex;
@ -93,10 +94,11 @@ std::size_t ShaderGraph::AddInput(std::string name, InOutType type, InputRole ro
return index;
}
std::size_t ShaderGraph::AddOutput(std::string name, InOutType type)
std::size_t ShaderGraph::AddOutput(std::string name, InOutType type, std::size_t locationIndex)
{
std::size_t index = m_outputs.size();
auto& outputEntry = m_outputs.emplace_back();
outputEntry.locationIndex = locationIndex;
outputEntry.name = std::move(name);
outputEntry.type = type;
@ -105,10 +107,11 @@ std::size_t ShaderGraph::AddOutput(std::string name, InOutType type)
return index;
}
std::size_t ShaderGraph::AddTexture(std::string name, TextureType type)
std::size_t ShaderGraph::AddTexture(std::string name, TextureType type, std::size_t bindingIndex)
{
std::size_t index = m_textures.size();
auto& textureEntry = m_textures.emplace_back();
textureEntry.bindingIndex = bindingIndex;
textureEntry.name = std::move(name);
textureEntry.type = type;
@ -141,6 +144,7 @@ void ShaderGraph::Load(const QJsonObject& data)
QJsonObject inputDoc = inputDocRef.toObject();
InputEntry& input = m_inputs.emplace_back();
input.locationIndex = static_cast<std::size_t>(inputDoc["locationIndex"].toInt(0));
input.name = inputDoc["name"].toString().toStdString();
input.role = DecodeEnum<InputRole>(inputDoc["role"].toString().toStdString()).value();
input.roleIndex = static_cast<std::size_t>(inputDoc["roleIndex"].toInt(0));
@ -155,6 +159,7 @@ void ShaderGraph::Load(const QJsonObject& data)
QJsonObject outputDoc = outputDocRef.toObject();
OutputEntry& output = m_outputs.emplace_back();
output.locationIndex = static_cast<std::size_t>(outputDoc["locationIndex"].toInt(0));
output.name = outputDoc["name"].toString().toStdString();
output.type = DecodeEnum<InOutType>(outputDoc["type"].toString().toStdString()).value();
}
@ -167,6 +172,7 @@ void ShaderGraph::Load(const QJsonObject& data)
QJsonObject textureDoc = textureDocRef.toObject();
TextureEntry& texture = m_textures.emplace_back();
texture.bindingIndex = static_cast<std::size_t>(textureDoc["bindingIndex"].toInt(0));
texture.name = textureDoc["name"].toString().toStdString();
texture.type = DecodeEnum<TextureType>(textureDoc["type"].toString().toStdString()).value();
}
@ -189,6 +195,7 @@ QJsonObject ShaderGraph::Save()
for (const auto& input : m_inputs)
{
QJsonObject inputDoc;
inputDoc["locationIndex"] = int(input.locationIndex);
inputDoc["name"] = QString::fromStdString(input.name);
inputDoc["role"] = QString(EnumToString(input.role));
inputDoc["roleIndex"] = int(input.roleIndex);
@ -204,6 +211,7 @@ QJsonObject ShaderGraph::Save()
for (const auto& output : m_outputs)
{
QJsonObject outputDoc;
outputDoc["locationIndex"] = int(output.locationIndex);
outputDoc["name"] = QString::fromStdString(output.name);
outputDoc["type"] = QString(EnumToString(output.type));
@ -217,6 +225,7 @@ QJsonObject ShaderGraph::Save()
for (const auto& texture : m_textures)
{
QJsonObject textureDoc;
textureDoc["bindingIndex"] = int(texture.bindingIndex);
textureDoc["name"] = QString::fromStdString(texture.name);
textureDoc["type"] = QString(EnumToString(texture.type));
@ -247,9 +256,9 @@ QJsonObject ShaderGraph::Save()
return sceneJson;
}
Nz::ShaderAst::StatementPtr ShaderGraph::ToAst()
Nz::ShaderNodes::StatementPtr ShaderGraph::ToAst()
{
std::vector<Nz::ShaderAst::StatementPtr> statements;
std::vector<Nz::ShaderNodes::StatementPtr> statements;
QHash<QUuid, unsigned int> usageCount;
std::function<void(QtNodes::Node*)> DetectVariables;
@ -278,13 +287,13 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst()
DetectVariables(node);
});
QHash<QUuid, Nz::ShaderAst::ExpressionPtr> variableExpressions;
QHash<QUuid, Nz::ShaderNodes::ExpressionPtr> variableExpressions;
unsigned int varCount = 0;
std::unordered_set<std::string> usedVariableNames;
std::function<Nz::ShaderAst::ExpressionPtr(QtNodes::Node*)> HandleNode;
HandleNode = [&](QtNodes::Node* node) -> Nz::ShaderAst::ExpressionPtr
std::function<Nz::ShaderNodes::ExpressionPtr(QtNodes::Node*)> HandleNode;
HandleNode = [&](QtNodes::Node* node) -> Nz::ShaderNodes::ExpressionPtr
{
ShaderNode* shaderNode = static_cast<ShaderNode*>(node->nodeDataModel());
if (shaderNode->validationState() != QtNodes::NodeValidationState::Valid)
@ -298,7 +307,7 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst()
assert(it != usageCount.end());
std::size_t inputCount = shaderNode->nPorts(QtNodes::PortType::In);
Nz::StackArray<Nz::ShaderAst::ExpressionPtr> expressions = NazaraStackArray(Nz::ShaderAst::ExpressionPtr, inputCount);
Nz::StackArray<Nz::ShaderNodes::ExpressionPtr> expressions = NazaraStackArray(Nz::ShaderNodes::ExpressionPtr, inputCount);
std::size_t i = 0;
for (const auto& connectionSet : node->nodeState().getEntries(QtNodes::PortType::In))
@ -316,8 +325,8 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst()
const std::string& variableName = shaderNode->GetVariableName();
if (*it > 1 || !variableName.empty())
{
Nz::ShaderAst::ExpressionPtr varExpression;
if (expression->GetExpressionCategory() == Nz::ShaderAst::ExpressionCategory::RValue)
Nz::ShaderNodes::ExpressionPtr varExpression;
if (expression->GetExpressionCategory() == Nz::ShaderNodes::ExpressionCategory::RValue)
{
std::string name;
if (variableName.empty())
@ -330,10 +339,10 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst()
usedVariableNames.insert(name);
auto variable = Nz::ShaderBuilder::Variable(std::move(name), expression->GetExpressionType());
auto variable = Nz::ShaderBuilder::Local(std::move(name), expression->GetExpressionType());
statements.emplace_back(Nz::ShaderBuilder::DeclareVariable(variable, expression));
varExpression = variable;
varExpression = Nz::ShaderBuilder::Identifier(variable);
}
else
varExpression = expression;
@ -354,13 +363,14 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst()
}
});
return Nz::ShaderAst::StatementBlock::Build(std::move(statements));
return Nz::ShaderNodes::StatementBlock::Build(std::move(statements));
}
void ShaderGraph::UpdateInput(std::size_t inputIndex, std::string name, InOutType type, InputRole role, std::size_t roleIndex)
void ShaderGraph::UpdateInput(std::size_t inputIndex, std::string name, InOutType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex)
{
assert(inputIndex < m_inputs.size());
auto& inputEntry = m_inputs[inputIndex];
inputEntry.locationIndex = locationIndex;
inputEntry.name = std::move(name);
inputEntry.role = role;
inputEntry.roleIndex = roleIndex;
@ -369,10 +379,11 @@ void ShaderGraph::UpdateInput(std::size_t inputIndex, std::string name, InOutTyp
OnInputUpdate(this, inputIndex);
}
void ShaderGraph::UpdateOutput(std::size_t outputIndex, std::string name, InOutType type)
void ShaderGraph::UpdateOutput(std::size_t outputIndex, std::string name, InOutType type, std::size_t locationIndex)
{
assert(outputIndex < m_outputs.size());
auto& outputEntry = m_outputs[outputIndex];
outputEntry.locationIndex = locationIndex;
outputEntry.name = std::move(name);
outputEntry.type = type;

View File

@ -4,7 +4,7 @@
#define NAZARA_SHADERNODES_SHADERGRAPH_HPP
#include <Nazara/Core/Signal.hpp>
#include <Nazara/Renderer/ShaderAst.hpp>
#include <Nazara/Renderer/ShaderNodes.hpp>
#include <nodes/FlowScene>
#include <ShaderNode/Enums.hpp>
#include <ShaderNode/Previews/PreviewModel.hpp>
@ -23,9 +23,9 @@ class ShaderGraph
ShaderGraph();
~ShaderGraph();
std::size_t AddInput(std::string name, InOutType type, InputRole role, std::size_t roleIndex);
std::size_t AddOutput(std::string name, InOutType type);
std::size_t AddTexture(std::string name, TextureType type);
std::size_t AddInput(std::string name, InOutType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex);
std::size_t AddOutput(std::string name, InOutType type, std::size_t locationIndex);
std::size_t AddTexture(std::string name, TextureType type, std::size_t bindingIndex);
void Clear();
@ -44,14 +44,15 @@ class ShaderGraph
void Load(const QJsonObject& data);
QJsonObject Save();
Nz::ShaderAst::StatementPtr ToAst();
Nz::ShaderNodes::StatementPtr ToAst();
void UpdateInput(std::size_t inputIndex, std::string name, InOutType type, InputRole role, std::size_t roleIndex);
void UpdateOutput(std::size_t outputIndex, std::string name, InOutType type);
void UpdateInput(std::size_t inputIndex, std::string name, InOutType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex);
void UpdateOutput(std::size_t outputIndex, std::string name, InOutType type, std::size_t locationIndex);
void UpdateTexturePreview(std::size_t texture, QImage preview);
struct InputEntry
{
std::size_t locationIndex;
std::size_t roleIndex;
std::string name;
InputRole role;
@ -60,12 +61,14 @@ class ShaderGraph
struct OutputEntry
{
std::size_t locationIndex;
std::string name;
InOutType type;
};
struct TextureEntry
{
std::size_t bindingIndex;
std::string name;
TextureType type;
QImage preview;

View File

@ -23,6 +23,8 @@ QDialog(parent)
for (std::size_t i = 0; i < InputRoleCount; ++i)
m_roleList->addItem(EnumToString(static_cast<InputRole>(i)));
m_locationIndex = new QSpinBox;
m_roleIndex = new QSpinBox;
QFormLayout* formLayout = new QFormLayout;
@ -30,6 +32,7 @@ QDialog(parent)
formLayout->addRow(tr("Type"), m_typeList);
formLayout->addRow(tr("Role"), m_roleList);
formLayout->addRow(tr("Role index"), m_roleIndex);
formLayout->addRow(tr("Input index"), m_locationIndex);
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, &QDialogButtonBox::accepted, this, &InputEditDialog::OnAccept);
@ -46,6 +49,7 @@ InputEditDialog::InputEditDialog(const InputInfo& input, QWidget* parent) :
InputEditDialog(parent)
{
m_inputName->setText(QString::fromStdString(input.name));
m_locationIndex->setValue(int(input.locationIndex));
m_roleIndex->setValue(int(input.roleIndex));
m_roleList->setCurrentText(EnumToString(input.role));
m_typeList->setCurrentText(EnumToString(input.type));
@ -54,6 +58,7 @@ InputEditDialog(parent)
InputInfo InputEditDialog::GetInputInfo() const
{
InputInfo inputInfo;
inputInfo.locationIndex = static_cast<std::size_t>(m_locationIndex->value());
inputInfo.name = m_inputName->text().toStdString();
inputInfo.role = static_cast<InputRole>(m_roleList->currentIndex());
inputInfo.roleIndex = static_cast<std::size_t>(m_roleIndex->value());

View File

@ -12,6 +12,7 @@ class QSpinBox;
struct InputInfo
{
std::size_t locationIndex;
std::size_t roleIndex;
std::string name;
InputRole role;
@ -33,6 +34,7 @@ class InputEditDialog : public QDialog
QComboBox* m_roleList;
QComboBox* m_typeList;
QLineEdit* m_inputName;
QSpinBox* m_locationIndex;
QSpinBox* m_roleIndex;
};

View File

@ -39,7 +39,7 @@ void InputEditor::OnAddInput()
connect(dialog, &QDialog::accepted, [this, dialog]
{
InputInfo inputInfo = dialog->GetInputInfo();
m_shaderGraph.AddInput(std::move(inputInfo.name), inputInfo.type, inputInfo.role, inputInfo.roleIndex);
m_shaderGraph.AddInput(std::move(inputInfo.name), inputInfo.type, inputInfo.role, inputInfo.roleIndex, inputInfo.locationIndex);
});
dialog->open();
@ -60,7 +60,7 @@ void InputEditor::OnEditInput(int inputIndex)
connect(dialog, &QDialog::accepted, [this, dialog, inputIndex]
{
InputInfo inputInfo = dialog->GetInputInfo();
m_shaderGraph.UpdateInput(inputIndex, std::move(inputInfo.name), inputInfo.type, inputInfo.role, inputInfo.roleIndex);
m_shaderGraph.UpdateInput(inputIndex, std::move(inputInfo.name), inputInfo.type, inputInfo.role, inputInfo.roleIndex, inputInfo.locationIndex);
});
dialog->open();

View File

@ -1,5 +1,7 @@
#include <ShaderNode/Widgets/MainWindow.hpp>
#include <Nazara/Core/File.hpp>
#include <Nazara/Renderer/GlslWriter.hpp>
#include <Nazara/Renderer/ShaderSerializer.hpp>
#include <ShaderNode/ShaderGraph.hpp>
#include <ShaderNode/Widgets/InputEditor.hpp>
#include <ShaderNode/Widgets/OutputEditor.hpp>
@ -84,8 +86,6 @@ void MainWindow::BuildMenu()
QMenu* shader = menu->addMenu(tr("&Shader"));
{
QtNodes::FlowScene* scene = &m_shaderGraph.GetScene();
QAction* loadShader = shader->addAction(tr("Load..."));
QObject::connect(loadShader, &QAction::triggered, this, &MainWindow::OnLoad);
QAction* saveShader = shader->addAction(tr("Save..."));
@ -101,8 +101,52 @@ void MainWindow::OnCompileToGLSL()
{
try
{
Nz::ShaderNodes::StatementPtr shaderAst = m_shaderGraph.ToAst();
Nz::File file("shader.shader", Nz::OpenMode_WriteOnly);
file.Write(Nz::ShaderNodes::Serialize(shaderAst));
//TODO: Put in another function
auto GetExpressionFromInOut = [&] (InOutType type)
{
switch (type)
{
case InOutType::Bool: return Nz::ShaderNodes::ExpressionType::Boolean;
case InOutType::Float1: return Nz::ShaderNodes::ExpressionType::Float1;
case InOutType::Float2: return Nz::ShaderNodes::ExpressionType::Float2;
case InOutType::Float3: return Nz::ShaderNodes::ExpressionType::Float3;
case InOutType::Float4: return Nz::ShaderNodes::ExpressionType::Float4;
}
assert(false);
throw std::runtime_error("Unhandled input type");
};
auto GetExpressionFromTexture = [&](TextureType type)
{
switch (type)
{
case TextureType::Sampler2D: return Nz::ShaderNodes::ExpressionType::Sampler2D;
}
assert(false);
throw std::runtime_error("Unhandled texture type");
};
Nz::ShaderAst shader;
for (const auto& input : m_shaderGraph.GetInputs())
shader.AddInput(input.name, GetExpressionFromInOut(input.type), input.locationIndex);
for (const auto& output : m_shaderGraph.GetOutputs())
shader.AddOutput(output.name, GetExpressionFromInOut(output.type), output.locationIndex);
for (const auto& uniform : m_shaderGraph.GetTextures())
shader.AddUniform(uniform.name, GetExpressionFromTexture(uniform.type), uniform.bindingIndex);
shader.AddFunction("main", shaderAst);
Nz::GlslWriter writer;
Nz::String glsl = writer.Generate(m_shaderGraph.ToAst());
Nz::String glsl = writer.Generate(shader);
std::cout << glsl << std::endl;

View File

@ -4,6 +4,7 @@
#include <QtWidgets/QFormLayout>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QSpinBox>
#include <QtWidgets/QVBoxLayout>
OutputEditDialog::OutputEditDialog(QWidget* parent) :
@ -18,9 +19,12 @@ QDialog(parent)
for (std::size_t i = 0; i < InOutTypeCount; ++i)
m_typeList->addItem(EnumToString(static_cast<InOutType>(i)));
m_locationIndex = new QSpinBox;
QFormLayout* formLayout = new QFormLayout;
formLayout->addRow(tr("Name"), m_outputName);
formLayout->addRow(tr("Type"), m_typeList);
formLayout->addRow(tr("Output index"), m_locationIndex);
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, &QDialogButtonBox::accepted, this, &OutputEditDialog::OnAccept);
@ -33,16 +37,18 @@ QDialog(parent)
setLayout(verticalLayout);
}
OutputEditDialog::OutputEditDialog(const OutputInfo& input, QWidget* parent) :
OutputEditDialog::OutputEditDialog(const OutputInfo& output, QWidget* parent) :
OutputEditDialog(parent)
{
m_outputName->setText(QString::fromStdString(input.name));
m_typeList->setCurrentText(EnumToString(input.type));
m_locationIndex->setValue(int(output.locationIndex));
m_outputName->setText(QString::fromStdString(output.name));
m_typeList->setCurrentText(EnumToString(output.type));
}
OutputInfo OutputEditDialog::GetOutputInfo() const
{
OutputInfo inputInfo;
inputInfo.locationIndex = static_cast<std::size_t>(m_locationIndex->value());
inputInfo.name = m_outputName->text().toStdString();
inputInfo.type = static_cast<InOutType>(m_typeList->currentIndex());

View File

@ -8,9 +8,11 @@
class QComboBox;
class QLineEdit;
class QSpinBox;
struct OutputInfo
{
std::size_t locationIndex;
std::string name;
InOutType type;
};
@ -19,7 +21,7 @@ class OutputEditDialog : public QDialog
{
public:
OutputEditDialog(QWidget* parent = nullptr);
OutputEditDialog(const OutputInfo& input, QWidget* parent = nullptr);
OutputEditDialog(const OutputInfo& output, QWidget* parent = nullptr);
~OutputEditDialog() = default;
OutputInfo GetOutputInfo() const;
@ -29,6 +31,7 @@ class OutputEditDialog : public QDialog
QComboBox* m_typeList;
QLineEdit* m_outputName;
QSpinBox* m_locationIndex;
};
#include <ShaderNode/Widgets/OutputEditDialog.inl>

View File

@ -38,8 +38,8 @@ void OutputEditor::OnAddOutput()
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
connect(dialog, &QDialog::accepted, [this, dialog]
{
OutputInfo inputInfo = dialog->GetOutputInfo();
m_shaderGraph.AddOutput(std::move(inputInfo.name), inputInfo.type);
OutputInfo outputInfo = dialog->GetOutputInfo();
m_shaderGraph.AddOutput(std::move(outputInfo.name), outputInfo.type, outputInfo.locationIndex);
});
dialog->open();
@ -57,8 +57,8 @@ void OutputEditor::OnEditOutput(int inputIndex)
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
connect(dialog, &QDialog::accepted, [this, dialog, inputIndex]
{
OutputInfo inputInfo = dialog->GetOutputInfo();
m_shaderGraph.UpdateOutput(inputIndex, std::move(inputInfo.name), inputInfo.type);
OutputInfo outputInfo = dialog->GetOutputInfo();
m_shaderGraph.UpdateOutput(inputIndex, std::move(outputInfo.name), outputInfo.type, outputInfo.locationIndex);
});
dialog->open();