Split shader generation to a new module

This commit is contained in:
Jérôme Leclercq
2020-08-11 00:00:36 +02:00
parent 0313f2d0a6
commit 837a6585a1
86 changed files with 564 additions and 312 deletions

View File

@@ -0,0 +1,53 @@
/*
Nazara Engine - Shader generator
Copyright (C) 2020 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#ifndef NAZARA_CONFIG_SHADER_HPP
#define NAZARA_CONFIG_SHADER_HPP
/// Each modification of a parameter needs a recompilation of the module
// Use the MemoryManager to manage dynamic allocations (can detect memory leak but allocations/frees are slower)
#define NAZARA_SHADER_MANAGE_MEMORY 0
// Activate the security tests based on the code (Advised for development)
#define NAZARA_SHADER_SAFE 1
/// Each modification of a parameter following implies a modification (often minor) of the code
/// Checking the values and types of certain constants
#include <Nazara/Shader/ConfigCheck.hpp>
#if !defined(NAZARA_STATIC)
#ifdef NAZARA_SHADER_BUILD
#define NAZARA_SHADER_API NAZARA_EXPORT
#else
#define NAZARA_SHADER_API NAZARA_IMPORT
#endif
#else
#define NAZARA_SHADER_API
#endif
#endif // NAZARA_CONFIG_SHADER_HPP

View File

@@ -0,0 +1,22 @@
// Copyright (C) YEAR AUTHORS
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_CONFIG_CHECK_SHADER_HPP
#define NAZARA_CONFIG_CHECK_SHADER_HPP
/// This file is used to check the constant values defined in Config.hpp
#include <type_traits>
#define CheckType(name, type, err) static_assert(std::is_ ##type <decltype(name)>::value, #type err)
#define CheckTypeAndVal(name, type, op, val, err) static_assert(std::is_ ##type <decltype(name)>::value && name op val, #type err)
// We force the value of MANAGE_MEMORY in debug
#if defined(NAZARA_DEBUG) && !NAZARA_SHADER_MANAGE_MEMORY
#undef NAZARA_SHADER_MANAGE_MEMORY
#define NAZARA_SHADER_MANAGE_MEMORY 0
#endif
#endif // NAZARA_CONFIG_CHECK_SHADER_HPP

View File

@@ -0,0 +1,8 @@
// Copyright (C) YEAR AUTHORS
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Shader/Config.hpp>
#if NAZARA_SHADER_MANAGE_MEMORY
#include <Nazara/Core/Debug/NewRedefinition.hpp>
#endif

View File

@@ -0,0 +1,9 @@
// Copyright (C) YEAR AUTHORS
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
// We suppose that Debug.hpp is already included, same goes for Config.hpp
#if NAZARA_SHADER_MANAGE_MEMORY
#undef delete
#undef new
#endif

View File

@@ -0,0 +1,109 @@
// 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_GLSLWRITER_HPP
#define NAZARA_GLSLWRITER_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Shader/Config.hpp>
#include <Nazara/Shader/ShaderAst.hpp>
#include <Nazara/Shader/ShaderVarVisitor.hpp>
#include <Nazara/Shader/ShaderAstVisitor.hpp>
#include <Nazara/Shader/ShaderWriter.hpp>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
namespace Nz
{
class NAZARA_SHADER_API GlslWriter : public ShaderWriter, public ShaderVarVisitor, public ShaderAstVisitor
{
public:
struct Environment;
using ExtSupportCallback = std::function<bool(const std::string_view& name)>;
GlslWriter();
GlslWriter(const GlslWriter&) = delete;
GlslWriter(GlslWriter&&) = delete;
~GlslWriter() = default;
std::string Generate(const ShaderAst& shader) override;
void SetEnv(Environment environment);
struct Environment
{
ExtSupportCallback extCallback;
unsigned int glMajorVersion = 3;
unsigned int glMinorVersion = 0;
bool glES = false;
bool flipYPosition = false;
};
private:
void Append(ShaderExpressionType type);
void Append(ShaderNodes::BuiltinEntry builtin);
void Append(ShaderNodes::BasicType 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 ShaderAst& shader, const std::vector<T>& variables, const std::string& keyword = {}, const std::string& section = {});
void EnterScope();
void LeaveScope();
using ShaderVarVisitor::Visit;
using ShaderAstVisitor::Visit;
void Visit(ShaderNodes::ExpressionPtr& expr, bool encloseIfRequired = false);
void Visit(ShaderNodes::AccessMember& node) override;
void Visit(ShaderNodes::AssignOp& node) override;
void Visit(ShaderNodes::Branch& node) override;
void Visit(ShaderNodes::BinaryOp& node) override;
void Visit(ShaderNodes::BuiltinVariable& var) override;
void Visit(ShaderNodes::Cast& node) override;
void Visit(ShaderNodes::Constant& node) override;
void Visit(ShaderNodes::DeclareVariable& node) override;
void Visit(ShaderNodes::ExpressionStatement& node) override;
void Visit(ShaderNodes::Identifier& node) override;
void Visit(ShaderNodes::InputVariable& var) override;
void Visit(ShaderNodes::IntrinsicCall& node) override;
void Visit(ShaderNodes::LocalVariable& var) override;
void Visit(ShaderNodes::ParameterVariable& var) override;
void Visit(ShaderNodes::OutputVariable& var) override;
void Visit(ShaderNodes::Sample2D& node) override;
void Visit(ShaderNodes::StatementBlock& node) override;
void Visit(ShaderNodes::SwizzleOp& node) override;
void Visit(ShaderNodes::UniformVariable& var) override;
static bool HasExplicitBinding(const ShaderAst& shader);
static bool HasExplicitLocation(const ShaderAst& shader);
struct Context
{
const ShaderAst* shader = nullptr;
const ShaderAst::Function* currentFunction = nullptr;
};
struct State
{
std::stringstream stream;
unsigned int indentLevel = 0;
};
Context m_context;
Environment m_environment;
State* m_currentState;
};
}
#include <Nazara/Shader/GlslWriter.inl>
#endif // NAZARA_GLSLWRITER_HPP

View File

@@ -0,0 +1,132 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Shader/GlslWriter.hpp>
#include <type_traits>
#include <Nazara/Shader/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 ShaderAst& shader, 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(") ");
}
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 || 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::BasicType>)
{
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();
}
}
}
#include <Nazara/Shader/DebugOff.hpp>

View File

@@ -0,0 +1,33 @@
// Copyright (C) YEAR AUTHORS
// This file is part of the "Nazara Engine - Module name"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_SHADER_HPP
#define NAZARA_SHADER_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/Initializer.hpp>
#include <Nazara/Shader/Config.hpp>
namespace Nz
{
class NAZARA_SHADER_API Shader
{
public:
Shader() = delete;
~Shader() = delete;
static bool Initialize();
static bool IsInitialized();
static void Uninitialize();
private:
static unsigned int s_moduleReferenceCounter;
};
}
#endif // NAZARA_SHADER_HPP

View File

@@ -0,0 +1,115 @@
// 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_AST_HPP
#define NAZARA_SHADER_AST_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Shader/ShaderExpressionType.hpp>
#include <Nazara/Shader/ShaderNodes.hpp>
#include <Nazara/Utility/Enums.hpp>
#include <optional>
#include <unordered_map>
#include <vector>
namespace Nz
{
class NAZARA_SHADER_API ShaderAst
{
public:
struct Function;
struct FunctionParameter;
struct InputOutput;
struct Struct;
struct StructMember;
struct Uniform;
struct VariableBase;
inline ShaderAst(ShaderStageType shaderStage);
ShaderAst(const ShaderAst&) = default;
ShaderAst(ShaderAst&&) = default;
~ShaderAst() = default;
void AddFunction(std::string name, ShaderNodes::StatementPtr statement, std::vector<FunctionParameter> parameters = {}, ShaderNodes::BasicType returnType = ShaderNodes::BasicType::Void);
void AddInput(std::string name, ShaderExpressionType type, std::optional<std::size_t> locationIndex);
void AddOutput(std::string name, ShaderExpressionType type, std::optional<std::size_t> locationIndex);
void AddStruct(std::string name, std::vector<StructMember> members);
void AddUniform(std::string name, ShaderExpressionType 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;
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 ShaderStageType GetStage() 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;
ShaderAst& operator=(const ShaderAst&) = default;
ShaderAst& operator=(ShaderAst&&) = default;
struct VariableBase
{
std::string name;
ShaderExpressionType type;
};
struct FunctionParameter : VariableBase
{
};
struct Function
{
std::string name;
std::vector<FunctionParameter> parameters;
ShaderNodes::BasicType returnType;
ShaderNodes::StatementPtr statement;
};
struct InputOutput : VariableBase
{
std::optional<std::size_t> locationIndex;
};
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;
ShaderExpressionType 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;
ShaderStageType m_stage;
};
}
#include <Nazara/Shader/ShaderAst.inl>
#endif // NAZARA_SHADER_AST_HPP

View File

@@ -0,0 +1,101 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Shader/ShaderAst.hpp>
#include <Nazara/Shader/Debug.hpp>
namespace Nz
{
inline ShaderAst::ShaderAst(ShaderStageType shaderStage) :
m_stage(shaderStage)
{
}
inline auto ShaderAst::GetFunction(std::size_t i) const -> const Function&
{
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 ShaderStageType ShaderAst::GetStage() const
{
return m_stage;
}
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());
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;
}
}
#include <Nazara/Shader/DebugOff.hpp>

View File

@@ -0,0 +1,74 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_SHADERASTCLONER_HPP
#define NAZARA_SHADERASTCLONER_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Shader/Config.hpp>
#include <Nazara/Shader/ShaderAstVisitor.hpp>
#include <Nazara/Shader/ShaderVarVisitor.hpp>
#include <vector>
namespace Nz
{
class NAZARA_SHADER_API ShaderAstCloner : public ShaderAstVisitor, public ShaderVarVisitor
{
public:
ShaderAstCloner() = default;
ShaderAstCloner(const ShaderAstCloner&) = default;
ShaderAstCloner(ShaderAstCloner&&) = default;
~ShaderAstCloner() = default;
ShaderNodes::StatementPtr Clone(const ShaderNodes::StatementPtr& statement);
ShaderAstCloner& operator=(const ShaderAstCloner&) = default;
ShaderAstCloner& operator=(ShaderAstCloner&&) = default;
protected:
ShaderNodes::ExpressionPtr CloneExpression(const ShaderNodes::ExpressionPtr& expr);
ShaderNodes::StatementPtr CloneStatement(const ShaderNodes::StatementPtr& statement);
ShaderNodes::VariablePtr CloneVariable(const ShaderNodes::VariablePtr& statement);
void Visit(ShaderNodes::AccessMember& node) override;
void Visit(ShaderNodes::AssignOp& node) override;
void Visit(ShaderNodes::BinaryOp& node) override;
void Visit(ShaderNodes::Branch& node) override;
void Visit(ShaderNodes::Cast& node) override;
void Visit(ShaderNodes::Constant& node) override;
void Visit(ShaderNodes::DeclareVariable& node) override;
void Visit(ShaderNodes::ExpressionStatement& node) override;
void Visit(ShaderNodes::Identifier& node) override;
void Visit(ShaderNodes::IntrinsicCall& node) override;
void Visit(ShaderNodes::Sample2D& node) override;
void Visit(ShaderNodes::StatementBlock& node) override;
void Visit(ShaderNodes::SwizzleOp& node) override;
void Visit(ShaderNodes::BuiltinVariable& var) override;
void Visit(ShaderNodes::InputVariable& var) override;
void Visit(ShaderNodes::LocalVariable& var) override;
void Visit(ShaderNodes::OutputVariable& var) override;
void Visit(ShaderNodes::ParameterVariable& var) override;
void Visit(ShaderNodes::UniformVariable& var) override;
void PushExpression(ShaderNodes::ExpressionPtr expression);
void PushStatement(ShaderNodes::StatementPtr statement);
void PushVariable(ShaderNodes::VariablePtr variable);
ShaderNodes::ExpressionPtr PopExpression();
ShaderNodes::StatementPtr PopStatement();
ShaderNodes::VariablePtr PopVariable();
private:
std::vector<ShaderNodes::ExpressionPtr> m_expressionStack;
std::vector<ShaderNodes::StatementPtr> m_statementStack;
std::vector<ShaderNodes::VariablePtr> m_variableStack;
};
}
#include <Nazara/Shader/ShaderAstCloner.inl>
#endif

View File

@@ -0,0 +1,12 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Shader/ShaderAstCloner.hpp>
#include <Nazara/Shader/Debug.hpp>
namespace Nz
{
}
#include <Nazara/Shader/DebugOff.hpp>

View File

@@ -0,0 +1,42 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_SHADER_RECURSIVE_VISITOR_HPP
#define NAZARA_SHADER_RECURSIVE_VISITOR_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Shader/Config.hpp>
#include <Nazara/Shader/ShaderAstVisitor.hpp>
namespace Nz
{
class NAZARA_SHADER_API ShaderAstRecursiveVisitor : public ShaderAstVisitor
{
public:
ShaderAstRecursiveVisitor() = default;
~ShaderAstRecursiveVisitor() = default;
using ShaderAstVisitor::Visit;
void Visit(ShaderNodes::AccessMember& node) override;
void Visit(ShaderNodes::AssignOp& node) override;
void Visit(ShaderNodes::BinaryOp& node) override;
void Visit(ShaderNodes::Branch& node) override;
void Visit(ShaderNodes::Cast& node) override;
void Visit(ShaderNodes::Constant& node) override;
void Visit(ShaderNodes::DeclareVariable& node) override;
void Visit(ShaderNodes::ExpressionStatement& node) override;
void Visit(ShaderNodes::Identifier& node) override;
void Visit(ShaderNodes::IntrinsicCall& node) override;
void Visit(ShaderNodes::Sample2D& node) override;
void Visit(ShaderNodes::StatementBlock& node) override;
void Visit(ShaderNodes::SwizzleOp& node) override;
};
}
#include <Nazara/Shader/ShaderAstRecursiveVisitor.inl>
#endif

View File

@@ -0,0 +1,12 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Shader/ShaderAstRecursiveVisitor.hpp>
#include <Nazara/Shader/Debug.hpp>
namespace Nz
{
}
#include <Nazara/Shader/DebugOff.hpp>

View File

@@ -0,0 +1,143 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_SHADERSERIALIZER_HPP
#define NAZARA_SHADERSERIALIZER_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/ByteArray.hpp>
#include <Nazara/Core/ByteStream.hpp>
#include <Nazara/Shader/Config.hpp>
#include <Nazara/Shader/ShaderAst.hpp>
#include <Nazara/Shader/ShaderNodes.hpp>
#include <Nazara/Shader/ShaderVariables.hpp>
namespace Nz
{
class NAZARA_SHADER_API ShaderAstSerializerBase
{
public:
ShaderAstSerializerBase() = default;
ShaderAstSerializerBase(const ShaderAstSerializerBase&) = delete;
ShaderAstSerializerBase(ShaderAstSerializerBase&&) = delete;
~ShaderAstSerializerBase() = default;
void Serialize(ShaderNodes::AccessMember& node);
void Serialize(ShaderNodes::AssignOp& node);
void Serialize(ShaderNodes::BinaryOp& node);
void Serialize(ShaderNodes::BuiltinVariable& var);
void Serialize(ShaderNodes::Branch& node);
void Serialize(ShaderNodes::Cast& node);
void Serialize(ShaderNodes::Constant& node);
void Serialize(ShaderNodes::DeclareVariable& node);
void Serialize(ShaderNodes::ExpressionStatement& node);
void Serialize(ShaderNodes::Identifier& node);
void Serialize(ShaderNodes::IntrinsicCall& node);
void Serialize(ShaderNodes::NamedVariable& var);
void Serialize(ShaderNodes::Sample2D& node);
void Serialize(ShaderNodes::StatementBlock& node);
void Serialize(ShaderNodes::SwizzleOp& node);
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;
virtual void Node(ShaderNodes::NodePtr& node) = 0;
template<typename T> void Node(std::shared_ptr<T>& node);
virtual void Type(ShaderExpressionType& type) = 0;
virtual void Value(bool& val) = 0;
virtual void Value(float& val) = 0;
virtual void Value(std::string& val) = 0;
virtual void Value(Int32& val) = 0;
virtual void Value(Vector2f& val) = 0;
virtual void Value(Vector3f& val) = 0;
virtual void Value(Vector4f& val) = 0;
virtual void Value(Vector2i32& val) = 0;
virtual void Value(Vector3i32& val) = 0;
virtual void Value(Vector4i32& 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);
virtual void Variable(ShaderNodes::VariablePtr& var) = 0;
template<typename T> void Variable(std::shared_ptr<T>& var);
};
class NAZARA_SHADER_API ShaderAstSerializer final : public ShaderAstSerializerBase
{
public:
inline ShaderAstSerializer(ByteStream& stream);
~ShaderAstSerializer() = default;
void Serialize(const ShaderAst& shader);
private:
bool IsWriting() const override;
void Node(const ShaderNodes::NodePtr& node);
void Node(ShaderNodes::NodePtr& node) override;
void Type(ShaderExpressionType& type) override;
void Value(bool& val) override;
void Value(float& val) override;
void Value(std::string& val) override;
void Value(Int32& val) override;
void Value(Vector2f& val) override;
void Value(Vector3f& val) override;
void Value(Vector4f& val) override;
void Value(Vector2i32& val) override;
void Value(Vector3i32& val) override;
void Value(Vector4i32& val) override;
void Value(UInt8& val) override;
void Value(UInt16& val) override;
void Value(UInt32& val) override;
void Variable(ShaderNodes::VariablePtr& var) override;
ByteStream& m_stream;
};
class NAZARA_SHADER_API ShaderAstUnserializer final : public ShaderAstSerializerBase
{
public:
ShaderAstUnserializer(ByteStream& stream);
~ShaderAstUnserializer() = default;
ShaderAst Unserialize();
private:
bool IsWriting() const override;
void Node(ShaderNodes::NodePtr& node) override;
void Type(ShaderExpressionType& type) override;
void Value(bool& val) override;
void Value(float& val) override;
void Value(std::string& val) override;
void Value(Int32& val) override;
void Value(Vector2f& val) override;
void Value(Vector3f& val) override;
void Value(Vector4f& val) override;
void Value(Vector2i32& val) override;
void Value(Vector3i32& val) override;
void Value(Vector4i32& val) override;
void Value(UInt8& val) override;
void Value(UInt16& val) override;
void Value(UInt32& val) override;
void Variable(ShaderNodes::VariablePtr& var) override;
ByteStream& m_stream;
};
NAZARA_SHADER_API ByteArray SerializeShader(const ShaderAst& shader);
NAZARA_SHADER_API ShaderAst UnserializeShader(ByteStream& stream);
}
#include <Nazara/Shader/ShaderAstSerializer.inl>
#endif

View File

@@ -0,0 +1,127 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Shader/ShaderAstSerializer.hpp>
#include <Nazara/Shader/Debug.hpp>
namespace Nz
{
template<typename T>
void ShaderAstSerializerBase::Container(T& container)
{
bool isWriting = IsWriting();
UInt32 size;
if (isWriting)
size = UInt32(container.size());
Value(size);
if (!isWriting)
container.resize(size);
}
template<typename T>
void ShaderAstSerializerBase::Enum(T& enumVal)
{
bool isWriting = IsWriting();
UInt32 value;
if (isWriting)
value = static_cast<UInt32>(enumVal);
Value(value);
if (!isWriting)
enumVal = static_cast<T>(value);
}
template<typename T>
void ShaderAstSerializerBase::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 ShaderAstSerializerBase::OptVal(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())
Value(optVal.value());
}
template<typename T>
void ShaderAstSerializerBase::Node(std::shared_ptr<T>& node)
{
bool isWriting = IsWriting();
ShaderNodes::NodePtr value;
if (isWriting)
value = node;
Node(value);
if (!isWriting)
node = std::static_pointer_cast<T>(value);
}
template<typename T>
void ShaderAstSerializerBase::Variable(std::shared_ptr<T>& var)
{
bool isWriting = IsWriting();
ShaderNodes::VariablePtr value;
if (isWriting)
value = var;
Variable(value);
if (!isWriting)
var = std::static_pointer_cast<T>(value);
}
inline void ShaderAstSerializerBase::Value(std::size_t& val)
{
bool isWriting = IsWriting();
UInt32 value;
if (isWriting)
value = static_cast<UInt32>(val);
Value(value);
if (!isWriting)
val = static_cast<std::size_t>(value);
}
inline ShaderAstSerializer::ShaderAstSerializer(ByteStream& stream) :
m_stream(stream)
{
}
inline ShaderAstUnserializer::ShaderAstUnserializer(ByteStream& stream) :
m_stream(stream)
{
}
}
#include <Nazara/Shader/DebugOff.hpp>

View File

@@ -0,0 +1,70 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_SHADERVALIDATOR_HPP
#define NAZARA_SHADERVALIDATOR_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/ByteArray.hpp>
#include <Nazara/Core/ByteStream.hpp>
#include <Nazara/Shader/Config.hpp>
#include <Nazara/Shader/ShaderAst.hpp>
#include <Nazara/Shader/ShaderAstRecursiveVisitor.hpp>
#include <Nazara/Shader/ShaderVarVisitor.hpp>
namespace Nz
{
class NAZARA_SHADER_API ShaderAstValidator : public ShaderAstRecursiveVisitor, public ShaderVarVisitor
{
public:
inline ShaderAstValidator(const ShaderAst& shader);
ShaderAstValidator(const ShaderAstValidator&) = delete;
ShaderAstValidator(ShaderAstValidator&&) = delete;
~ShaderAstValidator() = default;
bool Validate(std::string* error = nullptr);
private:
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(const ShaderExpressionType& left, const ShaderExpressionType& right);
using ShaderAstRecursiveVisitor::Visit;
void Visit(ShaderNodes::AccessMember& node) override;
void Visit(ShaderNodes::AssignOp& node) override;
void Visit(ShaderNodes::BinaryOp& node) override;
void Visit(ShaderNodes::Branch& node) override;
void Visit(ShaderNodes::Cast& node) override;
void Visit(ShaderNodes::Constant& node) override;
void Visit(ShaderNodes::DeclareVariable& node) override;
void Visit(ShaderNodes::ExpressionStatement& node) override;
void Visit(ShaderNodes::Identifier& node) override;
void Visit(ShaderNodes::IntrinsicCall& node) override;
void Visit(ShaderNodes::Sample2D& node) override;
void Visit(ShaderNodes::StatementBlock& node) override;
void Visit(ShaderNodes::SwizzleOp& node) override;
using ShaderVarVisitor::Visit;
void Visit(ShaderNodes::BuiltinVariable& var) override;
void Visit(ShaderNodes::InputVariable& var) override;
void Visit(ShaderNodes::LocalVariable& var) override;
void Visit(ShaderNodes::OutputVariable& var) override;
void Visit(ShaderNodes::ParameterVariable& var) override;
void Visit(ShaderNodes::UniformVariable& var) override;
struct Context;
const ShaderAst& m_shader;
Context* m_context;
};
NAZARA_SHADER_API bool ValidateShader(const ShaderAst& shader, std::string* error = nullptr);
}
#include <Nazara/Shader/ShaderAstValidator.inl>
#endif

View File

@@ -0,0 +1,16 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Shader/ShaderAstValidator.hpp>
#include <Nazara/Shader/Debug.hpp>
namespace Nz
{
ShaderAstValidator::ShaderAstValidator(const ShaderAst& shader) :
m_shader(shader)
{
}
}
#include <Nazara/Shader/DebugOff.hpp>

View File

@@ -0,0 +1,50 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_SHADERVISITOR_HPP
#define NAZARA_SHADERVISITOR_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Shader/Config.hpp>
#include <Nazara/Shader/ShaderNodes.hpp>
#include <string>
#include <unordered_set>
namespace Nz
{
class NAZARA_SHADER_API ShaderAstVisitor
{
public:
ShaderAstVisitor() = default;
ShaderAstVisitor(const ShaderAstVisitor&) = delete;
ShaderAstVisitor(ShaderAstVisitor&&) = delete;
virtual ~ShaderAstVisitor();
void EnableCondition(const std::string& name, bool cond);
bool IsConditionEnabled(const std::string& name) const;
void Visit(const ShaderNodes::NodePtr& node);
virtual void Visit(ShaderNodes::AccessMember& node) = 0;
virtual void Visit(ShaderNodes::AssignOp& node) = 0;
virtual void Visit(ShaderNodes::BinaryOp& node) = 0;
virtual void Visit(ShaderNodes::Branch& node) = 0;
virtual void Visit(ShaderNodes::Cast& node) = 0;
virtual void Visit(ShaderNodes::Constant& node) = 0;
virtual void Visit(ShaderNodes::DeclareVariable& node) = 0;
virtual void Visit(ShaderNodes::ExpressionStatement& node) = 0;
virtual void Visit(ShaderNodes::Identifier& node) = 0;
virtual void Visit(ShaderNodes::IntrinsicCall& node) = 0;
virtual void Visit(ShaderNodes::Sample2D& node) = 0;
virtual void Visit(ShaderNodes::StatementBlock& node) = 0;
virtual void Visit(ShaderNodes::SwizzleOp& node) = 0;
private:
std::unordered_set<std::string> m_conditions;
};
}
#endif

View File

@@ -0,0 +1,76 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_SHADER_BUILDER_HPP
#define NAZARA_SHADER_BUILDER_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Shader/ShaderNodes.hpp>
#include <memory>
namespace Nz::ShaderBuilder
{
template<ShaderNodes::AssignType op>
struct AssignOpBuilder
{
constexpr AssignOpBuilder() = default;
std::shared_ptr<ShaderNodes::AssignOp> operator()(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right) const;
};
template<ShaderNodes::BinaryType op>
struct BinOpBuilder
{
constexpr BinOpBuilder() = default;
std::shared_ptr<ShaderNodes::BinaryOp> operator()(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right) const;
};
struct BuiltinBuilder
{
constexpr BuiltinBuilder() = default;
inline std::shared_ptr<ShaderNodes::Variable> operator()(ShaderNodes::BuiltinEntry builtin) const;
};
template<typename T>
struct GenBuilder
{
constexpr GenBuilder() = default;
template<typename... Args> std::shared_ptr<T> operator()(Args&&... args) const;
};
constexpr GenBuilder<ShaderNodes::AccessMember> AccessMember;
constexpr BinOpBuilder<ShaderNodes::BinaryType::Add> Add;
constexpr AssignOpBuilder<ShaderNodes::AssignType::Simple> Assign;
constexpr BuiltinBuilder Builtin;
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<ShaderNodes::BasicType Type, typename... Args> std::shared_ptr<ShaderNodes::Cast> Cast(Args&&... args);
}
#include <Nazara/Shader/ShaderBuilder.inl>
#endif // NAZARA_SHADER_BUILDER_HPP

View File

@@ -0,0 +1,52 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Shader/ShaderBuilder.hpp>
#include <Nazara/Shader/Debug.hpp>
namespace Nz::ShaderBuilder
{
template<typename T>
template<typename... Args>
std::shared_ptr<T> GenBuilder<T>::operator()(Args&&... args) const
{
return T::Build(std::forward<Args>(args)...);
}
template<ShaderNodes::AssignType op>
std::shared_ptr<ShaderNodes::AssignOp> AssignOpBuilder<op>::operator()(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right) const
{
return ShaderNodes::AssignOp::Build(op, left, right);
}
template<ShaderNodes::BinaryType op>
std::shared_ptr<ShaderNodes::BinaryOp> BinOpBuilder<op>::operator()(const ShaderNodes::ExpressionPtr& left, const ShaderNodes::ExpressionPtr& right) const
{
return ShaderNodes::BinaryOp::Build(op, left, right);
}
inline std::shared_ptr<ShaderNodes::Variable> BuiltinBuilder::operator()(ShaderNodes::BuiltinEntry builtin) const
{
ShaderNodes::BasicType exprType = ShaderNodes::BasicType::Void;
switch (builtin)
{
case ShaderNodes::BuiltinEntry::VertexPosition:
exprType = ShaderNodes::BasicType::Float4;
break;
}
NazaraAssert(exprType != ShaderNodes::BasicType::Void, "Unhandled builtin");
return ShaderNodes::BuiltinVariable::Build(builtin, exprType);
}
template<ShaderNodes::BasicType Type, typename... Args>
std::shared_ptr<ShaderNodes::Cast> Cast(Args&&... args)
{
return ShaderNodes::Cast::Build(Type, std::forward<Args>(args)...);
}
}
#include <Nazara/Shader/DebugOff.hpp>

View File

@@ -0,0 +1,118 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// 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 BasicType
{
Boolean, //< bool
Float1, //< float
Float2, //< vec2
Float3, //< vec3
Float4, //< vec4
Int1, //< int
Int2, //< ivec2
Int3, //< ivec3
Int4, //< ivec4
Mat4x4, //< mat4
Sampler2D, //< sampler2D
Void //< void
};
enum class BinaryType
{
Add, //< +
Substract, //< -
Multiply, //< *
Divide, //< /
Equality //< ==
};
enum class BuiltinEntry
{
VertexPosition, // gl_Position
};
enum class ExpressionCategory
{
LValue,
RValue
};
enum class IntrinsicType
{
CrossProduct,
DotProduct
};
enum class MemoryLayout
{
Std140
};
enum class NodeType
{
None = -1,
AccessMember,
AssignOp,
BinaryOp,
Branch,
Cast,
Constant,
ConditionalStatement,
DeclareVariable,
ExpressionStatement,
Identifier,
IntrinsicCall,
Sample2D,
SwizzleOp,
StatementBlock
};
enum class SsaInstruction
{
OpAdd,
OpDiv,
OpMul,
OpSub,
OpSample
};
enum class SwizzleComponent
{
First,
Second,
Third,
Fourth
};
enum class VariableType
{
None = -1,
BuiltinVariable,
InputVariable,
LocalVariable,
OutputVariable,
ParameterVariable,
UniformVariable
};
}
#endif // NAZARA_SHADER_ENUMS_HPP

View File

@@ -0,0 +1,20 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_SHADER_EXPRESSIONTYPE_HPP
#define NAZARA_SHADER_EXPRESSIONTYPE_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Shader/ShaderEnums.hpp>
#include <string>
#include <variant>
namespace Nz
{
using ShaderExpressionType = std::variant<ShaderNodes::BasicType, std::string>;
}
#endif // NAZARA_SHADER_EXPRESSIONTYPE_HPP

View File

@@ -0,0 +1,292 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// 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/Shader/Config.hpp>
#include <Nazara/Shader/ShaderEnums.hpp>
#include <Nazara/Shader/ShaderExpressionType.hpp>
#include <Nazara/Shader/ShaderVariables.hpp>
#include <array>
#include <optional>
#include <string>
namespace Nz
{
class ShaderAstVisitor;
namespace ShaderNodes
{
class Node;
using NodePtr = std::shared_ptr<Node>;
class NAZARA_SHADER_API Node
{
public:
virtual ~Node();
inline NodeType GetType() const;
inline bool IsStatement() const;
virtual void Visit(ShaderAstVisitor& visitor) = 0;
static inline unsigned int GetComponentCount(BasicType type);
static inline BasicType GetComponentType(BasicType type);
protected:
inline Node(NodeType type, bool isStatement);
private:
NodeType m_type;
bool m_isStatement;
};
class Expression;
using ExpressionPtr = std::shared_ptr<Expression>;
class NAZARA_SHADER_API Expression : public Node
{
public:
inline Expression(NodeType type);
virtual ExpressionCategory GetExpressionCategory() const;
virtual ShaderExpressionType GetExpressionType() const = 0;
};
class Statement;
using StatementPtr = std::shared_ptr<Statement>;
class NAZARA_SHADER_API Statement : public Node
{
public:
inline Statement(NodeType type);
};
struct NAZARA_SHADER_API ExpressionStatement : public Statement
{
inline ExpressionStatement();
void Visit(ShaderAstVisitor& visitor) override;
ExpressionPtr expression;
static inline std::shared_ptr<ExpressionStatement> Build(ExpressionPtr expr);
};
//////////////////////////////////////////////////////////////////////////
struct NAZARA_SHADER_API ConditionalStatement : public Statement
{
inline ConditionalStatement();
void Visit(ShaderAstVisitor& visitor) override;
std::string conditionName;
StatementPtr statement;
static inline std::shared_ptr<ConditionalStatement> Build(std::string condition, StatementPtr statementPtr);
};
struct NAZARA_SHADER_API StatementBlock : public Statement
{
inline StatementBlock();
void Visit(ShaderAstVisitor& visitor) override;
std::vector<StatementPtr> statements;
static inline std::shared_ptr<StatementBlock> Build(std::vector<StatementPtr> statements);
template<typename... Args> static std::shared_ptr<StatementBlock> Build(Args&&... args);
};
struct NAZARA_SHADER_API DeclareVariable : public Statement
{
inline DeclareVariable();
void Visit(ShaderAstVisitor& visitor) override;
ExpressionPtr expression;
VariablePtr variable;
static inline std::shared_ptr<DeclareVariable> Build(VariablePtr variable, ExpressionPtr expression = nullptr);
};
struct NAZARA_SHADER_API Identifier : public Expression
{
inline Identifier();
ExpressionCategory GetExpressionCategory() const override;
ShaderExpressionType GetExpressionType() const override;
void Visit(ShaderAstVisitor& visitor) override;
VariablePtr var;
static inline std::shared_ptr<Identifier> Build(VariablePtr variable);
};
struct NAZARA_SHADER_API AccessMember : public Expression
{
inline AccessMember();
ExpressionCategory GetExpressionCategory() const override;
ShaderExpressionType GetExpressionType() const override;
void Visit(ShaderAstVisitor& visitor) override;
std::size_t memberIndex;
ExpressionPtr structExpr;
ShaderExpressionType exprType;
static inline std::shared_ptr<AccessMember> Build(ExpressionPtr structExpr, std::size_t memberIndex, ShaderExpressionType exprType);
};
//////////////////////////////////////////////////////////////////////////
struct NAZARA_SHADER_API AssignOp : public Expression
{
inline AssignOp();
ShaderExpressionType GetExpressionType() const override;
void Visit(ShaderAstVisitor& visitor) override;
AssignType op;
ExpressionPtr left;
ExpressionPtr right;
static inline std::shared_ptr<AssignOp> Build(AssignType op, ExpressionPtr left, ExpressionPtr right);
};
struct NAZARA_SHADER_API BinaryOp : public Expression
{
inline BinaryOp();
ShaderExpressionType GetExpressionType() const override;
void Visit(ShaderAstVisitor& visitor) override;
BinaryType op;
ExpressionPtr left;
ExpressionPtr right;
static inline std::shared_ptr<BinaryOp> Build(BinaryType op, ExpressionPtr left, ExpressionPtr right);
};
struct NAZARA_SHADER_API Branch : public Statement
{
struct ConditionalStatement;
inline Branch();
void Visit(ShaderAstVisitor& visitor) override;
std::vector<ConditionalStatement> condStatements;
StatementPtr elseStatement;
struct ConditionalStatement
{
ExpressionPtr condition;
StatementPtr statement;
};
static inline std::shared_ptr<Branch> Build(ExpressionPtr condition, StatementPtr trueStatement, StatementPtr falseStatement = nullptr);
static inline std::shared_ptr<Branch> Build(std::vector<ConditionalStatement> statements, StatementPtr elseStatement = nullptr);
};
struct NAZARA_SHADER_API Cast : public Expression
{
inline Cast();
ShaderExpressionType GetExpressionType() const override;
void Visit(ShaderAstVisitor& visitor) override;
BasicType exprType;
std::array<ExpressionPtr, 4> expressions;
static inline std::shared_ptr<Cast> Build(BasicType castTo, ExpressionPtr first, ExpressionPtr second = nullptr, ExpressionPtr third = nullptr, ExpressionPtr fourth = nullptr);
static inline std::shared_ptr<Cast> Build(BasicType castTo, ExpressionPtr* expressions, std::size_t expressionCount);
};
struct NAZARA_SHADER_API Constant : public Expression
{
inline Constant();
ShaderExpressionType GetExpressionType() const override;
void Visit(ShaderAstVisitor& visitor) override;
using Variant = std::variant<
bool,
float,
Int32,
Vector2f,
Vector3f,
Vector4f,
Vector2i32,
Vector3i32,
Vector4i32
>;
Variant value;
template<typename T> static std::shared_ptr<Constant> Build(const T& value);
};
struct NAZARA_SHADER_API SwizzleOp : public Expression
{
inline SwizzleOp();
ExpressionCategory GetExpressionCategory() const override;
ShaderExpressionType GetExpressionType() const override;
void Visit(ShaderAstVisitor& 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);
static inline std::shared_ptr<SwizzleOp> Build(ExpressionPtr expressionPtr, const SwizzleComponent* components, std::size_t componentCount);
};
//////////////////////////////////////////////////////////////////////////
struct NAZARA_SHADER_API Sample2D : public Expression
{
inline Sample2D();
ShaderExpressionType GetExpressionType() const override;
void Visit(ShaderAstVisitor& visitor) override;
ExpressionPtr sampler;
ExpressionPtr coordinates;
static inline std::shared_ptr<Sample2D> Build(ExpressionPtr samplerPtr, ExpressionPtr coordinatesPtr);
};
//////////////////////////////////////////////////////////////////////////
struct NAZARA_SHADER_API IntrinsicCall : public Expression
{
inline IntrinsicCall();
ShaderExpressionType GetExpressionType() const override;
void Visit(ShaderAstVisitor& visitor) override;
IntrinsicType intrinsic;
std::vector<ExpressionPtr> parameters;
static inline std::shared_ptr<IntrinsicCall> Build(IntrinsicType intrinsic, std::vector<ExpressionPtr> parameters);
};
}
}
#include <Nazara/Shader/ShaderNodes.inl>
#endif

View File

@@ -0,0 +1,338 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Shader/ShaderNodes.hpp>
#include <Nazara/Shader/Debug.hpp>
namespace Nz::ShaderNodes
{
inline Node::Node(NodeType type, bool isStatement) :
m_type(type),
m_isStatement(isStatement)
{
}
inline NodeType ShaderNodes::Node::GetType() const
{
return m_type;
}
inline bool Node::IsStatement() const
{
return m_isStatement;
}
inline unsigned int Node::GetComponentCount(BasicType type)
{
switch (type)
{
case BasicType::Float2:
case BasicType::Int2:
return 2;
case BasicType::Float3:
case BasicType::Int3:
return 3;
case BasicType::Float4:
case BasicType::Int4:
return 4;
case BasicType::Mat4x4:
return 4;
default:
return 1;
}
}
inline BasicType Node::GetComponentType(BasicType type)
{
switch (type)
{
case BasicType::Float2:
case BasicType::Float3:
case BasicType::Float4:
return BasicType::Float1;
case BasicType::Int2:
case BasicType::Int3:
case BasicType::Int4:
return BasicType::Int1;
case BasicType::Mat4x4:
return BasicType::Float4;
default:
return type;
}
}
inline Expression::Expression(NodeType type) :
Node(type, false)
{
}
inline Statement::Statement(NodeType type) :
Node(type, true)
{
}
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)
{
}
inline std::shared_ptr<StatementBlock> StatementBlock::Build(std::vector<StatementPtr> statements)
{
auto node = std::make_shared<StatementBlock>();
node->statements = std::move(statements);
return node;
}
template<typename... Args>
std::shared_ptr<StatementBlock> StatementBlock::Build(Args&&... args)
{
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(VariablePtr 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 AccessMember::AccessMember() :
Expression(NodeType::AccessMember)
{
}
inline std::shared_ptr<AccessMember> AccessMember::Build(ExpressionPtr structExpr, std::size_t memberIndex, ShaderExpressionType exprType)
{
auto node = std::make_shared<AccessMember>();
node->exprType = std::move(exprType);
node->memberIndex = memberIndex;
node->structExpr = std::move(structExpr);
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 std::shared_ptr<Branch> Branch::Build(std::vector<ConditionalStatement> statements, StatementPtr elseStatement)
{
auto node = std::make_shared<Branch>();
node->condStatements = std::move(statements);
node->elseStatement = std::move(elseStatement);
return node;
}
inline Cast::Cast() :
Expression(NodeType::Cast)
{
}
inline std::shared_ptr<Cast> Cast::Build(BasicType 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(BasicType 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)
{
}
template<typename T>
std::shared_ptr<Constant> Nz::ShaderNodes::Constant::Build(const T& value)
{
auto node = std::make_shared<Constant>();
node->value = 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 std::shared_ptr<SwizzleOp> SwizzleOp::Build(ExpressionPtr expressionPtr, const SwizzleComponent* components, std::size_t componentCount)
{
auto node = std::make_shared<SwizzleOp>();
assert(componentCount < node->components.size());
node->componentCount = componentCount;
node->expression = std::move(expressionPtr);
std::copy(components, components + componentCount, node->components.begin());
return node;
}
inline Sample2D::Sample2D() :
Expression(NodeType::Sample2D)
{
}
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/Shader/DebugOff.hpp>

View File

@@ -0,0 +1,35 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// 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/Shader/Config.hpp>
#include <Nazara/Shader/ShaderVariables.hpp>
namespace Nz
{
class NAZARA_SHADER_API ShaderVarVisitor
{
public:
ShaderVarVisitor() = default;
ShaderVarVisitor(const ShaderVarVisitor&) = delete;
ShaderVarVisitor(ShaderVarVisitor&&) = delete;
virtual ~ShaderVarVisitor();
void Visit(const ShaderNodes::VariablePtr& node);
virtual void Visit(ShaderNodes::BuiltinVariable& var) = 0;
virtual void Visit(ShaderNodes::InputVariable& var) = 0;
virtual void Visit(ShaderNodes::LocalVariable& var) = 0;
virtual void Visit(ShaderNodes::OutputVariable& var) = 0;
virtual void Visit(ShaderNodes::ParameterVariable& var) = 0;
virtual void Visit(ShaderNodes::UniformVariable& var) = 0;
};
}
#endif

View File

@@ -0,0 +1,128 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// 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/Shader/Config.hpp>
#include <Nazara/Shader/ShaderExpressionType.hpp>
#include <array>
#include <memory>
#include <optional>
#include <string>
namespace Nz
{
class ShaderVarVisitor;
namespace ShaderNodes
{
struct Variable;
using VariablePtr = std::shared_ptr<Variable>;
struct NAZARA_SHADER_API Variable : std::enable_shared_from_this<Variable>
{
virtual ~Variable();
virtual VariableType GetType() const = 0;
virtual void Visit(ShaderVarVisitor& visitor) = 0;
ShaderExpressionType type;
};
struct BuiltinVariable;
using BuiltinVariablePtr = std::shared_ptr<BuiltinVariable>;
struct NAZARA_SHADER_API BuiltinVariable : public Variable
{
BuiltinEntry entry;
VariableType GetType() const override;
void Visit(ShaderVarVisitor& visitor) override;
static inline std::shared_ptr<BuiltinVariable> Build(BuiltinEntry entry, ShaderExpressionType varType);
};
struct NamedVariable;
using NamedVariablePtr = std::shared_ptr<NamedVariable>;
struct NAZARA_SHADER_API NamedVariable : public Variable
{
std::string name;
};
struct InputVariable;
using InputVariablePtr = std::shared_ptr<InputVariable>;
struct NAZARA_SHADER_API InputVariable : public NamedVariable
{
VariableType GetType() const override;
void Visit(ShaderVarVisitor& visitor) override;
static inline std::shared_ptr<InputVariable> Build(std::string varName, ShaderExpressionType varType);
};
struct LocalVariable;
using LocalVariablePtr = std::shared_ptr<LocalVariable>;
struct NAZARA_SHADER_API LocalVariable : public NamedVariable
{
VariableType GetType() const override;
void Visit(ShaderVarVisitor& visitor) override;
static inline std::shared_ptr<LocalVariable> Build(std::string varName, ShaderExpressionType varType);
};
struct OutputVariable;
using OutputVariablePtr = std::shared_ptr<OutputVariable>;
struct NAZARA_SHADER_API OutputVariable : public NamedVariable
{
VariableType GetType() const override;
void Visit(ShaderVarVisitor& visitor) override;
static inline std::shared_ptr<OutputVariable> Build(std::string varName, ShaderExpressionType varType);
};
struct ParameterVariable;
using ParameterVariablePtr = std::shared_ptr<ParameterVariable>;
struct NAZARA_SHADER_API ParameterVariable : public NamedVariable
{
VariableType GetType() const override;
void Visit(ShaderVarVisitor& visitor) override;
static inline std::shared_ptr<ParameterVariable> Build(std::string varName, ShaderExpressionType varType);
};
struct UniformVariable;
using UniformVariablePtr = std::shared_ptr<UniformVariable>;
struct NAZARA_SHADER_API UniformVariable : public NamedVariable
{
VariableType GetType() const override;
void Visit(ShaderVarVisitor& visitor) override;
static inline std::shared_ptr<UniformVariable> Build(std::string varName, ShaderExpressionType varType);
};
}
}
#include <Nazara/Shader/ShaderVariables.inl>
#endif

View File

@@ -0,0 +1,65 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Shader/ShaderVariables.hpp>
#include <Nazara/Shader/Debug.hpp>
namespace Nz::ShaderNodes
{
inline std::shared_ptr<BuiltinVariable> BuiltinVariable::Build(BuiltinEntry variable, ShaderExpressionType 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, ShaderExpressionType 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, ShaderExpressionType 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, ShaderExpressionType 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, ShaderExpressionType 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, ShaderExpressionType varType)
{
auto node = std::make_shared<UniformVariable>();
node->name = std::move(varName);
node->type = varType;
return node;
}
}
#include <Nazara/Shader/DebugOff.hpp>

View File

@@ -0,0 +1,30 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_SHADERWRITER_HPP
#define NAZARA_SHADERWRITER_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Shader/Config.hpp>
#include <string>
namespace Nz
{
class ShaderAst;
class NAZARA_SHADER_API ShaderWriter
{
public:
ShaderWriter() = default;
ShaderWriter(const ShaderWriter&) = default;
ShaderWriter(ShaderWriter&&) = default;
virtual ~ShaderWriter();
virtual std::string Generate(const ShaderAst& shader) = 0;
};
}
#endif // NAZARA_SHADERWRITER_HPP

View File

@@ -0,0 +1,132 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_SPIRVWRITER_HPP
#define NAZARA_SPIRVWRITER_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Shader/Config.hpp>
#include <Nazara/Shader/ShaderAst.hpp>
#include <Nazara/Shader/ShaderAstVisitor.hpp>
#include <Nazara/Shader/ShaderVarVisitor.hpp>
#include <Nazara/Shader/ShaderWriter.hpp>
#include <Nazara/Utility/FieldOffsets.hpp>
#include <string>
#include <string_view>
#include <unordered_map>
namespace Nz
{
class NAZARA_SHADER_API SpirvWriter : public ShaderAstVisitor, public ShaderVarVisitor
{
public:
struct Environment;
SpirvWriter();
SpirvWriter(const SpirvWriter&) = delete;
SpirvWriter(SpirvWriter&&) = delete;
~SpirvWriter() = default;
std::vector<UInt32> Generate(const ShaderAst& shader);
void SetEnv(Environment environment);
struct Environment
{
UInt32 spvMajorVersion = 1;
UInt32 spvMinorVersion = 0;
};
private:
struct ExtVar;
struct Opcode;
struct Raw;
struct WordCount;
struct Section
{
inline std::size_t Append(const char* str);
inline std::size_t Append(const std::string_view& str);
inline std::size_t Append(const std::string& str);
inline std::size_t Append(UInt32 value);
std::size_t Append(const Opcode& opcode, const WordCount& wordCount);
std::size_t Append(const Raw& raw);
inline std::size_t Append(std::initializer_list<UInt32> codepoints);
template<typename... Args> std::size_t Append(Opcode opcode, const Args&... args);
template<typename T> std::size_t Append(T value);
inline unsigned int CountWord(const char* str);
inline unsigned int CountWord(const std::string_view& str);
inline unsigned int CountWord(const std::string& str);
unsigned int CountWord(const Raw& raw);
template<typename T> unsigned int CountWord(const T& value);
template<typename T1, typename T2, typename... Args> unsigned int CountWord(const T1& value, const T2& value2, const Args&... rest);
inline std::size_t GetOutputOffset() const;
std::vector<UInt32> data;
};
UInt32 AllocateResultId();
void AppendConstants();
void AppendHeader();
void AppendStructType(std::size_t structIndex, UInt32 resultId);
void AppendTypes();
UInt32 EvaluateExpression(const ShaderNodes::ExpressionPtr& expr);
UInt32 GetConstantId(const ShaderNodes::Constant::Variant& value) const;
UInt32 GetTypeId(const ShaderExpressionType& type) const;
void PushResultId(UInt32 value);
UInt32 PopResultId();
UInt32 ReadVariable(ExtVar& var);
UInt32 RegisterType(ShaderExpressionType type);
using ShaderAstVisitor::Visit;
void Visit(ShaderNodes::AccessMember& node) override;
void Visit(ShaderNodes::AssignOp& node) override;
void Visit(ShaderNodes::Branch& node) override;
void Visit(ShaderNodes::BinaryOp& node) override;
void Visit(ShaderNodes::Cast& node) override;
void Visit(ShaderNodes::Constant& node) override;
void Visit(ShaderNodes::DeclareVariable& node) override;
void Visit(ShaderNodes::ExpressionStatement& node) override;
void Visit(ShaderNodes::Identifier& node) override;
void Visit(ShaderNodes::IntrinsicCall& node) override;
void Visit(ShaderNodes::Sample2D& node) override;
void Visit(ShaderNodes::StatementBlock& node) override;
void Visit(ShaderNodes::SwizzleOp& node) override;
using ShaderVarVisitor::Visit;
void Visit(ShaderNodes::BuiltinVariable& var) override;
void Visit(ShaderNodes::InputVariable& var) override;
void Visit(ShaderNodes::LocalVariable& var) override;
void Visit(ShaderNodes::OutputVariable& var) override;
void Visit(ShaderNodes::ParameterVariable& var) override;
void Visit(ShaderNodes::UniformVariable& var) override;
static void MergeBlocks(std::vector<UInt32>& output, const Section& from);
struct Context
{
const ShaderAst* shader = nullptr;
const ShaderAst::Function* currentFunction = nullptr;
};
struct State;
Context m_context;
Environment m_environment;
State* m_currentState;
};
}
#include <Nazara/Shader/SpirvWriter.inl>
#endif

View File

@@ -0,0 +1,111 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Shader generator"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Shader/SpirvWriter.hpp>
#include <cassert>
#include <type_traits>
#include <Nazara/Shader/Debug.hpp>
namespace Nz
{
inline std::size_t SpirvWriter::Section::Append(const char* str)
{
return Append(std::string_view(str));
}
inline std::size_t SpirvWriter::Section::Append(const std::string_view& str)
{
std::size_t offset = GetOutputOffset();
std::size_t size4 = CountWord(str);
for (std::size_t i = 0; i < size4; ++i)
{
UInt32 codepoint = 0;
for (std::size_t j = 0; j < 4; ++j)
{
std::size_t pos = i * 4 + j;
if (pos < str.size())
codepoint |= UInt32(str[pos]) << (j * 8);
}
Append(codepoint);
}
return offset;
}
inline std::size_t SpirvWriter::Section::Append(const std::string& str)
{
return Append(std::string_view(str));
}
inline std::size_t SpirvWriter::Section::Append(UInt32 value)
{
std::size_t offset = GetOutputOffset();
data.push_back(value);
return offset;
}
inline std::size_t SpirvWriter::Section::Append(std::initializer_list<UInt32> codepoints)
{
std::size_t offset = GetOutputOffset();
for (UInt32 cp : codepoints)
Append(cp);
return offset;
}
template<typename ...Args>
std::size_t SpirvWriter::Section::Append(Opcode opcode, const Args&... args)
{
unsigned int wordCount = 1 + (CountWord(args) + ... + 0);
std::size_t offset = Append(opcode, WordCount{ wordCount });
if constexpr (sizeof...(args) > 0)
(Append(args), ...);
return offset;
}
template<typename T>
std::size_t SpirvWriter::Section::Append(T value)
{
return Append(static_cast<UInt32>(value));
}
template<typename T>
unsigned int SpirvWriter::Section::CountWord(const T& value)
{
return 1;
}
template<typename T1, typename T2, typename ...Args>
unsigned int SpirvWriter::Section::CountWord(const T1& value, const T2& value2, const Args&... rest)
{
return CountWord(value) + CountWord(value2) + (CountWord(rest) + ...);
}
inline unsigned int SpirvWriter::Section::CountWord(const char* str)
{
return CountWord(std::string_view(str));
}
inline unsigned int Nz::SpirvWriter::Section::CountWord(const std::string& str)
{
return CountWord(std::string_view(str));
}
inline unsigned int SpirvWriter::Section::CountWord(const std::string_view& str)
{
return (static_cast<unsigned int>(str.size() + 1) + sizeof(UInt32) - 1) / sizeof(UInt32); //< + 1 for null character
}
std::size_t SpirvWriter::Section::GetOutputOffset() const
{
return data.size();
}
}
#include <Nazara/Shader/DebugOff.hpp>