Renderer: Add support for struct and UBO
This commit is contained in:
@@ -44,15 +44,17 @@ namespace Nz
|
||||
};
|
||||
|
||||
private:
|
||||
void Append(ShaderAst::Type type);
|
||||
void Append(ShaderNodes::BuiltinEntry builtin);
|
||||
void Append(ShaderNodes::ExpressionType type);
|
||||
void Append(ShaderNodes::MemoryLayout layout);
|
||||
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 = {});
|
||||
|
||||
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 LeaveScope();
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Nz
|
||||
}
|
||||
|
||||
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())
|
||||
{
|
||||
@@ -34,27 +34,94 @@ namespace Nz
|
||||
Append(*var.locationIndex);
|
||||
Append(") ");
|
||||
}
|
||||
|
||||
if (!keyword.empty())
|
||||
{
|
||||
Append(keyword);
|
||||
Append(" ");
|
||||
}
|
||||
|
||||
Append(var.type);
|
||||
Append(" ");
|
||||
Append(var.name);
|
||||
AppendLine(";");
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, ShaderAst::Uniform>)
|
||||
{
|
||||
if (var.bindingIndex)
|
||||
if (var.bindingIndex || var.memoryLayout)
|
||||
{
|
||||
Append("layout(binding = ");
|
||||
Append(*var.bindingIndex);
|
||||
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(" ");
|
||||
}
|
||||
if (!keyword.empty())
|
||||
{
|
||||
Append(keyword);
|
||||
Append(" ");
|
||||
}
|
||||
|
||||
Append(var.type);
|
||||
Append(" ");
|
||||
Append(var.name);
|
||||
AppendLine(";");
|
||||
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();
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <Nazara/Renderer/ShaderNodes.hpp>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
namespace Nz
|
||||
@@ -21,16 +23,21 @@ namespace Nz
|
||||
struct Function;
|
||||
struct FunctionParameter;
|
||||
struct InputOutput;
|
||||
struct VariableBase;
|
||||
struct Struct;
|
||||
struct StructMember;
|
||||
struct Uniform;
|
||||
struct VariableBase;
|
||||
|
||||
using Type = std::variant<ShaderNodes::ExpressionType, std::string>;
|
||||
|
||||
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);
|
||||
void AddInput(std::string name, Type type, std::optional<std::size_t> locationIndex);
|
||||
void AddOutput(std::string name, Type type, std::optional<std::size_t> locationIndex);
|
||||
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 std::size_t GetFunctionCount() const;
|
||||
@@ -41,6 +48,9 @@ namespace Nz
|
||||
inline const InputOutput& GetOutput(std::size_t i) const;
|
||||
inline std::size_t GetOutputCount() 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 std::size_t GetUniformCount() const;
|
||||
inline const std::vector<Uniform>& GetUniforms() const;
|
||||
@@ -48,7 +58,7 @@ namespace Nz
|
||||
struct VariableBase
|
||||
{
|
||||
std::string name;
|
||||
ShaderNodes::ExpressionType type;
|
||||
Type type;
|
||||
};
|
||||
|
||||
struct FunctionParameter : VariableBase
|
||||
@@ -71,12 +81,26 @@ namespace Nz
|
||||
struct Uniform : VariableBase
|
||||
{
|
||||
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:
|
||||
std::vector<Function> m_functions;
|
||||
std::vector<InputOutput> m_inputs;
|
||||
std::vector<InputOutput> m_outputs;
|
||||
std::vector<Struct> m_structs;
|
||||
std::vector<Uniform> m_uniforms;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -55,6 +55,22 @@ namespace Nz
|
||||
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&
|
||||
{
|
||||
assert(i < m_uniforms.size());
|
||||
|
||||
@@ -56,6 +56,11 @@ namespace Nz::ShaderNodes
|
||||
DotProduct
|
||||
};
|
||||
|
||||
enum class MemoryLayout
|
||||
{
|
||||
Std140
|
||||
};
|
||||
|
||||
enum class NodeType
|
||||
{
|
||||
None = -1,
|
||||
|
||||
@@ -11,13 +11,12 @@
|
||||
#include <Nazara/Core/ByteArray.hpp>
|
||||
#include <Nazara/Core/ByteStream.hpp>
|
||||
#include <Nazara/Renderer/Config.hpp>
|
||||
#include <Nazara/Renderer/ShaderAst.hpp>
|
||||
#include <Nazara/Renderer/ShaderNodes.hpp>
|
||||
#include <Nazara/Renderer/ShaderVariables.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class ShaderAst;
|
||||
|
||||
class NAZARA_RENDERER_API ShaderSerializerBase
|
||||
{
|
||||
public:
|
||||
@@ -44,6 +43,7 @@ namespace Nz
|
||||
protected:
|
||||
template<typename T> void Container(T& container);
|
||||
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);
|
||||
|
||||
virtual bool IsWriting() const = 0;
|
||||
@@ -57,6 +57,8 @@ namespace Nz
|
||||
virtual void Value(Vector2f& val) = 0;
|
||||
virtual void Value(Vector3f& 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;
|
||||
inline void Value(std::size_t& val);
|
||||
|
||||
@@ -82,6 +84,8 @@ namespace Nz
|
||||
void Value(Vector2f& val) override;
|
||||
void Value(Vector3f& val) override;
|
||||
void Value(Vector4f& val) override;
|
||||
void Value(UInt8& val) override;
|
||||
void Value(UInt16& val) override;
|
||||
void Value(UInt32& val) override;
|
||||
void Variable(ShaderNodes::VariablePtr& var) override;
|
||||
|
||||
@@ -99,12 +103,15 @@ namespace Nz
|
||||
private:
|
||||
bool IsWriting() const override;
|
||||
void Node(ShaderNodes::NodePtr& node) override;
|
||||
void Type(ShaderAst::Type& type);
|
||||
void Value(bool& val) override;
|
||||
void Value(float& val) override;
|
||||
void Value(std::string& val) override;
|
||||
void Value(Vector2f& val) override;
|
||||
void Value(Vector3f& val) override;
|
||||
void Value(Vector4f& val) override;
|
||||
void Value(UInt8& val) override;
|
||||
void Value(UInt16& val) override;
|
||||
void Value(UInt32& val) override;
|
||||
void Variable(ShaderNodes::VariablePtr& var) override;
|
||||
|
||||
|
||||
@@ -36,6 +36,24 @@ namespace Nz
|
||||
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>
|
||||
void ShaderSerializerBase::OptVal(std::optional<T>& optVal)
|
||||
{
|
||||
|
||||
@@ -11,12 +11,11 @@
|
||||
#include <Nazara/Core/ByteArray.hpp>
|
||||
#include <Nazara/Core/ByteStream.hpp>
|
||||
#include <Nazara/Renderer/Config.hpp>
|
||||
#include <Nazara/Renderer/ShaderAst.hpp>
|
||||
#include <Nazara/Renderer/ShaderVisitor.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class ShaderAst;
|
||||
|
||||
class NAZARA_RENDERER_API ShaderValidator : public ShaderVisitor
|
||||
{
|
||||
public:
|
||||
@@ -31,7 +30,7 @@ namespace Nz
|
||||
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);
|
||||
void TypeMustMatch(const ShaderAst::Type& left, const ShaderAst::Type& right);
|
||||
|
||||
using ShaderVisitor::Visit;
|
||||
void Visit(const ShaderNodes::AssignOp& node) override;
|
||||
|
||||
Reference in New Issue
Block a user