Shader: Add function parameters and return handling
This commit is contained in:
@@ -83,6 +83,7 @@ namespace Nz
|
||||
void Visit(ShaderNodes::LocalVariable& var) override;
|
||||
void Visit(ShaderNodes::NoOp& node) override;
|
||||
void Visit(ShaderNodes::ParameterVariable& var) override;
|
||||
void Visit(ShaderNodes::ReturnStatement& node) override;
|
||||
void Visit(ShaderNodes::OutputVariable& var) override;
|
||||
void Visit(ShaderNodes::Sample2D& node) override;
|
||||
void Visit(ShaderNodes::StatementBlock& node) override;
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Nz
|
||||
~ShaderAst() = default;
|
||||
|
||||
void AddCondition(std::string name);
|
||||
void AddFunction(std::string name, ShaderNodes::StatementPtr statement, std::vector<FunctionParameter> parameters = {}, ShaderNodes::BasicType returnType = ShaderNodes::BasicType::Void);
|
||||
void AddFunction(std::string name, ShaderNodes::StatementPtr statement, std::vector<FunctionParameter> parameters = {}, ShaderExpressionType 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);
|
||||
@@ -85,7 +85,7 @@ namespace Nz
|
||||
{
|
||||
std::string name;
|
||||
std::vector<FunctionParameter> parameters;
|
||||
ShaderNodes::BasicType returnType;
|
||||
ShaderExpressionType returnType;
|
||||
ShaderNodes::StatementPtr statement;
|
||||
};
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ namespace Nz
|
||||
void Visit(ShaderNodes::Identifier& node) override;
|
||||
void Visit(ShaderNodes::IntrinsicCall& node) override;
|
||||
void Visit(ShaderNodes::NoOp& node) override;
|
||||
void Visit(ShaderNodes::ReturnStatement& node) override;
|
||||
void Visit(ShaderNodes::Sample2D& node) override;
|
||||
void Visit(ShaderNodes::StatementBlock& node) override;
|
||||
void Visit(ShaderNodes::SwizzleOp& node) override;
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace Nz
|
||||
void Visit(ShaderNodes::Identifier& node) override;
|
||||
void Visit(ShaderNodes::IntrinsicCall& node) override;
|
||||
void Visit(ShaderNodes::NoOp& node) override;
|
||||
void Visit(ShaderNodes::ReturnStatement& node) override;
|
||||
void Visit(ShaderNodes::Sample2D& node) override;
|
||||
void Visit(ShaderNodes::StatementBlock& node) override;
|
||||
void Visit(ShaderNodes::SwizzleOp& node) override;
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace Nz
|
||||
void Serialize(ShaderNodes::IntrinsicCall& node);
|
||||
void Serialize(ShaderNodes::NamedVariable& var);
|
||||
void Serialize(ShaderNodes::NoOp& node);
|
||||
void Serialize(ShaderNodes::ReturnStatement& node);
|
||||
void Serialize(ShaderNodes::Sample2D& node);
|
||||
void Serialize(ShaderNodes::StatementBlock& node);
|
||||
void Serialize(ShaderNodes::SwizzleOp& node);
|
||||
|
||||
@@ -48,6 +48,7 @@ namespace Nz
|
||||
void Visit(ShaderNodes::ExpressionStatement& node) override;
|
||||
void Visit(ShaderNodes::Identifier& node) override;
|
||||
void Visit(ShaderNodes::IntrinsicCall& node) override;
|
||||
void Visit(ShaderNodes::ReturnStatement& node) override;
|
||||
void Visit(ShaderNodes::Sample2D& node) override;
|
||||
void Visit(ShaderNodes::StatementBlock& node) override;
|
||||
void Visit(ShaderNodes::SwizzleOp& node) override;
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace Nz
|
||||
virtual void Visit(ShaderNodes::Identifier& node) = 0;
|
||||
virtual void Visit(ShaderNodes::IntrinsicCall& node) = 0;
|
||||
virtual void Visit(ShaderNodes::NoOp& node) = 0;
|
||||
virtual void Visit(ShaderNodes::ReturnStatement& node) = 0;
|
||||
virtual void Visit(ShaderNodes::Sample2D& node) = 0;
|
||||
virtual void Visit(ShaderNodes::StatementBlock& node) = 0;
|
||||
virtual void Visit(ShaderNodes::SwizzleOp& node) = 0;
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace Nz
|
||||
void Visit(ShaderNodes::Identifier& node) override;
|
||||
void Visit(ShaderNodes::IntrinsicCall& node) override;
|
||||
void Visit(ShaderNodes::NoOp& node) override;
|
||||
void Visit(ShaderNodes::ReturnStatement& node) override;
|
||||
void Visit(ShaderNodes::Sample2D& node) override;
|
||||
void Visit(ShaderNodes::StatementBlock& node) override;
|
||||
void Visit(ShaderNodes::SwizzleOp& node) override;
|
||||
|
||||
@@ -91,6 +91,7 @@ namespace Nz::ShaderNodes
|
||||
Identifier,
|
||||
IntrinsicCall,
|
||||
NoOp,
|
||||
ReturnStatement,
|
||||
Sample2D,
|
||||
SwizzleOp,
|
||||
StatementBlock,
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Shader/Config.hpp>
|
||||
#include <Nazara/Shader/ShaderLangLexer.hpp>
|
||||
#include <Nazara/Shader/ShaderAst.hpp>
|
||||
|
||||
namespace Nz::ShaderLang
|
||||
{
|
||||
@@ -19,6 +20,18 @@ namespace Nz::ShaderLang
|
||||
using exception::exception;
|
||||
};
|
||||
|
||||
class ReservedKeyword : public std::exception
|
||||
{
|
||||
public:
|
||||
using exception::exception;
|
||||
};
|
||||
|
||||
class UnknownType : public std::exception
|
||||
{
|
||||
public:
|
||||
using exception::exception;
|
||||
};
|
||||
|
||||
class UnexpectedToken : public std::exception
|
||||
{
|
||||
public:
|
||||
@@ -31,19 +44,39 @@ namespace Nz::ShaderLang
|
||||
inline Parser();
|
||||
~Parser() = default;
|
||||
|
||||
void Parse(const std::vector<Token>& tokens);
|
||||
ShaderAst Parse(const std::vector<Token>& tokens);
|
||||
|
||||
private:
|
||||
// Flow control
|
||||
const Token& Advance();
|
||||
void Expect(const Token& token, TokenType type);
|
||||
void ExpectNext(TokenType type);
|
||||
void ParseFunctionBody();
|
||||
void ParseFunctionDeclaration();
|
||||
void ParseFunctionParameter();
|
||||
const Token& ExpectNext(TokenType type);
|
||||
const Token& PeekNext();
|
||||
|
||||
// Statements
|
||||
ShaderNodes::StatementPtr ParseFunctionBody();
|
||||
void ParseFunctionDeclaration();
|
||||
ShaderAst::FunctionParameter ParseFunctionParameter();
|
||||
ShaderNodes::StatementPtr ParseReturnStatement();
|
||||
ShaderNodes::StatementPtr ParseStatement();
|
||||
ShaderNodes::StatementPtr ParseStatementList();
|
||||
|
||||
// Expressions
|
||||
ShaderNodes::ExpressionPtr ParseBinOpRhs(int exprPrecedence, ShaderNodes::ExpressionPtr lhs);
|
||||
ShaderNodes::ExpressionPtr ParseExpression();
|
||||
ShaderNodes::ExpressionPtr ParseIdentifier();
|
||||
ShaderNodes::ExpressionPtr ParseIntegerExpression();
|
||||
ShaderNodes::ExpressionPtr ParseParenthesisExpression();
|
||||
ShaderNodes::ExpressionPtr ParsePrimaryExpression();
|
||||
|
||||
std::string ParseIdentifierAsName();
|
||||
ShaderExpressionType ParseIdentifierAsType();
|
||||
|
||||
static int GetTokenPrecedence(TokenType token);
|
||||
|
||||
struct Context
|
||||
{
|
||||
ShaderAst result;
|
||||
std::size_t tokenCount;
|
||||
std::size_t tokenIndex = 0;
|
||||
const Token* tokens;
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#define NAZARA_SHADERLANG_TOKEN_LAST(X) NAZARA_SHADERLANG_TOKEN(X)
|
||||
#endif
|
||||
|
||||
NAZARA_SHADERLANG_TOKEN(Add)
|
||||
NAZARA_SHADERLANG_TOKEN(BoolFalse)
|
||||
NAZARA_SHADERLANG_TOKEN(BoolTrue)
|
||||
NAZARA_SHADERLANG_TOKEN(ClosingParenthesis)
|
||||
@@ -26,11 +25,12 @@ NAZARA_SHADERLANG_TOKEN(FunctionReturn)
|
||||
NAZARA_SHADERLANG_TOKEN(IntegerValue)
|
||||
NAZARA_SHADERLANG_TOKEN(Identifier)
|
||||
NAZARA_SHADERLANG_TOKEN(Multiply)
|
||||
NAZARA_SHADERLANG_TOKEN(Minus)
|
||||
NAZARA_SHADERLANG_TOKEN(Plus)
|
||||
NAZARA_SHADERLANG_TOKEN(OpenCurlyBracket)
|
||||
NAZARA_SHADERLANG_TOKEN(OpenParenthesis)
|
||||
NAZARA_SHADERLANG_TOKEN(Semicolon)
|
||||
NAZARA_SHADERLANG_TOKEN(Return)
|
||||
NAZARA_SHADERLANG_TOKEN(Subtract)
|
||||
|
||||
#undef NAZARA_SHADERLANG_TOKEN
|
||||
#undef NAZARA_SHADERLANG_TOKEN_LAST
|
||||
|
||||
@@ -168,6 +168,17 @@ namespace Nz
|
||||
static inline std::shared_ptr<NoOp> Build();
|
||||
};
|
||||
|
||||
struct NAZARA_SHADER_API ReturnStatement : public Statement
|
||||
{
|
||||
inline ReturnStatement();
|
||||
|
||||
void Visit(ShaderAstVisitor& visitor) override;
|
||||
|
||||
ExpressionPtr returnExpr;
|
||||
|
||||
static inline std::shared_ptr<ReturnStatement> Build(ExpressionPtr expr = nullptr);
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct NAZARA_SHADER_API AssignOp : public Expression
|
||||
|
||||
@@ -194,7 +194,7 @@ namespace Nz::ShaderNodes
|
||||
}
|
||||
|
||||
|
||||
inline ShaderNodes::NoOp::NoOp() :
|
||||
inline NoOp::NoOp() :
|
||||
Statement(NodeType::NoOp)
|
||||
{
|
||||
}
|
||||
@@ -205,6 +205,20 @@ namespace Nz::ShaderNodes
|
||||
}
|
||||
|
||||
|
||||
inline ReturnStatement::ReturnStatement() :
|
||||
Statement(NodeType::ReturnStatement)
|
||||
{
|
||||
}
|
||||
|
||||
inline std::shared_ptr<ReturnStatement> ShaderNodes::ReturnStatement::Build(ExpressionPtr expr)
|
||||
{
|
||||
auto node = std::make_shared<ReturnStatement>();
|
||||
node->returnExpr = std::move(expr);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
inline AssignOp::AssignOp() :
|
||||
Expression(NodeType::AssignOp)
|
||||
{
|
||||
|
||||
@@ -43,6 +43,7 @@ namespace Nz
|
||||
void Visit(ShaderNodes::Identifier& node) override;
|
||||
void Visit(ShaderNodes::IntrinsicCall& node) override;
|
||||
void Visit(ShaderNodes::NoOp& node) override;
|
||||
void Visit(ShaderNodes::ReturnStatement& node) override;
|
||||
void Visit(ShaderNodes::Sample2D& node) override;
|
||||
void Visit(ShaderNodes::StatementBlock& node) override;
|
||||
void Visit(ShaderNodes::SwizzleOp& node) override;
|
||||
|
||||
@@ -8,14 +8,14 @@
|
||||
#define NAZARA_SPIRVBLOCK_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Shader/SpirvSection.hpp>
|
||||
#include <Nazara/Shader/SpirvSectionBase.hpp>
|
||||
#include <Nazara/Shader/SpirvWriter.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class NAZARA_SHADER_API SpirvBlock : public SpirvSection
|
||||
class NAZARA_SHADER_API SpirvBlock : public SpirvSectionBase
|
||||
{
|
||||
public:
|
||||
inline SpirvBlock(SpirvWriter& writer);
|
||||
@@ -23,13 +23,24 @@ namespace Nz
|
||||
SpirvBlock(SpirvBlock&&) = default;
|
||||
~SpirvBlock() = default;
|
||||
|
||||
inline std::size_t Append(SpirvOp opcode, const OpSize& wordCount);
|
||||
template<typename... Args> std::size_t Append(SpirvOp opcode, Args&&... args);
|
||||
template<typename F> std::size_t AppendVariadic(SpirvOp opcode, F&& callback);
|
||||
|
||||
inline UInt32 GetLabelId() const;
|
||||
|
||||
inline bool IsTerminated() const;
|
||||
|
||||
SpirvBlock& operator=(const SpirvBlock&) = delete;
|
||||
SpirvBlock& operator=(SpirvBlock&&) = default;
|
||||
|
||||
static inline bool IsTerminationInstruction(SpirvOp op);
|
||||
|
||||
private:
|
||||
inline void HandleSpirvOp(SpirvOp op);
|
||||
|
||||
UInt32 m_labelId;
|
||||
bool m_isTerminated;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -7,16 +7,70 @@
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline SpirvBlock::SpirvBlock(SpirvWriter& writer)
|
||||
inline SpirvBlock::SpirvBlock(SpirvWriter& writer) :
|
||||
m_isTerminated(false)
|
||||
{
|
||||
m_labelId = writer.AllocateResultId();
|
||||
Append(SpirvOp::OpLabel, m_labelId);
|
||||
}
|
||||
|
||||
inline std::size_t SpirvBlock::Append(SpirvOp opcode, const OpSize& wordCount)
|
||||
{
|
||||
HandleSpirvOp(opcode);
|
||||
|
||||
return SpirvSectionBase::Append(opcode, wordCount);
|
||||
}
|
||||
|
||||
template<typename ...Args>
|
||||
std::size_t SpirvBlock::Append(SpirvOp opcode, Args&&... args)
|
||||
{
|
||||
HandleSpirvOp(opcode);
|
||||
|
||||
return SpirvSectionBase::Append(opcode, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
std::size_t SpirvBlock::AppendVariadic(SpirvOp opcode, F&& callback)
|
||||
{
|
||||
HandleSpirvOp(opcode);
|
||||
|
||||
return SpirvSectionBase::AppendVariadic(opcode, std::forward<F>(callback));
|
||||
}
|
||||
|
||||
inline UInt32 SpirvBlock::GetLabelId() const
|
||||
{
|
||||
return m_labelId;
|
||||
}
|
||||
|
||||
inline bool SpirvBlock::IsTerminated() const
|
||||
{
|
||||
return m_isTerminated;
|
||||
}
|
||||
|
||||
inline bool SpirvBlock::IsTerminationInstruction(SpirvOp op)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case SpirvOp::OpBranch:
|
||||
case SpirvOp::OpBranchConditional:
|
||||
case SpirvOp::OpKill:
|
||||
case SpirvOp::OpReturn:
|
||||
case SpirvOp::OpReturnValue:
|
||||
case SpirvOp::OpSwitch:
|
||||
case SpirvOp::OpUnreachable:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SpirvBlock::HandleSpirvOp(SpirvOp op)
|
||||
{
|
||||
assert(!m_isTerminated);
|
||||
if (IsTerminationInstruction(op))
|
||||
m_isTerminated = true;
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Shader/DebugOff.hpp>
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace Nz
|
||||
using ShaderVarVisitor::Visit;
|
||||
void Visit(ShaderNodes::InputVariable& var) override;
|
||||
void Visit(ShaderNodes::LocalVariable& var) override;
|
||||
void Visit(ShaderNodes::ParameterVariable& var) override;
|
||||
void Visit(ShaderNodes::UniformVariable& var) override;
|
||||
|
||||
SpirvExpressionLoad& operator=(const SpirvExpressionLoad&) = delete;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Shader/Config.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
@@ -23,7 +24,9 @@ namespace Nz
|
||||
SpirvPrinter(SpirvPrinter&&) = default;
|
||||
~SpirvPrinter() = default;
|
||||
|
||||
inline std::string Print(const std::vector<UInt32>& codepoints);
|
||||
inline std::string Print(const UInt32* codepoints, std::size_t count);
|
||||
inline std::string Print(const std::vector<UInt32>& codepoints, const Settings& settings);
|
||||
std::string Print(const UInt32* codepoints, std::size_t count, const Settings& settings);
|
||||
|
||||
SpirvPrinter& operator=(const SpirvPrinter&) = default;
|
||||
|
||||
@@ -12,11 +12,21 @@ namespace Nz
|
||||
{
|
||||
}
|
||||
|
||||
inline std::string SpirvPrinter::Print(const std::vector<UInt32>& codepoints)
|
||||
{
|
||||
return Print(codepoints.data(), codepoints.size());
|
||||
}
|
||||
|
||||
inline std::string SpirvPrinter::Print(const UInt32* codepoints, std::size_t count)
|
||||
{
|
||||
Settings settings;
|
||||
return Print(codepoints, count, settings);
|
||||
}
|
||||
|
||||
inline std::string SpirvPrinter::Print(const std::vector<UInt32>& codepoints, const Settings& settings)
|
||||
{
|
||||
return Print(codepoints.data(), codepoints.size(), settings);
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Shader/DebugOff.hpp>
|
||||
|
||||
@@ -8,64 +8,25 @@
|
||||
#define NAZARA_SPIRVSECTION_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Shader/ShaderEnums.hpp>
|
||||
#include <Nazara/Shader/SpirvData.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <Nazara/Shader/SpirvSectionBase.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class NAZARA_SHADER_API SpirvSection
|
||||
class NAZARA_SHADER_API SpirvSection : public SpirvSectionBase
|
||||
{
|
||||
public:
|
||||
struct OpSize;
|
||||
struct Raw;
|
||||
|
||||
SpirvSection() = default;
|
||||
SpirvSection(const SpirvSection&) = default;
|
||||
SpirvSection(SpirvSection&&) = default;
|
||||
~SpirvSection() = default;
|
||||
|
||||
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);
|
||||
inline std::size_t Append(SpirvOp opcode, const OpSize& 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(SpirvOp opcode, const Args&... args);
|
||||
template<typename F> std::size_t AppendVariadic(SpirvOp opcode, F&& callback);
|
||||
inline std::size_t Append(const SpirvSection& section);
|
||||
template<typename T, typename = std::enable_if_t<std::is_integral_v<T> || std::is_enum_v<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);
|
||||
inline unsigned int CountWord(const Raw& raw);
|
||||
template<typename T, typename = std::enable_if_t<std::is_integral_v<T> || std::is_enum_v<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 const std::vector<UInt32>& GetBytecode() const;
|
||||
inline std::size_t GetOutputOffset() const;
|
||||
using SpirvSectionBase::Append;
|
||||
using SpirvSectionBase::AppendRaw;
|
||||
using SpirvSectionBase::AppendSection;
|
||||
using SpirvSectionBase::AppendVariadic;
|
||||
|
||||
SpirvSection& operator=(const SpirvSection&) = delete;
|
||||
SpirvSection& operator=(SpirvSection&&) = default;
|
||||
|
||||
struct OpSize
|
||||
{
|
||||
unsigned int wc;
|
||||
};
|
||||
|
||||
struct Raw
|
||||
{
|
||||
const void* ptr;
|
||||
std::size_t size;
|
||||
};
|
||||
|
||||
static inline UInt32 BuildOpcode(SpirvOp opcode, unsigned int wordCount);
|
||||
|
||||
private:
|
||||
std::vector<UInt32> m_bytecode;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -7,151 +7,6 @@
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline std::size_t SpirvSection::Append(const char* str)
|
||||
{
|
||||
return Append(std::string_view(str));
|
||||
}
|
||||
|
||||
inline std::size_t SpirvSection::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 SpirvSection::Append(const std::string& str)
|
||||
{
|
||||
return Append(std::string_view(str));
|
||||
}
|
||||
|
||||
inline std::size_t SpirvSection::Append(UInt32 value)
|
||||
{
|
||||
std::size_t offset = GetOutputOffset();
|
||||
m_bytecode.push_back(value);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
inline std::size_t SpirvSection::Append(SpirvOp opcode, const OpSize& wordCount)
|
||||
{
|
||||
return Append(BuildOpcode(opcode, wordCount.wc));
|
||||
}
|
||||
|
||||
inline std::size_t SpirvSection::Append(std::initializer_list<UInt32> codepoints)
|
||||
{
|
||||
std::size_t offset = GetOutputOffset();
|
||||
|
||||
for (UInt32 cp : codepoints)
|
||||
Append(cp);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
inline std::size_t SpirvSection::Append(const SpirvSection& section)
|
||||
{
|
||||
const std::vector<UInt32>& bytecode = section.GetBytecode();
|
||||
|
||||
std::size_t offset = GetOutputOffset();
|
||||
m_bytecode.resize(offset + bytecode.size());
|
||||
std::copy(bytecode.begin(), bytecode.end(), m_bytecode.begin() + offset);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
template<typename ...Args>
|
||||
std::size_t SpirvSection::Append(SpirvOp opcode, const Args&... args)
|
||||
{
|
||||
unsigned int wordCount = 1 + (CountWord(args) + ... + 0);
|
||||
std::size_t offset = Append(opcode, OpSize{ wordCount });
|
||||
if constexpr (sizeof...(args) > 0)
|
||||
(Append(args), ...);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
template<typename F> std::size_t SpirvSection::AppendVariadic(SpirvOp opcode, F&& callback)
|
||||
{
|
||||
std::size_t offset = Append(0); //< Will be filled later
|
||||
|
||||
unsigned int wordCount = 1;
|
||||
auto appendFunctor = [&](const auto& value)
|
||||
{
|
||||
wordCount += CountWord(value);
|
||||
Append(value);
|
||||
};
|
||||
callback(appendFunctor);
|
||||
|
||||
m_bytecode[offset] = BuildOpcode(opcode, wordCount);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
template<typename T, typename>
|
||||
std::size_t SpirvSection::Append(T value)
|
||||
{
|
||||
return Append(static_cast<UInt32>(value));
|
||||
}
|
||||
|
||||
template<typename T, typename>
|
||||
unsigned int SpirvSection::CountWord(const T& /*value*/)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2, typename ...Args>
|
||||
unsigned int SpirvSection::CountWord(const T1& value, const T2& value2, const Args&... rest)
|
||||
{
|
||||
return CountWord(value) + CountWord(value2) + (CountWord(rest) + ...);
|
||||
}
|
||||
|
||||
inline unsigned int SpirvSection::CountWord(const char* str)
|
||||
{
|
||||
return CountWord(std::string_view(str));
|
||||
}
|
||||
|
||||
inline unsigned int Nz::SpirvSection::CountWord(const std::string& str)
|
||||
{
|
||||
return CountWord(std::string_view(str));
|
||||
}
|
||||
|
||||
inline unsigned int SpirvSection::CountWord(const Raw& raw)
|
||||
{
|
||||
return static_cast<unsigned int>((raw.size + sizeof(UInt32) - 1) / sizeof(UInt32));
|
||||
}
|
||||
|
||||
inline unsigned int SpirvSection::CountWord(const std::string_view& str)
|
||||
{
|
||||
return (static_cast<unsigned int>(str.size() + 1) + sizeof(UInt32) - 1) / sizeof(UInt32); //< + 1 for null character
|
||||
}
|
||||
|
||||
inline const std::vector<UInt32>& SpirvSection::GetBytecode() const
|
||||
{
|
||||
return m_bytecode;
|
||||
}
|
||||
|
||||
inline std::size_t SpirvSection::GetOutputOffset() const
|
||||
{
|
||||
return m_bytecode.size();
|
||||
}
|
||||
|
||||
inline UInt32 SpirvSection::BuildOpcode(SpirvOp opcode, unsigned int wordCount)
|
||||
{
|
||||
return UInt32(opcode) | UInt32(wordCount) << 16;
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Shader/DebugOff.hpp>
|
||||
|
||||
75
include/Nazara/Shader/SpirvSectionBase.hpp
Normal file
75
include/Nazara/Shader/SpirvSectionBase.hpp
Normal file
@@ -0,0 +1,75 @@
|
||||
// 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_SPIRVSECTIONBASE_HPP
|
||||
#define NAZARA_SPIRVSECTIONBASE_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Shader/ShaderEnums.hpp>
|
||||
#include <Nazara/Shader/SpirvData.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class NAZARA_SHADER_API SpirvSectionBase
|
||||
{
|
||||
public:
|
||||
struct OpSize;
|
||||
struct Raw;
|
||||
|
||||
SpirvSectionBase() = default;
|
||||
SpirvSectionBase(const SpirvSectionBase&) = default;
|
||||
SpirvSectionBase(SpirvSectionBase&&) = default;
|
||||
~SpirvSectionBase() = default;
|
||||
|
||||
inline const std::vector<UInt32>& GetBytecode() const;
|
||||
inline std::size_t GetOutputOffset() const;
|
||||
|
||||
SpirvSectionBase& operator=(const SpirvSectionBase&) = delete;
|
||||
SpirvSectionBase& operator=(SpirvSectionBase&&) = default;
|
||||
|
||||
struct OpSize
|
||||
{
|
||||
unsigned int wc;
|
||||
};
|
||||
|
||||
struct Raw
|
||||
{
|
||||
const void* ptr;
|
||||
std::size_t size;
|
||||
};
|
||||
|
||||
static inline UInt32 BuildOpcode(SpirvOp opcode, unsigned int wordCount);
|
||||
|
||||
protected:
|
||||
inline std::size_t Append(SpirvOp opcode, const OpSize& wordCount);
|
||||
template<typename... Args> std::size_t Append(SpirvOp opcode, const Args&... args);
|
||||
template<typename F> std::size_t AppendVariadic(SpirvOp opcode, F&& callback);
|
||||
inline std::size_t AppendRaw(const char* str);
|
||||
inline std::size_t AppendRaw(const std::string_view& str);
|
||||
inline std::size_t AppendRaw(const std::string& str);
|
||||
inline std::size_t AppendRaw(UInt32 value);
|
||||
std::size_t AppendRaw(const Raw& raw);
|
||||
inline std::size_t AppendRaw(std::initializer_list<UInt32> codepoints);
|
||||
inline std::size_t AppendSection(const SpirvSectionBase& section);
|
||||
template<typename T, typename = std::enable_if_t<std::is_integral_v<T> || std::is_enum_v<T>>> std::size_t AppendRaw(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);
|
||||
inline unsigned int CountWord(const Raw& raw);
|
||||
template<typename T, typename = std::enable_if_t<std::is_integral_v<T> || std::is_enum_v<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);
|
||||
|
||||
private:
|
||||
std::vector<UInt32> m_bytecode;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Shader/SpirvSectionBase.inl>
|
||||
|
||||
#endif
|
||||
157
include/Nazara/Shader/SpirvSectionBase.inl
Normal file
157
include/Nazara/Shader/SpirvSectionBase.inl
Normal file
@@ -0,0 +1,157 @@
|
||||
// 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/SpirvSectionBase.hpp>
|
||||
#include <Nazara/Shader/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline std::size_t SpirvSectionBase::Append(SpirvOp opcode, const OpSize& wordCount)
|
||||
{
|
||||
return AppendRaw(BuildOpcode(opcode, wordCount.wc));
|
||||
}
|
||||
|
||||
template<typename ...Args>
|
||||
std::size_t SpirvSectionBase::Append(SpirvOp opcode, const Args&... args)
|
||||
{
|
||||
unsigned int wordCount = 1 + (CountWord(args) + ... + 0);
|
||||
std::size_t offset = Append(opcode, OpSize{ wordCount });
|
||||
if constexpr (sizeof...(args) > 0)
|
||||
(AppendRaw(args), ...);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
template<typename F> std::size_t SpirvSectionBase::AppendVariadic(SpirvOp opcode, F&& callback)
|
||||
{
|
||||
std::size_t offset = AppendRaw(0); //< Will be filled later
|
||||
|
||||
unsigned int wordCount = 1;
|
||||
auto appendFunctor = [&](const auto& value)
|
||||
{
|
||||
wordCount += CountWord(value);
|
||||
AppendRaw(value);
|
||||
};
|
||||
callback(appendFunctor);
|
||||
|
||||
m_bytecode[offset] = BuildOpcode(opcode, wordCount);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
inline std::size_t SpirvSectionBase::AppendRaw(const char* str)
|
||||
{
|
||||
return AppendRaw(std::string_view(str));
|
||||
}
|
||||
|
||||
inline std::size_t SpirvSectionBase::AppendRaw(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);
|
||||
}
|
||||
|
||||
AppendRaw(codepoint);
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
inline std::size_t SpirvSectionBase::AppendRaw(const std::string& str)
|
||||
{
|
||||
return AppendRaw(std::string_view(str));
|
||||
}
|
||||
|
||||
inline std::size_t SpirvSectionBase::AppendRaw(UInt32 value)
|
||||
{
|
||||
std::size_t offset = GetOutputOffset();
|
||||
m_bytecode.push_back(value);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
inline std::size_t SpirvSectionBase::AppendRaw(std::initializer_list<UInt32> codepoints)
|
||||
{
|
||||
std::size_t offset = GetOutputOffset();
|
||||
|
||||
for (UInt32 cp : codepoints)
|
||||
AppendRaw(cp);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
inline std::size_t SpirvSectionBase::AppendSection(const SpirvSectionBase& section)
|
||||
{
|
||||
const std::vector<UInt32>& bytecode = section.GetBytecode();
|
||||
|
||||
std::size_t offset = GetOutputOffset();
|
||||
m_bytecode.resize(offset + bytecode.size());
|
||||
std::copy(bytecode.begin(), bytecode.end(), m_bytecode.begin() + offset);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
template<typename T, typename>
|
||||
std::size_t SpirvSectionBase::AppendRaw(T value)
|
||||
{
|
||||
return AppendRaw(static_cast<UInt32>(value));
|
||||
}
|
||||
|
||||
template<typename T, typename>
|
||||
unsigned int SpirvSectionBase::CountWord(const T& /*value*/)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2, typename ...Args>
|
||||
unsigned int SpirvSectionBase::CountWord(const T1& value, const T2& value2, const Args&... rest)
|
||||
{
|
||||
return CountWord(value) + CountWord(value2) + (CountWord(rest) + ...);
|
||||
}
|
||||
|
||||
inline unsigned int SpirvSectionBase::CountWord(const char* str)
|
||||
{
|
||||
return CountWord(std::string_view(str));
|
||||
}
|
||||
|
||||
inline unsigned int Nz::SpirvSectionBase::CountWord(const std::string& str)
|
||||
{
|
||||
return CountWord(std::string_view(str));
|
||||
}
|
||||
|
||||
inline unsigned int SpirvSectionBase::CountWord(const Raw& raw)
|
||||
{
|
||||
return static_cast<unsigned int>((raw.size + sizeof(UInt32) - 1) / sizeof(UInt32));
|
||||
}
|
||||
|
||||
inline unsigned int SpirvSectionBase::CountWord(const std::string_view& str)
|
||||
{
|
||||
return (static_cast<unsigned int>(str.size() + 1) + sizeof(UInt32) - 1) / sizeof(UInt32); //< + 1 for null character
|
||||
}
|
||||
|
||||
inline const std::vector<UInt32>& SpirvSectionBase::GetBytecode() const
|
||||
{
|
||||
return m_bytecode;
|
||||
}
|
||||
|
||||
inline std::size_t SpirvSectionBase::GetOutputOffset() const
|
||||
{
|
||||
return m_bytecode.size();
|
||||
}
|
||||
|
||||
inline UInt32 SpirvSectionBase::BuildOpcode(SpirvOp opcode, unsigned int wordCount)
|
||||
{
|
||||
return UInt32(opcode) | UInt32(wordCount) << 16;
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Shader/DebugOff.hpp>
|
||||
@@ -57,6 +57,8 @@ namespace Nz
|
||||
|
||||
void AppendHeader();
|
||||
|
||||
SpirvConstantCache::Function BuildFunctionType(ShaderExpressionType retType, const std::vector<ShaderAst::FunctionParameter>& parameters);
|
||||
|
||||
UInt32 GetConstantId(const ShaderConstantValue& value) const;
|
||||
UInt32 GetFunctionTypeId(ShaderExpressionType retType, const std::vector<ShaderAst::FunctionParameter>& parameters);
|
||||
const ExtVar& GetBuiltinVariable(ShaderNodes::BuiltinEntry builtin) const;
|
||||
@@ -72,6 +74,8 @@ namespace Nz
|
||||
std::optional<UInt32> ReadInputVariable(const std::string& name, OnlyCache);
|
||||
UInt32 ReadLocalVariable(const std::string& name);
|
||||
std::optional<UInt32> ReadLocalVariable(const std::string& name, OnlyCache);
|
||||
UInt32 ReadParameterVariable(const std::string& name);
|
||||
std::optional<UInt32> ReadParameterVariable(const std::string& name, OnlyCache);
|
||||
UInt32 ReadUniformVariable(const std::string& name);
|
||||
std::optional<UInt32> ReadUniformVariable(const std::string& name, OnlyCache);
|
||||
UInt32 ReadVariable(ExtVar& var);
|
||||
@@ -89,8 +93,8 @@ namespace Nz
|
||||
struct Context
|
||||
{
|
||||
const ShaderAst* shader = nullptr;
|
||||
const ShaderAst::Function* currentFunction = nullptr;
|
||||
const States* states = nullptr;
|
||||
std::vector<SpirvBlock> functionBlocks;
|
||||
};
|
||||
|
||||
struct ExtVar
|
||||
|
||||
Reference in New Issue
Block a user