ShaderAst: Big refactor + add binding/location support
This commit is contained in:
parent
463b540739
commit
f38bfdde8a
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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)...);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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>
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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>
|
||||
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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("}");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 = ¤tContext;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,4 +7,5 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
ShaderWriter::~ShaderWriter() = default;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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"; }
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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"; }
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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"; }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"; }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Reference in New Issue