Renderer: Add support for struct and UBO
This commit is contained in:
parent
4c0dc7813d
commit
fbba281d14
|
|
@ -44,15 +44,17 @@ namespace Nz
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void Append(ShaderAst::Type type);
|
||||||
void Append(ShaderNodes::BuiltinEntry builtin);
|
void Append(ShaderNodes::BuiltinEntry builtin);
|
||||||
void Append(ShaderNodes::ExpressionType type);
|
void Append(ShaderNodes::ExpressionType type);
|
||||||
|
void Append(ShaderNodes::MemoryLayout layout);
|
||||||
template<typename T> void Append(const T& param);
|
template<typename T> void Append(const T& param);
|
||||||
void AppendCommentSection(const std::string& section);
|
void AppendCommentSection(const std::string& section);
|
||||||
void AppendFunction(const ShaderAst::Function& func);
|
void AppendFunction(const ShaderAst::Function& func);
|
||||||
void AppendFunctionPrototype(const ShaderAst::Function& func);
|
void AppendFunctionPrototype(const ShaderAst::Function& func);
|
||||||
void AppendLine(const std::string& txt = {});
|
void AppendLine(const std::string& txt = {});
|
||||||
|
|
||||||
template<typename T> void DeclareVariables(const std::vector<T>& variables, const std::string& keyword = {}, const std::string& section = {});
|
template<typename T> void DeclareVariables(const ShaderAst& shader, const std::vector<T>& variables, const std::string& keyword = {}, const std::string& section = {});
|
||||||
|
|
||||||
void EnterScope();
|
void EnterScope();
|
||||||
void LeaveScope();
|
void LeaveScope();
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ namespace Nz
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void GlslWriter::DeclareVariables(const std::vector<T>& variables, const std::string& keyword, const std::string& section)
|
void GlslWriter::DeclareVariables(const ShaderAst& shader, const std::vector<T>& variables, const std::string& keyword, const std::string& section)
|
||||||
{
|
{
|
||||||
if (!variables.empty())
|
if (!variables.empty())
|
||||||
{
|
{
|
||||||
|
|
@ -34,16 +34,6 @@ namespace Nz
|
||||||
Append(*var.locationIndex);
|
Append(*var.locationIndex);
|
||||||
Append(") ");
|
Append(") ");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if constexpr (std::is_same_v<T, ShaderAst::Uniform>)
|
|
||||||
{
|
|
||||||
if (var.bindingIndex)
|
|
||||||
{
|
|
||||||
Append("layout(binding = ");
|
|
||||||
Append(*var.bindingIndex);
|
|
||||||
Append(") ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!keyword.empty())
|
if (!keyword.empty())
|
||||||
{
|
{
|
||||||
|
|
@ -56,6 +46,83 @@ namespace Nz
|
||||||
Append(var.name);
|
Append(var.name);
|
||||||
AppendLine(";");
|
AppendLine(";");
|
||||||
}
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, ShaderAst::Uniform>)
|
||||||
|
{
|
||||||
|
if (var.bindingIndex || var.memoryLayout)
|
||||||
|
{
|
||||||
|
Append("layout(");
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
if (var.bindingIndex)
|
||||||
|
{
|
||||||
|
if (!first)
|
||||||
|
Append(", ");
|
||||||
|
|
||||||
|
Append("binding = ");
|
||||||
|
Append(*var.bindingIndex);
|
||||||
|
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var.memoryLayout)
|
||||||
|
{
|
||||||
|
if (!first)
|
||||||
|
Append(", ");
|
||||||
|
|
||||||
|
Append(*var.memoryLayout);
|
||||||
|
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Append(") ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!keyword.empty())
|
||||||
|
{
|
||||||
|
Append(keyword);
|
||||||
|
Append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::visit([&](auto&& arg)
|
||||||
|
{
|
||||||
|
using T = std::decay_t<decltype(arg)>;
|
||||||
|
if constexpr (std::is_same_v<T, ShaderNodes::ExpressionType>)
|
||||||
|
{
|
||||||
|
Append(arg);
|
||||||
|
Append(" ");
|
||||||
|
Append(var.name);
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, std::string>)
|
||||||
|
{
|
||||||
|
const auto& structs = shader.GetStructs();
|
||||||
|
auto it = std::find_if(structs.begin(), structs.end(), [&](const auto& s) { return s.name == arg; });
|
||||||
|
if (it == structs.end())
|
||||||
|
throw std::runtime_error("struct " + arg + " has not been defined");
|
||||||
|
|
||||||
|
const auto& s = *it;
|
||||||
|
|
||||||
|
AppendLine(var.name + "_interface");
|
||||||
|
AppendLine("{");
|
||||||
|
for (const auto& m : s.members)
|
||||||
|
{
|
||||||
|
Append("\t");
|
||||||
|
Append(m.type);
|
||||||
|
Append(" ");
|
||||||
|
Append(m.name);
|
||||||
|
AppendLine(";");
|
||||||
|
}
|
||||||
|
Append("} ");
|
||||||
|
Append(var.name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor");
|
||||||
|
|
||||||
|
}, var.type);
|
||||||
|
|
||||||
|
AppendLine(";");
|
||||||
|
AppendLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AppendLine();
|
AppendLine();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@
|
||||||
#include <Nazara/Renderer/ShaderNodes.hpp>
|
#include <Nazara/Renderer/ShaderNodes.hpp>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
|
|
@ -21,16 +23,21 @@ namespace Nz
|
||||||
struct Function;
|
struct Function;
|
||||||
struct FunctionParameter;
|
struct FunctionParameter;
|
||||||
struct InputOutput;
|
struct InputOutput;
|
||||||
struct VariableBase;
|
struct Struct;
|
||||||
|
struct StructMember;
|
||||||
struct Uniform;
|
struct Uniform;
|
||||||
|
struct VariableBase;
|
||||||
|
|
||||||
|
using Type = std::variant<ShaderNodes::ExpressionType, std::string>;
|
||||||
|
|
||||||
ShaderAst() = default;
|
ShaderAst() = default;
|
||||||
~ShaderAst() = default;
|
~ShaderAst() = default;
|
||||||
|
|
||||||
void AddFunction(std::string name, ShaderNodes::StatementPtr statement, std::vector<FunctionParameter> parameters = {}, ShaderNodes::ExpressionType returnType = ShaderNodes::ExpressionType::Void);
|
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 AddInput(std::string name, Type type, std::optional<std::size_t> locationIndex);
|
||||||
void AddOutput(std::string name, ShaderNodes::ExpressionType type, std::optional<std::size_t> locationIndex);
|
void AddOutput(std::string name, Type type, std::optional<std::size_t> locationIndex);
|
||||||
void AddUniform(std::string name, ShaderNodes::ExpressionType type, std::optional<std::size_t> bindingIndex);
|
void AddStruct(std::string name, std::vector<StructMember> members);
|
||||||
|
void AddUniform(std::string name, Type type, std::optional<std::size_t> bindingIndex, std::optional<ShaderNodes::MemoryLayout> memoryLayout);
|
||||||
|
|
||||||
inline const Function& GetFunction(std::size_t i) const;
|
inline const Function& GetFunction(std::size_t i) const;
|
||||||
inline std::size_t GetFunctionCount() const;
|
inline std::size_t GetFunctionCount() const;
|
||||||
|
|
@ -41,6 +48,9 @@ namespace Nz
|
||||||
inline const InputOutput& GetOutput(std::size_t i) const;
|
inline const InputOutput& GetOutput(std::size_t i) const;
|
||||||
inline std::size_t GetOutputCount() const;
|
inline std::size_t GetOutputCount() const;
|
||||||
inline const std::vector<InputOutput>& GetOutputs() const;
|
inline const std::vector<InputOutput>& GetOutputs() const;
|
||||||
|
inline const Struct& GetStruct(std::size_t i) const;
|
||||||
|
inline std::size_t GetStructCount() const;
|
||||||
|
inline const std::vector<Struct>& GetStructs() const;
|
||||||
inline const Uniform& GetUniform(std::size_t i) const;
|
inline const Uniform& GetUniform(std::size_t i) const;
|
||||||
inline std::size_t GetUniformCount() const;
|
inline std::size_t GetUniformCount() const;
|
||||||
inline const std::vector<Uniform>& GetUniforms() const;
|
inline const std::vector<Uniform>& GetUniforms() const;
|
||||||
|
|
@ -48,7 +58,7 @@ namespace Nz
|
||||||
struct VariableBase
|
struct VariableBase
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
ShaderNodes::ExpressionType type;
|
Type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FunctionParameter : VariableBase
|
struct FunctionParameter : VariableBase
|
||||||
|
|
@ -71,12 +81,26 @@ namespace Nz
|
||||||
struct Uniform : VariableBase
|
struct Uniform : VariableBase
|
||||||
{
|
{
|
||||||
std::optional<std::size_t> bindingIndex;
|
std::optional<std::size_t> bindingIndex;
|
||||||
|
std::optional<ShaderNodes::MemoryLayout> memoryLayout;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Struct
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
std::vector<StructMember> members;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct StructMember
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
Type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Function> m_functions;
|
std::vector<Function> m_functions;
|
||||||
std::vector<InputOutput> m_inputs;
|
std::vector<InputOutput> m_inputs;
|
||||||
std::vector<InputOutput> m_outputs;
|
std::vector<InputOutput> m_outputs;
|
||||||
|
std::vector<Struct> m_structs;
|
||||||
std::vector<Uniform> m_uniforms;
|
std::vector<Uniform> m_uniforms;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,22 @@ namespace Nz
|
||||||
return m_outputs;
|
return m_outputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline auto ShaderAst::GetStruct(std::size_t i) const -> const Struct&
|
||||||
|
{
|
||||||
|
assert(i < m_structs.size());
|
||||||
|
return m_structs[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::size_t ShaderAst::GetStructCount() const
|
||||||
|
{
|
||||||
|
return m_structs.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto ShaderAst::GetStructs() const -> const std::vector<Struct>&
|
||||||
|
{
|
||||||
|
return m_structs;
|
||||||
|
}
|
||||||
|
|
||||||
inline auto ShaderAst::GetUniform(std::size_t i) const -> const Uniform&
|
inline auto ShaderAst::GetUniform(std::size_t i) const -> const Uniform&
|
||||||
{
|
{
|
||||||
assert(i < m_uniforms.size());
|
assert(i < m_uniforms.size());
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,11 @@ namespace Nz::ShaderNodes
|
||||||
DotProduct
|
DotProduct
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class MemoryLayout
|
||||||
|
{
|
||||||
|
Std140
|
||||||
|
};
|
||||||
|
|
||||||
enum class NodeType
|
enum class NodeType
|
||||||
{
|
{
|
||||||
None = -1,
|
None = -1,
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,12 @@
|
||||||
#include <Nazara/Core/ByteArray.hpp>
|
#include <Nazara/Core/ByteArray.hpp>
|
||||||
#include <Nazara/Core/ByteStream.hpp>
|
#include <Nazara/Core/ByteStream.hpp>
|
||||||
#include <Nazara/Renderer/Config.hpp>
|
#include <Nazara/Renderer/Config.hpp>
|
||||||
|
#include <Nazara/Renderer/ShaderAst.hpp>
|
||||||
#include <Nazara/Renderer/ShaderNodes.hpp>
|
#include <Nazara/Renderer/ShaderNodes.hpp>
|
||||||
#include <Nazara/Renderer/ShaderVariables.hpp>
|
#include <Nazara/Renderer/ShaderVariables.hpp>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
class ShaderAst;
|
|
||||||
|
|
||||||
class NAZARA_RENDERER_API ShaderSerializerBase
|
class NAZARA_RENDERER_API ShaderSerializerBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -44,6 +43,7 @@ namespace Nz
|
||||||
protected:
|
protected:
|
||||||
template<typename T> void Container(T& container);
|
template<typename T> void Container(T& container);
|
||||||
template<typename T> void Enum(T& enumVal);
|
template<typename T> void Enum(T& enumVal);
|
||||||
|
template<typename T> void OptEnum(std::optional<T>& optVal);
|
||||||
template<typename T> void OptVal(std::optional<T>& optVal);
|
template<typename T> void OptVal(std::optional<T>& optVal);
|
||||||
|
|
||||||
virtual bool IsWriting() const = 0;
|
virtual bool IsWriting() const = 0;
|
||||||
|
|
@ -57,6 +57,8 @@ namespace Nz
|
||||||
virtual void Value(Vector2f& val) = 0;
|
virtual void Value(Vector2f& val) = 0;
|
||||||
virtual void Value(Vector3f& val) = 0;
|
virtual void Value(Vector3f& val) = 0;
|
||||||
virtual void Value(Vector4f& val) = 0;
|
virtual void Value(Vector4f& val) = 0;
|
||||||
|
virtual void Value(UInt8& val) = 0;
|
||||||
|
virtual void Value(UInt16& val) = 0;
|
||||||
virtual void Value(UInt32& val) = 0;
|
virtual void Value(UInt32& val) = 0;
|
||||||
inline void Value(std::size_t& val);
|
inline void Value(std::size_t& val);
|
||||||
|
|
||||||
|
|
@ -82,6 +84,8 @@ namespace Nz
|
||||||
void Value(Vector2f& val) override;
|
void Value(Vector2f& val) override;
|
||||||
void Value(Vector3f& val) override;
|
void Value(Vector3f& val) override;
|
||||||
void Value(Vector4f& val) override;
|
void Value(Vector4f& val) override;
|
||||||
|
void Value(UInt8& val) override;
|
||||||
|
void Value(UInt16& val) override;
|
||||||
void Value(UInt32& val) override;
|
void Value(UInt32& val) override;
|
||||||
void Variable(ShaderNodes::VariablePtr& var) override;
|
void Variable(ShaderNodes::VariablePtr& var) override;
|
||||||
|
|
||||||
|
|
@ -99,12 +103,15 @@ namespace Nz
|
||||||
private:
|
private:
|
||||||
bool IsWriting() const override;
|
bool IsWriting() const override;
|
||||||
void Node(ShaderNodes::NodePtr& node) override;
|
void Node(ShaderNodes::NodePtr& node) override;
|
||||||
|
void Type(ShaderAst::Type& type);
|
||||||
void Value(bool& val) override;
|
void Value(bool& val) override;
|
||||||
void Value(float& val) override;
|
void Value(float& val) override;
|
||||||
void Value(std::string& val) override;
|
void Value(std::string& val) override;
|
||||||
void Value(Vector2f& val) override;
|
void Value(Vector2f& val) override;
|
||||||
void Value(Vector3f& val) override;
|
void Value(Vector3f& val) override;
|
||||||
void Value(Vector4f& val) override;
|
void Value(Vector4f& val) override;
|
||||||
|
void Value(UInt8& val) override;
|
||||||
|
void Value(UInt16& val) override;
|
||||||
void Value(UInt32& val) override;
|
void Value(UInt32& val) override;
|
||||||
void Variable(ShaderNodes::VariablePtr& var) override;
|
void Variable(ShaderNodes::VariablePtr& var) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,24 @@ namespace Nz
|
||||||
enumVal = static_cast<T>(value);
|
enumVal = static_cast<T>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void ShaderSerializerBase::OptEnum(std::optional<T>& optVal)
|
||||||
|
{
|
||||||
|
bool isWriting = IsWriting();
|
||||||
|
|
||||||
|
bool hasValue;
|
||||||
|
if (isWriting)
|
||||||
|
hasValue = optVal.has_value();
|
||||||
|
|
||||||
|
Value(hasValue);
|
||||||
|
|
||||||
|
if (!isWriting && hasValue)
|
||||||
|
optVal.emplace();
|
||||||
|
|
||||||
|
if (optVal.has_value())
|
||||||
|
Enum(optVal.value());
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void ShaderSerializerBase::OptVal(std::optional<T>& optVal)
|
void ShaderSerializerBase::OptVal(std::optional<T>& optVal)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,11 @@
|
||||||
#include <Nazara/Core/ByteArray.hpp>
|
#include <Nazara/Core/ByteArray.hpp>
|
||||||
#include <Nazara/Core/ByteStream.hpp>
|
#include <Nazara/Core/ByteStream.hpp>
|
||||||
#include <Nazara/Renderer/Config.hpp>
|
#include <Nazara/Renderer/Config.hpp>
|
||||||
|
#include <Nazara/Renderer/ShaderAst.hpp>
|
||||||
#include <Nazara/Renderer/ShaderVisitor.hpp>
|
#include <Nazara/Renderer/ShaderVisitor.hpp>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
class ShaderAst;
|
|
||||||
|
|
||||||
class NAZARA_RENDERER_API ShaderValidator : public ShaderVisitor
|
class NAZARA_RENDERER_API ShaderValidator : public ShaderVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -31,7 +30,7 @@ namespace Nz
|
||||||
const ShaderNodes::ExpressionPtr& MandatoryExpr(const ShaderNodes::ExpressionPtr& node);
|
const ShaderNodes::ExpressionPtr& MandatoryExpr(const ShaderNodes::ExpressionPtr& node);
|
||||||
const ShaderNodes::NodePtr& MandatoryNode(const ShaderNodes::NodePtr& node);
|
const ShaderNodes::NodePtr& MandatoryNode(const ShaderNodes::NodePtr& node);
|
||||||
void TypeMustMatch(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right);
|
void TypeMustMatch(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right);
|
||||||
void TypeMustMatch(ShaderNodes::ExpressionType left, ShaderNodes::ExpressionType right);
|
void TypeMustMatch(const ShaderAst::Type& left, const ShaderAst::Type& right);
|
||||||
|
|
||||||
using ShaderVisitor::Visit;
|
using ShaderVisitor::Visit;
|
||||||
void Visit(const ShaderNodes::AssignOp& node) override;
|
void Visit(const ShaderNodes::AssignOp& node) override;
|
||||||
|
|
|
||||||
|
|
@ -108,13 +108,35 @@ namespace Nz
|
||||||
AppendLine();
|
AppendLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Structures
|
||||||
|
/*if (shader.GetStructCount() > 0)
|
||||||
|
{
|
||||||
|
AppendCommentSection("Structures");
|
||||||
|
for (const auto& s : shader.GetStructs())
|
||||||
|
{
|
||||||
|
Append("struct ");
|
||||||
|
AppendLine(s.name);
|
||||||
|
AppendLine("{");
|
||||||
|
for (const auto& m : s.members)
|
||||||
|
{
|
||||||
|
Append("\t");
|
||||||
|
Append(m.type);
|
||||||
|
Append(" ");
|
||||||
|
Append(m.name);
|
||||||
|
AppendLine(";");
|
||||||
|
}
|
||||||
|
AppendLine("};");
|
||||||
|
AppendLine();
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
// Global variables (uniforms, input and outputs)
|
// Global variables (uniforms, input and outputs)
|
||||||
const char* inKeyword = (glslVersion >= 130) ? "in" : "varying";
|
const char* inKeyword = (glslVersion >= 130) ? "in" : "varying";
|
||||||
const char* outKeyword = (glslVersion >= 130) ? "out" : "varying";
|
const char* outKeyword = (glslVersion >= 130) ? "out" : "varying";
|
||||||
|
|
||||||
DeclareVariables(shader.GetUniforms(), "uniform", "Uniforms");
|
DeclareVariables(shader, shader.GetUniforms(), "uniform", "Uniforms");
|
||||||
DeclareVariables(shader.GetInputs(), inKeyword, "Inputs");
|
DeclareVariables(shader, shader.GetInputs(), inKeyword, "Inputs");
|
||||||
DeclareVariables(shader.GetOutputs(), outKeyword, "Outputs");
|
DeclareVariables(shader, shader.GetOutputs(), outKeyword, "Outputs");
|
||||||
|
|
||||||
std::size_t functionCount = shader.GetFunctionCount();
|
std::size_t functionCount = shader.GetFunctionCount();
|
||||||
if (functionCount > 1)
|
if (functionCount > 1)
|
||||||
|
|
@ -141,6 +163,14 @@ namespace Nz
|
||||||
m_environment = std::move(environment);
|
m_environment = std::move(environment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GlslWriter::Append(ShaderAst::Type type)
|
||||||
|
{
|
||||||
|
std::visit([&](auto&& arg)
|
||||||
|
{
|
||||||
|
Append(arg);
|
||||||
|
}, type);
|
||||||
|
}
|
||||||
|
|
||||||
void GlslWriter::Append(ShaderNodes::BuiltinEntry builtin)
|
void GlslWriter::Append(ShaderNodes::BuiltinEntry builtin)
|
||||||
{
|
{
|
||||||
switch (builtin)
|
switch (builtin)
|
||||||
|
|
@ -182,6 +212,16 @@ namespace Nz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GlslWriter::Append(ShaderNodes::MemoryLayout layout)
|
||||||
|
{
|
||||||
|
switch (layout)
|
||||||
|
{
|
||||||
|
case ShaderNodes::MemoryLayout::Std140:
|
||||||
|
Append("std140");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GlslWriter::AppendCommentSection(const std::string& section)
|
void GlslWriter::AppendCommentSection(const std::string& section)
|
||||||
{
|
{
|
||||||
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
|
NazaraAssert(m_currentState, "This function should only be called while processing an AST");
|
||||||
|
|
|
||||||
|
|
@ -16,27 +16,35 @@ namespace Nz
|
||||||
functionEntry.statement = std::move(statement);
|
functionEntry.statement = std::move(statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderAst::AddInput(std::string name, ShaderNodes::ExpressionType type, std::optional<std::size_t> locationIndex)
|
void ShaderAst::AddInput(std::string name, Type type, std::optional<std::size_t> locationIndex)
|
||||||
{
|
{
|
||||||
auto& inputEntry = m_inputs.emplace_back();
|
auto& inputEntry = m_inputs.emplace_back();
|
||||||
inputEntry.name = std::move(name);
|
inputEntry.name = std::move(name);
|
||||||
inputEntry.locationIndex = std::move(locationIndex);
|
inputEntry.locationIndex = std::move(locationIndex);
|
||||||
inputEntry.type = type;
|
inputEntry.type = std::move(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderAst::AddOutput(std::string name, ShaderNodes::ExpressionType type, std::optional<std::size_t> locationIndex)
|
void ShaderAst::AddOutput(std::string name, Type type, std::optional<std::size_t> locationIndex)
|
||||||
{
|
{
|
||||||
auto& outputEntry = m_outputs.emplace_back();
|
auto& outputEntry = m_outputs.emplace_back();
|
||||||
outputEntry.name = std::move(name);
|
outputEntry.name = std::move(name);
|
||||||
outputEntry.locationIndex = std::move(locationIndex);
|
outputEntry.locationIndex = std::move(locationIndex);
|
||||||
outputEntry.type = type;
|
outputEntry.type = std::move(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderAst::AddUniform(std::string name, ShaderNodes::ExpressionType type, std::optional<std::size_t> bindingIndex)
|
void ShaderAst::AddStruct(std::string name, std::vector<StructMember> members)
|
||||||
|
{
|
||||||
|
auto& structEntry = m_structs.emplace_back();
|
||||||
|
structEntry.name = std::move(name);
|
||||||
|
structEntry.members = std::move(members);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderAst::AddUniform(std::string name, Type type, std::optional<std::size_t> bindingIndex, std::optional<ShaderNodes::MemoryLayout> memoryLayout)
|
||||||
{
|
{
|
||||||
auto& uniformEntry = m_uniforms.emplace_back();
|
auto& uniformEntry = m_uniforms.emplace_back();
|
||||||
uniformEntry.bindingIndex = std::move(bindingIndex);
|
uniformEntry.bindingIndex = std::move(bindingIndex);
|
||||||
|
uniformEntry.memoryLayout = std::move(memoryLayout);
|
||||||
uniformEntry.name = std::move(name);
|
uniformEntry.name = std::move(name);
|
||||||
uniformEntry.type = type;
|
uniformEntry.type = std::move(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
#include <Nazara/Renderer/ShaderSerializer.hpp>
|
#include <Nazara/Renderer/ShaderSerializer.hpp>
|
||||||
#include <Nazara/Renderer/ShaderAst.hpp>
|
|
||||||
#include <Nazara/Renderer/ShaderVarVisitor.hpp>
|
#include <Nazara/Renderer/ShaderVarVisitor.hpp>
|
||||||
#include <Nazara/Renderer/ShaderVisitor.hpp>
|
#include <Nazara/Renderer/ShaderVisitor.hpp>
|
||||||
#include <Nazara/Renderer/Debug.hpp>
|
#include <Nazara/Renderer/Debug.hpp>
|
||||||
|
|
@ -250,12 +249,33 @@ namespace Nz
|
||||||
{
|
{
|
||||||
m_stream << s_magicNumber << s_currentVersion;
|
m_stream << s_magicNumber << s_currentVersion;
|
||||||
|
|
||||||
|
auto SerializeType = [&](const ShaderAst::Type& type)
|
||||||
|
{
|
||||||
|
std::visit([&](auto&& arg)
|
||||||
|
{
|
||||||
|
using T = std::decay_t<decltype(arg)>;
|
||||||
|
if constexpr (std::is_same_v<T, ShaderNodes::ExpressionType>)
|
||||||
|
{
|
||||||
|
m_stream << UInt8(0);
|
||||||
|
m_stream << UInt32(arg);
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, std::string>)
|
||||||
|
{
|
||||||
|
m_stream << UInt8(1);
|
||||||
|
m_stream << arg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor");
|
||||||
|
}, type);
|
||||||
|
};
|
||||||
|
|
||||||
auto SerializeInputOutput = [&](auto& inout)
|
auto SerializeInputOutput = [&](auto& inout)
|
||||||
{
|
{
|
||||||
m_stream << UInt32(inout.size());
|
m_stream << UInt32(inout.size());
|
||||||
for (const auto& data : inout)
|
for (const auto& data : inout)
|
||||||
{
|
{
|
||||||
m_stream << data.name << UInt32(data.type);
|
m_stream << data.name;
|
||||||
|
SerializeType(data.type);
|
||||||
|
|
||||||
m_stream << data.locationIndex.has_value();
|
m_stream << data.locationIndex.has_value();
|
||||||
if (data.locationIndex)
|
if (data.locationIndex)
|
||||||
|
|
@ -263,17 +283,34 @@ namespace Nz
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
m_stream << UInt32(shader.GetStructCount());
|
||||||
|
for (const auto& s : shader.GetStructs())
|
||||||
|
{
|
||||||
|
m_stream << s.name;
|
||||||
|
m_stream << UInt32(s.members.size());
|
||||||
|
for (const auto& member : s.members)
|
||||||
|
{
|
||||||
|
m_stream << member.name;
|
||||||
|
SerializeType(member.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SerializeInputOutput(shader.GetInputs());
|
SerializeInputOutput(shader.GetInputs());
|
||||||
SerializeInputOutput(shader.GetOutputs());
|
SerializeInputOutput(shader.GetOutputs());
|
||||||
|
|
||||||
m_stream << UInt32(shader.GetUniformCount());
|
m_stream << UInt32(shader.GetUniformCount());
|
||||||
for (const auto& uniform : shader.GetUniforms())
|
for (const auto& uniform : shader.GetUniforms())
|
||||||
{
|
{
|
||||||
m_stream << uniform.name << UInt32(uniform.type);
|
m_stream << uniform.name;
|
||||||
|
SerializeType(uniform.type);
|
||||||
|
|
||||||
m_stream << uniform.bindingIndex.has_value();
|
m_stream << uniform.bindingIndex.has_value();
|
||||||
if (uniform.bindingIndex)
|
if (uniform.bindingIndex)
|
||||||
m_stream << UInt32(uniform.bindingIndex.value());
|
m_stream << UInt32(uniform.bindingIndex.value());
|
||||||
|
|
||||||
|
m_stream << uniform.memoryLayout.has_value();
|
||||||
|
if (uniform.memoryLayout)
|
||||||
|
m_stream << UInt32(uniform.memoryLayout.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_stream << UInt32(shader.GetFunctionCount());
|
m_stream << UInt32(shader.GetFunctionCount());
|
||||||
|
|
@ -283,7 +320,10 @@ namespace Nz
|
||||||
|
|
||||||
m_stream << UInt32(func.parameters.size());
|
m_stream << UInt32(func.parameters.size());
|
||||||
for (const auto& param : func.parameters)
|
for (const auto& param : func.parameters)
|
||||||
m_stream << param.name << UInt32(param.type);
|
{
|
||||||
|
m_stream << param.name;
|
||||||
|
SerializeType(param.type);
|
||||||
|
}
|
||||||
|
|
||||||
Node(func.statement);
|
Node(func.statement);
|
||||||
}
|
}
|
||||||
|
|
@ -343,6 +383,16 @@ namespace Nz
|
||||||
m_stream << val;
|
m_stream << val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShaderSerializer::Value(UInt8& val)
|
||||||
|
{
|
||||||
|
m_stream << val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderSerializer::Value(UInt16& val)
|
||||||
|
{
|
||||||
|
m_stream << val;
|
||||||
|
}
|
||||||
|
|
||||||
void ShaderSerializer::Value(UInt32& val)
|
void ShaderSerializer::Value(UInt32& val)
|
||||||
{
|
{
|
||||||
m_stream << val;
|
m_stream << val;
|
||||||
|
|
@ -374,19 +424,38 @@ namespace Nz
|
||||||
|
|
||||||
ShaderAst shader;
|
ShaderAst shader;
|
||||||
|
|
||||||
|
UInt32 structCount;
|
||||||
|
m_stream >> structCount;
|
||||||
|
for (UInt32 i = 0; i < structCount; ++i)
|
||||||
|
{
|
||||||
|
std::string structName;
|
||||||
|
std::vector<ShaderAst::StructMember> members;
|
||||||
|
|
||||||
|
Value(structName);
|
||||||
|
Container(members);
|
||||||
|
|
||||||
|
for (auto& member : members)
|
||||||
|
{
|
||||||
|
Value(member.name);
|
||||||
|
Type(member.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
shader.AddStruct(std::move(structName), std::move(members));
|
||||||
|
}
|
||||||
|
|
||||||
UInt32 inputCount;
|
UInt32 inputCount;
|
||||||
m_stream >> inputCount;
|
m_stream >> inputCount;
|
||||||
for (UInt32 i = 0; i < inputCount; ++i)
|
for (UInt32 i = 0; i < inputCount; ++i)
|
||||||
{
|
{
|
||||||
std::string inputName;
|
std::string inputName;
|
||||||
ShaderNodes::ExpressionType inputType;
|
ShaderAst::Type inputType;
|
||||||
std::optional<std::size_t> location;
|
std::optional<std::size_t> location;
|
||||||
|
|
||||||
Value(inputName);
|
Value(inputName);
|
||||||
Enum(inputType);
|
Type(inputType);
|
||||||
OptVal(location);
|
OptVal(location);
|
||||||
|
|
||||||
shader.AddInput(std::move(inputName), inputType, location);
|
shader.AddInput(std::move(inputName), std::move(inputType), location);
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32 outputCount;
|
UInt32 outputCount;
|
||||||
|
|
@ -394,14 +463,14 @@ namespace Nz
|
||||||
for (UInt32 i = 0; i < outputCount; ++i)
|
for (UInt32 i = 0; i < outputCount; ++i)
|
||||||
{
|
{
|
||||||
std::string outputName;
|
std::string outputName;
|
||||||
ShaderNodes::ExpressionType outputType;
|
ShaderAst::Type outputType;
|
||||||
std::optional<std::size_t> location;
|
std::optional<std::size_t> location;
|
||||||
|
|
||||||
Value(outputName);
|
Value(outputName);
|
||||||
Enum(outputType);
|
Type(outputType);
|
||||||
OptVal(location);
|
OptVal(location);
|
||||||
|
|
||||||
shader.AddOutput(std::move(outputName), outputType, location);
|
shader.AddOutput(std::move(outputName), std::move(outputType), location);
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32 uniformCount;
|
UInt32 uniformCount;
|
||||||
|
|
@ -409,14 +478,16 @@ namespace Nz
|
||||||
for (UInt32 i = 0; i < uniformCount; ++i)
|
for (UInt32 i = 0; i < uniformCount; ++i)
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
ShaderNodes::ExpressionType type;
|
ShaderAst::Type type;
|
||||||
std::optional<std::size_t> binding;
|
std::optional<std::size_t> binding;
|
||||||
|
std::optional<ShaderNodes::MemoryLayout> memLayout;
|
||||||
|
|
||||||
Value(name);
|
Value(name);
|
||||||
Enum(type);
|
Type(type);
|
||||||
OptVal(binding);
|
OptVal(binding);
|
||||||
|
OptEnum(memLayout);
|
||||||
|
|
||||||
shader.AddUniform(std::move(name), type, binding);
|
shader.AddUniform(std::move(name), std::move(type), std::move(binding), std::move(memLayout));
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32 funcCount;
|
UInt32 funcCount;
|
||||||
|
|
@ -433,7 +504,7 @@ namespace Nz
|
||||||
for (auto& param : parameters)
|
for (auto& param : parameters)
|
||||||
{
|
{
|
||||||
Value(param.name);
|
Value(param.name);
|
||||||
Enum(param.type);
|
Type(param.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderNodes::NodePtr node;
|
ShaderNodes::NodePtr node;
|
||||||
|
|
@ -489,6 +560,36 @@ namespace Nz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShaderUnserializer::Type(ShaderAst::Type& type)
|
||||||
|
{
|
||||||
|
UInt8 typeIndex;
|
||||||
|
Value(typeIndex);
|
||||||
|
|
||||||
|
switch (typeIndex)
|
||||||
|
{
|
||||||
|
case 0: //< Primitive
|
||||||
|
{
|
||||||
|
ShaderNodes::ExpressionType exprType;
|
||||||
|
Enum(exprType);
|
||||||
|
|
||||||
|
type = exprType;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 1: //< Struct (name)
|
||||||
|
{
|
||||||
|
std::string structName;
|
||||||
|
Value(structName);
|
||||||
|
|
||||||
|
type = std::move(structName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ShaderUnserializer::Value(bool& val)
|
void ShaderUnserializer::Value(bool& val)
|
||||||
{
|
{
|
||||||
m_stream >> val;
|
m_stream >> val;
|
||||||
|
|
@ -519,6 +620,16 @@ namespace Nz
|
||||||
m_stream >> val;
|
m_stream >> val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShaderUnserializer::Value(UInt8& val)
|
||||||
|
{
|
||||||
|
m_stream >> val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderUnserializer::Value(UInt16& val)
|
||||||
|
{
|
||||||
|
m_stream >> val;
|
||||||
|
}
|
||||||
|
|
||||||
void ShaderUnserializer::Value(UInt32& val)
|
void ShaderUnserializer::Value(UInt32& val)
|
||||||
{
|
{
|
||||||
m_stream >> val;
|
m_stream >> val;
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ namespace Nz
|
||||||
return TypeMustMatch(left->GetExpressionType(), right->GetExpressionType());
|
return TypeMustMatch(left->GetExpressionType(), right->GetExpressionType());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderValidator::TypeMustMatch(ShaderNodes::ExpressionType left, ShaderNodes::ExpressionType right)
|
void ShaderValidator::TypeMustMatch(const ShaderAst::Type& left, const ShaderAst::Type& right)
|
||||||
{
|
{
|
||||||
if (left != right)
|
if (left != right)
|
||||||
throw AstError{ "Left expression type must match right expression type" };
|
throw AstError{ "Left expression type must match right expression type" };
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue