Shader: Add initial support for options (WIP)
This commit is contained in:
parent
7da02c8708
commit
87ce2edc6e
|
|
@ -9,6 +9,9 @@
|
|||
#include <iostream>
|
||||
|
||||
const char shaderSource[] = R"(
|
||||
|
||||
option red: bool;
|
||||
|
||||
[layout(std140)]
|
||||
struct Data
|
||||
{
|
||||
|
|
@ -49,7 +52,7 @@ fn main(fragIn: VertOut) -> FragOut
|
|||
let lightFactor = dot(fragIn.normal, lightDir);
|
||||
|
||||
let fragOut: FragOut;
|
||||
fragOut.color = lightFactor * tex.Sample(fragIn.uv);
|
||||
fragOut.color = lightFactor * tex.Sample(fragIn.uv) * select_opt(red, vec4<f32>(1.0, 0.0, 0.0, 1.0), vec4<f32>(1.0, 1.0, 1.0, 1.0));
|
||||
|
||||
return fragOut;
|
||||
}
|
||||
|
|
@ -92,7 +95,10 @@ int main()
|
|||
|
||||
std::shared_ptr<Nz::RenderDevice> device = window.GetRenderDevice();
|
||||
|
||||
auto fragVertShader = device->InstantiateShaderModule(Nz::ShaderStageType::Fragment | Nz::ShaderStageType::Vertex, Nz::ShaderLanguage::NazaraShader, shaderSource, sizeof(shaderSource));
|
||||
Nz::ShaderWriter::States states;
|
||||
states.enabledOptions = 0;
|
||||
|
||||
auto fragVertShader = device->InstantiateShaderModule(Nz::ShaderStageType::Fragment | Nz::ShaderStageType::Vertex, Nz::ShaderLanguage::NazaraShader, shaderSource, sizeof(shaderSource), states);
|
||||
if (!fragVertShader)
|
||||
{
|
||||
std::cout << "Failed to instantiate shader" << std::endl;
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ namespace Nz
|
|||
std::shared_ptr<RenderPipeline> InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override;
|
||||
std::shared_ptr<RenderPipelineLayout> InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override;
|
||||
std::shared_ptr<ShaderModule> InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states) override;
|
||||
std::shared_ptr<ShaderModule> InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize) override;
|
||||
std::shared_ptr<ShaderModule> InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states) override;
|
||||
std::shared_ptr<Texture> InstantiateTexture(const TextureInfo& params) override;
|
||||
std::shared_ptr<TextureSampler> InstantiateTextureSampler(const TextureSamplerInfo& params) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace Nz
|
|||
{
|
||||
public:
|
||||
OpenGLShaderModule(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states);
|
||||
OpenGLShaderModule(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize);
|
||||
OpenGLShaderModule(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states);
|
||||
OpenGLShaderModule(const OpenGLShaderModule&) = delete;
|
||||
OpenGLShaderModule(OpenGLShaderModule&&) noexcept = default;
|
||||
~OpenGLShaderModule() = default;
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ namespace Nz
|
|||
virtual std::shared_ptr<RenderPipeline> InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) = 0;
|
||||
virtual std::shared_ptr<RenderPipelineLayout> InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) = 0;
|
||||
virtual std::shared_ptr<ShaderModule> InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states) = 0;
|
||||
virtual std::shared_ptr<ShaderModule> InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize) = 0;
|
||||
std::shared_ptr<ShaderModule> InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const std::filesystem::path& sourcePath);
|
||||
virtual std::shared_ptr<ShaderModule> InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states) = 0;
|
||||
std::shared_ptr<ShaderModule> InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const std::filesystem::path& sourcePath, const ShaderWriter::States& states);
|
||||
virtual std::shared_ptr<Texture> InstantiateTexture(const TextureInfo& params) = 0;
|
||||
virtual std::shared_ptr<TextureSampler> InstantiateTextureSampler(const TextureSamplerInfo& params) = 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ namespace Nz::ShaderAst
|
|||
virtual ExpressionPtr Clone(ConstantExpression& node);
|
||||
virtual ExpressionPtr Clone(IdentifierExpression& node);
|
||||
virtual ExpressionPtr Clone(IntrinsicExpression& node);
|
||||
virtual ExpressionPtr Clone(SelectOptionExpression& node);
|
||||
virtual ExpressionPtr Clone(SwizzleExpression& node);
|
||||
virtual ExpressionPtr Clone(VariableExpression& node);
|
||||
|
||||
|
|
@ -52,6 +53,7 @@ namespace Nz::ShaderAst
|
|||
virtual StatementPtr Clone(ConditionalStatement& node);
|
||||
virtual StatementPtr Clone(DeclareExternalStatement& node);
|
||||
virtual StatementPtr Clone(DeclareFunctionStatement& node);
|
||||
virtual StatementPtr Clone(DeclareOptionStatement& node);
|
||||
virtual StatementPtr Clone(DeclareStructStatement& node);
|
||||
virtual StatementPtr Clone(DeclareVariableStatement& node);
|
||||
virtual StatementPtr Clone(DiscardStatement& node);
|
||||
|
|
|
|||
|
|
@ -35,12 +35,14 @@ NAZARA_SHADERAST_EXPRESSION(ConditionalExpression)
|
|||
NAZARA_SHADERAST_EXPRESSION(ConstantExpression)
|
||||
NAZARA_SHADERAST_EXPRESSION(IdentifierExpression)
|
||||
NAZARA_SHADERAST_EXPRESSION(IntrinsicExpression)
|
||||
NAZARA_SHADERAST_EXPRESSION(SelectOptionExpression)
|
||||
NAZARA_SHADERAST_EXPRESSION(SwizzleExpression)
|
||||
NAZARA_SHADERAST_EXPRESSION(VariableExpression)
|
||||
NAZARA_SHADERAST_STATEMENT(BranchStatement)
|
||||
NAZARA_SHADERAST_STATEMENT(ConditionalStatement)
|
||||
NAZARA_SHADERAST_STATEMENT(DeclareExternalStatement)
|
||||
NAZARA_SHADERAST_STATEMENT(DeclareFunctionStatement)
|
||||
NAZARA_SHADERAST_STATEMENT(DeclareOptionStatement)
|
||||
NAZARA_SHADERAST_STATEMENT(DeclareStructStatement)
|
||||
NAZARA_SHADERAST_STATEMENT(DeclareVariableStatement)
|
||||
NAZARA_SHADERAST_STATEMENT(DiscardStatement)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Shader/Config.hpp>
|
||||
#include <Nazara/Shader/Ast/AstCloner.hpp>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace Nz::ShaderAst
|
||||
|
|
@ -29,16 +30,15 @@ namespace Nz::ShaderAst
|
|||
AstOptimizer& operator=(AstOptimizer&&) = delete;
|
||||
|
||||
protected:
|
||||
using AstCloner::Visit;
|
||||
void Visit(BinaryExpression& node) override;
|
||||
void Visit(ConditionalExpression& node) override;
|
||||
void Visit(BranchStatement& node) override;
|
||||
void Visit(ConditionalStatement& node) override;
|
||||
ExpressionPtr Clone(BinaryExpression& node) override;
|
||||
ExpressionPtr Clone(ConditionalExpression& node) override;
|
||||
StatementPtr Clone(BranchStatement& node) override;
|
||||
StatementPtr Clone(ConditionalStatement& node) override;
|
||||
|
||||
template<BinaryType Type> void PropagateConstant(std::unique_ptr<ConstantExpression>&& lhs, std::unique_ptr<ConstantExpression>&& rhs);
|
||||
template<BinaryType Type> ExpressionPtr PropagateConstant(std::unique_ptr<ConstantExpression>&& lhs, std::unique_ptr<ConstantExpression>&& rhs);
|
||||
|
||||
private:
|
||||
UInt64 m_enabledConditions;
|
||||
std::optional<UInt64> m_enabledOptions;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ namespace Nz::ShaderAst
|
|||
void Visit(ConstantExpression& node) override;
|
||||
void Visit(IdentifierExpression& node) override;
|
||||
void Visit(IntrinsicExpression& node) override;
|
||||
void Visit(SelectOptionExpression& node) override;
|
||||
void Visit(SwizzleExpression& node) override;
|
||||
void Visit(VariableExpression& node) override;
|
||||
|
||||
|
|
@ -36,6 +37,7 @@ namespace Nz::ShaderAst
|
|||
void Visit(ConditionalStatement& node) override;
|
||||
void Visit(DeclareExternalStatement& node) override;
|
||||
void Visit(DeclareFunctionStatement& node) override;
|
||||
void Visit(DeclareOptionStatement& node) override;
|
||||
void Visit(DeclareStructStatement& node) override;
|
||||
void Visit(DeclareVariableStatement& node) override;
|
||||
void Visit(DiscardStatement& node) override;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ namespace Nz::ShaderAst
|
|||
void Serialize(ConstantExpression& node);
|
||||
void Serialize(IdentifierExpression& node);
|
||||
void Serialize(IntrinsicExpression& node);
|
||||
void Serialize(SelectOptionExpression& node);
|
||||
void Serialize(SwizzleExpression& node);
|
||||
void Serialize(VariableExpression& node);
|
||||
|
||||
|
|
@ -39,6 +40,7 @@ namespace Nz::ShaderAst
|
|||
void Serialize(ConditionalStatement& node);
|
||||
void Serialize(DeclareExternalStatement& node);
|
||||
void Serialize(DeclareFunctionStatement& node);
|
||||
void Serialize(DeclareOptionStatement& node);
|
||||
void Serialize(DeclareStructStatement& node);
|
||||
void Serialize(DeclareVariableStatement& node);
|
||||
void Serialize(DiscardStatement& node);
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ namespace Nz::ShaderAst
|
|||
void Visit(ConstantExpression& node) override;
|
||||
void Visit(IdentifierExpression& node) override;
|
||||
void Visit(IntrinsicExpression& node) override;
|
||||
void Visit(SelectOptionExpression& node) override;
|
||||
void Visit(SwizzleExpression& node) override;
|
||||
void Visit(VariableExpression& node) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ namespace Nz::ShaderAst
|
|||
Builtin, //< Builtin (struct member only) - has argument type
|
||||
Entry, //< Entry point (function only) - has argument type
|
||||
Layout, //< Struct layout (struct only) - has argument style
|
||||
Location //< Location (struct member only) - has argument index
|
||||
Location, //< Location (struct member only) - has argument index
|
||||
Option, //< Conditional compilation option - has argument expr
|
||||
};
|
||||
|
||||
enum class BinaryType
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ namespace Nz::ShaderAst
|
|||
NodeType GetType() const override;
|
||||
void Visit(AstExpressionVisitor& visitor) override;
|
||||
|
||||
std::string conditionName;
|
||||
std::size_t optionIndex;
|
||||
ExpressionPtr falsePath;
|
||||
ExpressionPtr truePath;
|
||||
};
|
||||
|
|
@ -146,6 +146,16 @@ namespace Nz::ShaderAst
|
|||
std::vector<ExpressionPtr> parameters;
|
||||
};
|
||||
|
||||
struct NAZARA_SHADER_API SelectOptionExpression : public Expression
|
||||
{
|
||||
NodeType GetType() const override;
|
||||
void Visit(AstExpressionVisitor& visitor) override;
|
||||
|
||||
std::string optionName;
|
||||
ExpressionPtr falsePath;
|
||||
ExpressionPtr truePath;
|
||||
};
|
||||
|
||||
struct NAZARA_SHADER_API SwizzleExpression : public Expression
|
||||
{
|
||||
NodeType GetType() const override;
|
||||
|
|
@ -203,7 +213,7 @@ namespace Nz::ShaderAst
|
|||
NodeType GetType() const override;
|
||||
void Visit(AstStatementVisitor& visitor) override;
|
||||
|
||||
std::string conditionName;
|
||||
std::size_t optionIndex;
|
||||
StatementPtr statement;
|
||||
};
|
||||
|
||||
|
|
@ -237,12 +247,24 @@ namespace Nz::ShaderAst
|
|||
std::optional<ShaderStageType> entryStage;
|
||||
std::optional<std::size_t> funcIndex;
|
||||
std::optional<std::size_t> varIndex;
|
||||
std::string optionName;
|
||||
std::string name;
|
||||
std::vector<Parameter> parameters;
|
||||
std::vector<StatementPtr> statements;
|
||||
ExpressionType returnType;
|
||||
};
|
||||
|
||||
struct NAZARA_SHADER_API DeclareOptionStatement : Statement
|
||||
{
|
||||
NodeType GetType() const override;
|
||||
void Visit(AstStatementVisitor& visitor) override;
|
||||
|
||||
std::optional<std::size_t> optIndex;
|
||||
std::string optName;
|
||||
ExpressionPtr initialValue;
|
||||
ExpressionType optType;
|
||||
};
|
||||
|
||||
struct NAZARA_SHADER_API DeclareStructStatement : Statement
|
||||
{
|
||||
NodeType GetType() const override;
|
||||
|
|
|
|||
|
|
@ -17,16 +17,24 @@ namespace Nz::ShaderAst
|
|||
class NAZARA_SHADER_API SanitizeVisitor final : AstCloner
|
||||
{
|
||||
public:
|
||||
struct Options;
|
||||
|
||||
inline SanitizeVisitor();
|
||||
SanitizeVisitor(const SanitizeVisitor&) = delete;
|
||||
SanitizeVisitor(SanitizeVisitor&&) = delete;
|
||||
~SanitizeVisitor() = default;
|
||||
|
||||
StatementPtr Sanitize(StatementPtr& statement, std::string* error = nullptr);
|
||||
inline StatementPtr Sanitize(StatementPtr& statement, std::string* error = nullptr);
|
||||
StatementPtr Sanitize(StatementPtr& statement, const Options& options, std::string* error = nullptr);
|
||||
|
||||
SanitizeVisitor& operator=(const SanitizeVisitor&) = delete;
|
||||
SanitizeVisitor& operator=(SanitizeVisitor&&) = delete;
|
||||
|
||||
struct Options
|
||||
{
|
||||
bool removeOptionDeclaration = true;
|
||||
};
|
||||
|
||||
private:
|
||||
struct Identifier;
|
||||
|
||||
|
|
@ -42,12 +50,14 @@ namespace Nz::ShaderAst
|
|||
ExpressionPtr Clone(ConstantExpression& node) override;
|
||||
ExpressionPtr Clone(IdentifierExpression& node) override;
|
||||
ExpressionPtr Clone(IntrinsicExpression& node) override;
|
||||
ExpressionPtr Clone(SelectOptionExpression& node) override;
|
||||
ExpressionPtr Clone(SwizzleExpression& node) override;
|
||||
|
||||
StatementPtr Clone(BranchStatement& node) override;
|
||||
StatementPtr Clone(ConditionalStatement& node) override;
|
||||
StatementPtr Clone(DeclareExternalStatement& node) override;
|
||||
StatementPtr Clone(DeclareFunctionStatement& node) override;
|
||||
StatementPtr Clone(DeclareOptionStatement& node) override;
|
||||
StatementPtr Clone(DeclareStructStatement& node) override;
|
||||
StatementPtr Clone(DeclareVariableStatement& node) override;
|
||||
StatementPtr Clone(ExpressionStatement& node) override;
|
||||
|
|
@ -64,6 +74,7 @@ namespace Nz::ShaderAst
|
|||
void PopScope();
|
||||
|
||||
inline std::size_t RegisterFunction(std::string name);
|
||||
inline std::size_t RegisterOption(std::string name, ExpressionType type);
|
||||
inline std::size_t RegisterStruct(std::string name, StructDescription description);
|
||||
inline std::size_t RegisterVariable(std::string name, ExpressionType type);
|
||||
|
||||
|
|
@ -78,6 +89,11 @@ namespace Nz::ShaderAst
|
|||
std::variant<ExpressionType> value;
|
||||
};
|
||||
|
||||
struct Option
|
||||
{
|
||||
std::size_t optionIndex;
|
||||
};
|
||||
|
||||
struct Struct
|
||||
{
|
||||
std::size_t structIndex;
|
||||
|
|
@ -91,11 +107,12 @@ namespace Nz::ShaderAst
|
|||
struct Identifier
|
||||
{
|
||||
std::string name;
|
||||
std::variant<Alias, Struct, Variable> value;
|
||||
std::variant<Alias, Option, Struct, Variable> value;
|
||||
};
|
||||
|
||||
std::size_t m_nextFuncIndex;
|
||||
std::vector<Identifier> m_identifiersInScope;
|
||||
std::vector<ExpressionType> m_options;
|
||||
std::vector<StructDescription> m_structs;
|
||||
std::vector<ExpressionType> m_variables;
|
||||
std::vector<std::size_t> m_scopeSizes;
|
||||
|
|
@ -105,6 +122,7 @@ namespace Nz::ShaderAst
|
|||
};
|
||||
|
||||
inline StatementPtr Sanitize(StatementPtr& ast, std::string* error = nullptr);
|
||||
inline StatementPtr Sanitize(StatementPtr& ast, const SanitizeVisitor::Options& options, std::string* error = nullptr);
|
||||
}
|
||||
|
||||
#include <Nazara/Shader/Ast/SanitizeVisitor.inl>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,11 @@ namespace Nz::ShaderAst
|
|||
{
|
||||
}
|
||||
|
||||
inline StatementPtr SanitizeVisitor::Sanitize(StatementPtr& statement, std::string* error)
|
||||
{
|
||||
return Sanitize(statement, {}, error);
|
||||
}
|
||||
|
||||
inline auto SanitizeVisitor::FindIdentifier(const std::string_view& identifierName) const -> const Identifier*
|
||||
{
|
||||
auto it = std::find_if(m_identifiersInScope.rbegin(), m_identifiersInScope.rend(), [&](const Identifier& identifier) { return identifier.name == identifierName; });
|
||||
|
|
@ -23,10 +28,23 @@ namespace Nz::ShaderAst
|
|||
|
||||
inline std::size_t SanitizeVisitor::RegisterFunction(std::string name)
|
||||
{
|
||||
std::size_t funcIndex = m_nextFuncIndex++;
|
||||
return funcIndex;
|
||||
return m_nextFuncIndex++;
|
||||
}
|
||||
|
||||
inline std::size_t SanitizeVisitor::RegisterOption(std::string name, ExpressionType type)
|
||||
{
|
||||
std::size_t optionIndex = m_options.size();
|
||||
m_options.emplace_back(std::move(type));
|
||||
|
||||
m_identifiersInScope.push_back({
|
||||
std::move(name),
|
||||
Option {
|
||||
optionIndex
|
||||
}
|
||||
});
|
||||
|
||||
return optionIndex;
|
||||
}
|
||||
|
||||
inline std::size_t SanitizeVisitor::RegisterStruct(std::string name, StructDescription description)
|
||||
{
|
||||
|
|
@ -63,6 +81,12 @@ namespace Nz::ShaderAst
|
|||
SanitizeVisitor sanitizer;
|
||||
return sanitizer.Sanitize(ast, error);
|
||||
}
|
||||
|
||||
StatementPtr Sanitize(StatementPtr& ast, const SanitizeVisitor::Options& options, std::string* error)
|
||||
{
|
||||
SanitizeVisitor sanitizer;
|
||||
return sanitizer.Sanitize(ast, options, error);
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Shader/DebugOff.hpp>
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@ namespace Nz
|
|||
GlslWriter(GlslWriter&&) = delete;
|
||||
~GlslWriter() = default;
|
||||
|
||||
inline std::string Generate(ShaderAst::StatementPtr& shader, const States& conditions = {});
|
||||
std::string Generate(std::optional<ShaderStageType> shaderStage, ShaderAst::StatementPtr& shader, const States& conditions = {});
|
||||
inline std::string Generate(ShaderAst::StatementPtr& shader, const States& states = {});
|
||||
std::string Generate(std::optional<ShaderStageType> shaderStage, ShaderAst::StatementPtr& shader, const States& states = {});
|
||||
|
||||
void SetEnv(Environment environment);
|
||||
|
||||
|
|
@ -60,7 +60,6 @@ namespace Nz
|
|||
template<typename T> void Append(const T& param);
|
||||
template<typename T1, typename T2, typename... Args> void Append(const T1& firstParam, const T2& secondParam, Args&&... params);
|
||||
void AppendCommentSection(const std::string& section);
|
||||
void AppendEntryPoint(ShaderStageType shaderStage, ShaderAst::StatementPtr& shader);
|
||||
void AppendField(std::size_t structIndex, const std::size_t* memberIndices, std::size_t remainingMembers);
|
||||
void AppendHeader();
|
||||
void AppendLine(const std::string& txt = {});
|
||||
|
|
|
|||
|
|
@ -12,9 +12,9 @@ namespace Nz
|
|||
{
|
||||
}
|
||||
|
||||
inline std::string GlslWriter::Generate(ShaderAst::StatementPtr& shader, const States& conditions)
|
||||
inline std::string GlslWriter::Generate(ShaderAst::StatementPtr& shader, const States& states)
|
||||
{
|
||||
return Generate(std::nullopt, shader, conditions);
|
||||
return Generate(std::nullopt, shader, states);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,111 @@
|
|||
// 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_LANGWRITER_HPP
|
||||
#define NAZARA_LANGWRITER_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Shader/Config.hpp>
|
||||
#include <Nazara/Shader/ShaderWriter.hpp>
|
||||
#include <Nazara/Shader/Ast/AstExpressionVisitorExcept.hpp>
|
||||
#include <Nazara/Shader/Ast/AstStatementVisitorExcept.hpp>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class NAZARA_SHADER_API LangWriter : public ShaderWriter, public ShaderAst::ExpressionVisitorExcept, public ShaderAst::StatementVisitorExcept
|
||||
{
|
||||
public:
|
||||
struct Environment;
|
||||
|
||||
inline LangWriter();
|
||||
LangWriter(const LangWriter&) = delete;
|
||||
LangWriter(LangWriter&&) = delete;
|
||||
~LangWriter() = default;
|
||||
|
||||
std::string Generate(ShaderAst::StatementPtr& shader, const States& conditions = {});
|
||||
|
||||
void SetEnv(Environment environment);
|
||||
|
||||
struct Environment
|
||||
{
|
||||
};
|
||||
|
||||
private:
|
||||
struct BindingAttribute;
|
||||
struct BuiltinAttribute;
|
||||
struct EntryAttribute;
|
||||
struct LayoutAttribute;
|
||||
struct LocationAttribute;
|
||||
|
||||
void Append(const ShaderAst::ExpressionType& type);
|
||||
void Append(const ShaderAst::IdentifierType& identifierType);
|
||||
void Append(const ShaderAst::MatrixType& matrixType);
|
||||
void Append(ShaderAst::NoType);
|
||||
void Append(ShaderAst::PrimitiveType type);
|
||||
void Append(const ShaderAst::SamplerType& samplerType);
|
||||
void Append(const ShaderAst::StructType& structType);
|
||||
void Append(const ShaderAst::UniformType& uniformType);
|
||||
void Append(const ShaderAst::VectorType& vecType);
|
||||
template<typename T> void Append(const T& param);
|
||||
template<typename T1, typename T2, typename... Args> void Append(const T1& firstParam, const T2& secondParam, Args&&... params);
|
||||
template<typename... Args> void AppendAttributes(bool appendLine, Args&&... params);
|
||||
void AppendAttribute(BindingAttribute builtin);
|
||||
void AppendAttribute(BuiltinAttribute builtin);
|
||||
void AppendAttribute(EntryAttribute entry);
|
||||
void AppendAttribute(LayoutAttribute layout);
|
||||
void AppendAttribute(LocationAttribute location);
|
||||
void AppendCommentSection(const std::string& section);
|
||||
void AppendField(std::size_t structIndex, const std::size_t* memberIndices, std::size_t remainingMembers);
|
||||
void AppendHeader();
|
||||
void AppendLine(const std::string& txt = {});
|
||||
template<typename... Args> void AppendLine(Args&&... params);
|
||||
void AppendStatementList(std::vector<ShaderAst::StatementPtr>& statements);
|
||||
|
||||
void EnterScope();
|
||||
void LeaveScope(bool skipLine = true);
|
||||
|
||||
void RegisterOption(std::size_t optionIndex, std::string optionName);
|
||||
void RegisterStruct(std::size_t structIndex, ShaderAst::StructDescription desc);
|
||||
void RegisterVariable(std::size_t varIndex, std::string varName);
|
||||
|
||||
void Visit(ShaderAst::ExpressionPtr& expr, bool encloseIfRequired = false);
|
||||
|
||||
void Visit(ShaderAst::AccessMemberIndexExpression& node) override;
|
||||
void Visit(ShaderAst::AssignExpression& node) override;
|
||||
void Visit(ShaderAst::BinaryExpression& node) override;
|
||||
void Visit(ShaderAst::CastExpression& node) override;
|
||||
void Visit(ShaderAst::ConditionalExpression& node) override;
|
||||
void Visit(ShaderAst::ConstantExpression& node) override;
|
||||
void Visit(ShaderAst::IntrinsicExpression& node) override;
|
||||
void Visit(ShaderAst::SwizzleExpression& node) override;
|
||||
void Visit(ShaderAst::VariableExpression& node) override;
|
||||
|
||||
void Visit(ShaderAst::BranchStatement& node) override;
|
||||
void Visit(ShaderAst::ConditionalStatement& node) override;
|
||||
void Visit(ShaderAst::DeclareExternalStatement& node) override;
|
||||
void Visit(ShaderAst::DeclareFunctionStatement& node) override;
|
||||
void Visit(ShaderAst::DeclareOptionStatement& node) override;
|
||||
void Visit(ShaderAst::DeclareStructStatement& node) override;
|
||||
void Visit(ShaderAst::DeclareVariableStatement& node) override;
|
||||
void Visit(ShaderAst::DiscardStatement& node) override;
|
||||
void Visit(ShaderAst::ExpressionStatement& node) override;
|
||||
void Visit(ShaderAst::MultiStatement& node) override;
|
||||
void Visit(ShaderAst::NoOpStatement& node) override;
|
||||
void Visit(ShaderAst::ReturnStatement& node) override;
|
||||
|
||||
struct State;
|
||||
|
||||
Environment m_environment;
|
||||
State* m_currentState;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Shader/LangWriter.inl>
|
||||
|
||||
#endif
|
||||
|
|
@ -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/LangWriter.hpp>
|
||||
#include <Nazara/Shader/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline LangWriter::LangWriter() :
|
||||
m_currentState(nullptr)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Shader/DebugOff.hpp>
|
||||
|
|
@ -44,12 +44,12 @@ namespace Nz::ShaderBuilder
|
|||
|
||||
struct ConditionalExpression
|
||||
{
|
||||
inline std::unique_ptr<ShaderAst::ConditionalExpression> operator()(std::string conditionName, ShaderAst::ExpressionPtr truePath, ShaderAst::ExpressionPtr falsePath) const;
|
||||
inline std::unique_ptr<ShaderAst::ConditionalExpression> operator()(std::size_t optionIndex, ShaderAst::ExpressionPtr truePath, ShaderAst::ExpressionPtr falsePath) const;
|
||||
};
|
||||
|
||||
struct ConditionalStatement
|
||||
{
|
||||
inline std::unique_ptr<ShaderAst::ConditionalStatement> operator()(std::string conditionName, ShaderAst::StatementPtr statement) const;
|
||||
inline std::unique_ptr<ShaderAst::ConditionalStatement> operator()(std::size_t optionIndex, ShaderAst::StatementPtr statement) const;
|
||||
};
|
||||
|
||||
struct Constant
|
||||
|
|
@ -64,6 +64,11 @@ namespace Nz::ShaderBuilder
|
|||
inline std::unique_ptr<ShaderAst::DeclareFunctionStatement> operator()(std::optional<ShaderStageType> entryStage, std::string name, std::vector<ShaderAst::DeclareFunctionStatement::Parameter> parameters, std::vector<ShaderAst::StatementPtr> statements, ShaderAst::ExpressionType returnType = ShaderAst::NoType{}) const;
|
||||
};
|
||||
|
||||
struct DeclareOption
|
||||
{
|
||||
inline std::unique_ptr<ShaderAst::DeclareOptionStatement> operator()(std::string name, ShaderAst::ExpressionType type, ShaderAst::ExpressionPtr initialValue = nullptr) const;
|
||||
};
|
||||
|
||||
struct DeclareStruct
|
||||
{
|
||||
inline std::unique_ptr<ShaderAst::DeclareStructStatement> operator()(ShaderAst::StructDescription description) const;
|
||||
|
|
@ -106,6 +111,11 @@ namespace Nz::ShaderBuilder
|
|||
inline std::unique_ptr<ShaderAst::ReturnStatement> operator()(ShaderAst::ExpressionPtr expr = nullptr) const;
|
||||
};
|
||||
|
||||
struct SelectOption
|
||||
{
|
||||
inline std::unique_ptr<ShaderAst::SelectOptionExpression> operator()(std::string optionName, ShaderAst::ExpressionPtr truePath, ShaderAst::ExpressionPtr falsePath) const;
|
||||
};
|
||||
|
||||
struct Swizzle
|
||||
{
|
||||
inline std::unique_ptr<ShaderAst::SwizzleExpression> operator()(ShaderAst::ExpressionPtr expression, std::vector<ShaderAst::SwizzleComponent> swizzleComponents) const;
|
||||
|
|
@ -121,6 +131,7 @@ namespace Nz::ShaderBuilder
|
|||
constexpr Impl::ConditionalStatement ConditionalStatement;
|
||||
constexpr Impl::Constant Constant;
|
||||
constexpr Impl::DeclareFunction DeclareFunction;
|
||||
constexpr Impl::DeclareOption DeclareOption;
|
||||
constexpr Impl::DeclareStruct DeclareStruct;
|
||||
constexpr Impl::DeclareVariable DeclareVariable;
|
||||
constexpr Impl::ExpressionStatement ExpressionStatement;
|
||||
|
|
@ -130,6 +141,7 @@ namespace Nz::ShaderBuilder
|
|||
constexpr Impl::Multi MultiStatement;
|
||||
constexpr Impl::NoParam<ShaderAst::NoOpStatement> NoOp;
|
||||
constexpr Impl::Return Return;
|
||||
constexpr Impl::SelectOption SelectOption;
|
||||
constexpr Impl::Swizzle Swizzle;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,20 +70,20 @@ namespace Nz::ShaderBuilder
|
|||
return castNode;
|
||||
}
|
||||
|
||||
inline std::unique_ptr<ShaderAst::ConditionalExpression> Impl::ConditionalExpression::operator()(std::string conditionName, ShaderAst::ExpressionPtr truePath, ShaderAst::ExpressionPtr falsePath) const
|
||||
inline std::unique_ptr<ShaderAst::ConditionalExpression> Impl::ConditionalExpression::operator()(std::size_t optionIndex, ShaderAst::ExpressionPtr truePath, ShaderAst::ExpressionPtr falsePath) const
|
||||
{
|
||||
auto condExprNode = std::make_unique<ShaderAst::ConditionalExpression>();
|
||||
condExprNode->conditionName = std::move(conditionName);
|
||||
condExprNode->optionIndex = optionIndex;
|
||||
condExprNode->falsePath = std::move(falsePath);
|
||||
condExprNode->truePath = std::move(truePath);
|
||||
|
||||
return condExprNode;
|
||||
}
|
||||
|
||||
inline std::unique_ptr<ShaderAst::ConditionalStatement> Impl::ConditionalStatement::operator()(std::string conditionName, ShaderAst::StatementPtr statement) const
|
||||
inline std::unique_ptr<ShaderAst::ConditionalStatement> Impl::ConditionalStatement::operator()(std::size_t optionIndex, ShaderAst::StatementPtr statement) const
|
||||
{
|
||||
auto condStatementNode = std::make_unique<ShaderAst::ConditionalStatement>();
|
||||
condStatementNode->conditionName = std::move(conditionName);
|
||||
condStatementNode->optionIndex = optionIndex;
|
||||
condStatementNode->statement = std::move(statement);
|
||||
|
||||
return condStatementNode;
|
||||
|
|
@ -129,6 +129,16 @@ namespace Nz::ShaderBuilder
|
|||
return declareFunctionNode;
|
||||
}
|
||||
|
||||
inline std::unique_ptr<ShaderAst::DeclareOptionStatement> Nz::ShaderBuilder::Impl::DeclareOption::operator()(std::string name, ShaderAst::ExpressionType type, ShaderAst::ExpressionPtr initialValue) const
|
||||
{
|
||||
auto declareOptionNode = std::make_unique<ShaderAst::DeclareOptionStatement>();
|
||||
declareOptionNode->optName = std::move(name);
|
||||
declareOptionNode->optType = std::move(type);
|
||||
declareOptionNode->initialValue = std::move(initialValue);
|
||||
|
||||
return declareOptionNode;
|
||||
}
|
||||
|
||||
inline std::unique_ptr<ShaderAst::DeclareStructStatement> Impl::DeclareStruct::operator()(ShaderAst::StructDescription description) const
|
||||
{
|
||||
auto declareStructNode = std::make_unique<ShaderAst::DeclareStructStatement>();
|
||||
|
|
@ -203,6 +213,16 @@ namespace Nz::ShaderBuilder
|
|||
return returnNode;
|
||||
}
|
||||
|
||||
inline std::unique_ptr<ShaderAst::SelectOptionExpression> Impl::SelectOption::operator()(std::string optionName, ShaderAst::ExpressionPtr truePath, ShaderAst::ExpressionPtr falsePath) const
|
||||
{
|
||||
auto selectOptNode = std::make_unique<ShaderAst::SelectOptionExpression>();
|
||||
selectOptNode->optionName = std::move(optionName);
|
||||
selectOptNode->falsePath = std::move(falsePath);
|
||||
selectOptNode->truePath = std::move(truePath);
|
||||
|
||||
return selectOptNode;
|
||||
}
|
||||
|
||||
inline std::unique_ptr<ShaderAst::SwizzleExpression> Impl::Swizzle::operator()(ShaderAst::ExpressionPtr expression, std::vector<ShaderAst::SwizzleComponent> swizzleComponents) const
|
||||
{
|
||||
auto swizzleNode = std::make_unique<ShaderAst::SwizzleExpression>();
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ namespace Nz::ShaderLang
|
|||
std::vector<ShaderAst::StatementPtr> ParseFunctionBody();
|
||||
ShaderAst::StatementPtr ParseFunctionDeclaration(std::vector<ShaderAst::Attribute> attributes = {});
|
||||
ShaderAst::DeclareFunctionStatement::Parameter ParseFunctionParameter();
|
||||
ShaderAst::StatementPtr ParseOptionDeclaration();
|
||||
ShaderAst::StatementPtr ParseStructDeclaration(std::vector<ShaderAst::Attribute> attributes = {});
|
||||
ShaderAst::StatementPtr ParseReturnStatement();
|
||||
ShaderAst::StatementPtr ParseStatement();
|
||||
|
|
@ -100,6 +101,7 @@ namespace Nz::ShaderLang
|
|||
std::vector<ShaderAst::ExpressionPtr> ParseParameters();
|
||||
ShaderAst::ExpressionPtr ParseParenthesisExpression();
|
||||
ShaderAst::ExpressionPtr ParsePrimaryExpression();
|
||||
ShaderAst::ExpressionPtr ParseSelectOptExpression();
|
||||
ShaderAst::ExpressionPtr ParseVariableAssignation();
|
||||
|
||||
ShaderAst::AttributeType ParseIdentifierAsAttributeType();
|
||||
|
|
|
|||
|
|
@ -40,8 +40,10 @@ NAZARA_SHADERLANG_TOKEN(Plus)
|
|||
NAZARA_SHADERLANG_TOKEN(OpenCurlyBracket)
|
||||
NAZARA_SHADERLANG_TOKEN(OpenSquareBracket)
|
||||
NAZARA_SHADERLANG_TOKEN(OpenParenthesis)
|
||||
NAZARA_SHADERLANG_TOKEN(Option)
|
||||
NAZARA_SHADERLANG_TOKEN(Semicolon)
|
||||
NAZARA_SHADERLANG_TOKEN(Return)
|
||||
NAZARA_SHADERLANG_TOKEN(SelectOpt)
|
||||
NAZARA_SHADERLANG_TOKEN(Struct)
|
||||
|
||||
#undef NAZARA_SHADERLANG_TOKEN
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ namespace Nz
|
|||
|
||||
struct States
|
||||
{
|
||||
Nz::UInt64 enabledConditions = 0;
|
||||
Nz::UInt64 enabledOptions = 0;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ namespace Nz
|
|||
SpirvWriter(SpirvWriter&&) = delete;
|
||||
~SpirvWriter() = default;
|
||||
|
||||
std::vector<UInt32> Generate(ShaderAst::StatementPtr& shader, const States& conditions = {});
|
||||
std::vector<UInt32> Generate(ShaderAst::StatementPtr& shader, const States& states = {});
|
||||
|
||||
void SetEnv(Environment environment);
|
||||
|
||||
|
|
@ -62,7 +62,7 @@ namespace Nz
|
|||
UInt32 GetPointerTypeId(const ShaderAst::ExpressionType& type, SpirvStorageClass storageClass) const;
|
||||
UInt32 GetTypeId(const ShaderAst::ExpressionType& type) const;
|
||||
|
||||
inline bool IsConditionEnabled(const std::string& condition) const;
|
||||
bool IsOptionEnabled(std::size_t optionIndex) const;
|
||||
|
||||
UInt32 RegisterConstant(const ShaderAst::ConstantValue& value);
|
||||
UInt32 RegisterFunctionType(const ShaderAst::DeclareFunctionStatement& functionNode);
|
||||
|
|
|
|||
|
|
@ -8,14 +8,6 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
inline bool SpirvWriter::IsConditionEnabled(const std::string& condition) const
|
||||
{
|
||||
/*std::size_t conditionIndex = m_context.shader->FindConditionByName(condition);
|
||||
assert(conditionIndex != ShaderAst::InvalidCondition);
|
||||
|
||||
return TestBit<Nz::UInt64>(m_context.states->enabledConditions, conditionIndex);*/
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Shader/DebugOff.hpp>
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace Nz
|
|||
std::shared_ptr<RenderPipeline> InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override;
|
||||
std::shared_ptr<RenderPipelineLayout> InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override;
|
||||
std::shared_ptr<ShaderModule> InstantiateShaderModule(ShaderStageTypeFlags stages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states) override;
|
||||
std::shared_ptr<ShaderModule> InstantiateShaderModule(ShaderStageTypeFlags stages, ShaderLanguage lang, const void* source, std::size_t sourceSize) override;
|
||||
std::shared_ptr<ShaderModule> InstantiateShaderModule(ShaderStageTypeFlags stages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states) override;
|
||||
std::shared_ptr<Texture> InstantiateTexture(const TextureInfo& params) override;
|
||||
std::shared_ptr<TextureSampler> InstantiateTextureSampler(const TextureSamplerInfo& params) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ namespace Nz
|
|||
~VulkanShaderModule() = default;
|
||||
|
||||
bool Create(Vk::Device& device, ShaderStageTypeFlags shaderStages, ShaderAst::StatementPtr& shaderAst, const ShaderWriter::States& states);
|
||||
bool Create(Vk::Device& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize);
|
||||
bool Create(Vk::Device& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states);
|
||||
|
||||
inline const Vk::ShaderModule& GetHandle() const;
|
||||
inline const std::vector<Stage>& GetStages() const;
|
||||
|
|
|
|||
|
|
@ -85,9 +85,9 @@ namespace Nz
|
|||
return std::make_shared<OpenGLShaderModule>(*this, shaderStages, shaderAst, states);
|
||||
}
|
||||
|
||||
std::shared_ptr<ShaderModule> OpenGLDevice::InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize)
|
||||
std::shared_ptr<ShaderModule> OpenGLDevice::InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states)
|
||||
{
|
||||
return std::make_shared<OpenGLShaderModule>(*this, shaderStages, lang, source, sourceSize);
|
||||
return std::make_shared<OpenGLShaderModule>(*this, shaderStages, lang, source, sourceSize, states);
|
||||
}
|
||||
|
||||
std::shared_ptr<Texture> OpenGLDevice::InstantiateTexture(const TextureInfo& params)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace Nz
|
|||
Create(device, shaderStages, shaderAst, states);
|
||||
}
|
||||
|
||||
OpenGLShaderModule::OpenGLShaderModule(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize)
|
||||
OpenGLShaderModule::OpenGLShaderModule(OpenGLDevice& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states)
|
||||
{
|
||||
NazaraAssert(shaderStages != 0, "at least one shader stage must be specified");
|
||||
|
||||
|
|
@ -65,7 +65,7 @@ namespace Nz
|
|||
|
||||
Nz::ShaderLang::Parser parser;
|
||||
Nz::ShaderAst::StatementPtr shaderAst = parser.Parse(tokens);
|
||||
Create(device, shaderStages, shaderAst, {});
|
||||
Create(device, shaderStages, shaderAst, states);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace Nz
|
|||
{
|
||||
RenderDevice::~RenderDevice() = default;
|
||||
|
||||
std::shared_ptr<ShaderModule> RenderDevice::InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const std::filesystem::path& sourcePath)
|
||||
std::shared_ptr<ShaderModule> RenderDevice::InstantiateShaderModule(ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const std::filesystem::path& sourcePath, const ShaderWriter::States& states)
|
||||
{
|
||||
File file(sourcePath);
|
||||
if (!file.Open(OpenMode_ReadOnly | OpenMode_Text))
|
||||
|
|
@ -29,6 +29,6 @@ namespace Nz
|
|||
return {};
|
||||
}
|
||||
|
||||
return InstantiateShaderModule(shaderStages, lang, source.data(), source.size());
|
||||
return InstantiateShaderModule(shaderStages, lang, source.data(), source.size(), states);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ namespace Nz::ShaderAst
|
|||
StatementPtr AstCloner::Clone(ConditionalStatement& node)
|
||||
{
|
||||
auto clone = std::make_unique<ConditionalStatement>();
|
||||
clone->conditionName = node.conditionName;
|
||||
clone->optionIndex = node.optionIndex;
|
||||
clone->statement = CloneStatement(node.statement);
|
||||
|
||||
return clone;
|
||||
|
|
@ -77,6 +77,7 @@ namespace Nz::ShaderAst
|
|||
clone->entryStage = node.entryStage;
|
||||
clone->funcIndex = node.funcIndex;
|
||||
clone->name = node.name;
|
||||
clone->optionName = node.optionName;
|
||||
clone->parameters = node.parameters;
|
||||
clone->returnType = node.returnType;
|
||||
clone->varIndex = node.varIndex;
|
||||
|
|
@ -88,6 +89,17 @@ namespace Nz::ShaderAst
|
|||
return clone;
|
||||
}
|
||||
|
||||
StatementPtr AstCloner::Clone(DeclareOptionStatement& node)
|
||||
{
|
||||
auto clone = std::make_unique<DeclareOptionStatement>();
|
||||
clone->initialValue = CloneExpression(node.initialValue);
|
||||
clone->optIndex = node.optIndex;
|
||||
clone->optName = node.optName;
|
||||
clone->optType = node.optType;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
StatementPtr AstCloner::Clone(DeclareStructStatement& node)
|
||||
{
|
||||
auto clone = std::make_unique<DeclareStructStatement>();
|
||||
|
|
@ -212,7 +224,7 @@ namespace Nz::ShaderAst
|
|||
ExpressionPtr AstCloner::Clone(ConditionalExpression& node)
|
||||
{
|
||||
auto clone = std::make_unique<ConditionalExpression>();
|
||||
clone->conditionName = node.conditionName;
|
||||
clone->optionIndex = node.optionIndex;
|
||||
clone->falsePath = CloneExpression(node.falsePath);
|
||||
clone->truePath = CloneExpression(node.truePath);
|
||||
|
||||
|
|
@ -255,6 +267,18 @@ namespace Nz::ShaderAst
|
|||
return clone;
|
||||
}
|
||||
|
||||
ExpressionPtr AstCloner::Clone(SelectOptionExpression& node)
|
||||
{
|
||||
auto clone = std::make_unique<SelectOptionExpression>();
|
||||
clone->optionName = node.optionName;
|
||||
clone->falsePath = CloneExpression(node.falsePath);
|
||||
clone->truePath = CloneExpression(node.truePath);
|
||||
|
||||
clone->cachedExpressionType = node.cachedExpressionType;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
ExpressionPtr AstCloner::Clone(SwizzleExpression& node)
|
||||
{
|
||||
auto clone = std::make_unique<SwizzleExpression>();
|
||||
|
|
|
|||
|
|
@ -62,6 +62,12 @@ namespace Nz::ShaderAst
|
|||
param->Visit(*this);
|
||||
}
|
||||
|
||||
void AstRecursiveVisitor::Visit(SelectOptionExpression& node)
|
||||
{
|
||||
node.truePath->Visit(*this);
|
||||
node.falsePath->Visit(*this);
|
||||
}
|
||||
|
||||
void AstRecursiveVisitor::Visit(SwizzleExpression& node)
|
||||
{
|
||||
node.expression->Visit(*this);
|
||||
|
|
@ -100,6 +106,12 @@ namespace Nz::ShaderAst
|
|||
statement->Visit(*this);
|
||||
}
|
||||
|
||||
void AstRecursiveVisitor::Visit(DeclareOptionStatement& node)
|
||||
{
|
||||
if (node.initialValue)
|
||||
node.initialValue->Visit(*this);
|
||||
}
|
||||
|
||||
void AstRecursiveVisitor::Visit(DeclareStructStatement& /*node*/)
|
||||
{
|
||||
/* Nothing to do */
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ namespace Nz::ShaderAst
|
|||
|
||||
void AstSerializerBase::Serialize(ConditionalExpression& node)
|
||||
{
|
||||
Value(node.conditionName);
|
||||
SizeT(node.optionIndex);
|
||||
Node(node.truePath);
|
||||
Node(node.falsePath);
|
||||
}
|
||||
|
|
@ -113,14 +113,6 @@ namespace Nz::ShaderAst
|
|||
}
|
||||
}
|
||||
|
||||
void AstSerializerBase::Serialize(DeclareVariableStatement& node)
|
||||
{
|
||||
OptVal(node.varIndex);
|
||||
Value(node.varName);
|
||||
Type(node.varType);
|
||||
Node(node.initialExpression);
|
||||
}
|
||||
|
||||
void AstSerializerBase::Serialize(IdentifierExpression& node)
|
||||
{
|
||||
Value(node.identifier);
|
||||
|
|
@ -134,6 +126,13 @@ namespace Nz::ShaderAst
|
|||
Node(param);
|
||||
}
|
||||
|
||||
void AstSerializerBase::Serialize(SelectOptionExpression& node)
|
||||
{
|
||||
Value(node.optionName);
|
||||
Node(node.truePath);
|
||||
Node(node.falsePath);
|
||||
}
|
||||
|
||||
void AstSerializerBase::Serialize(SwizzleExpression& node)
|
||||
{
|
||||
SizeT(node.componentCount);
|
||||
|
|
@ -163,7 +162,7 @@ namespace Nz::ShaderAst
|
|||
|
||||
void AstSerializerBase::Serialize(ConditionalStatement& node)
|
||||
{
|
||||
Value(node.conditionName);
|
||||
SizeT(node.optionIndex);
|
||||
Node(node.statement);
|
||||
}
|
||||
|
||||
|
|
@ -186,6 +185,7 @@ namespace Nz::ShaderAst
|
|||
Type(node.returnType);
|
||||
OptEnum(node.entryStage);
|
||||
OptVal(node.funcIndex);
|
||||
Value(node.optionName);
|
||||
OptVal(node.varIndex);
|
||||
|
||||
Container(node.parameters);
|
||||
|
|
@ -200,6 +200,14 @@ namespace Nz::ShaderAst
|
|||
Node(statement);
|
||||
}
|
||||
|
||||
void AstSerializerBase::Serialize(DeclareOptionStatement& node)
|
||||
{
|
||||
OptVal(node.optIndex);
|
||||
Value(node.optName);
|
||||
Type(node.optType);
|
||||
Node(node.initialValue);
|
||||
}
|
||||
|
||||
void AstSerializerBase::Serialize(DeclareStructStatement& node)
|
||||
{
|
||||
OptVal(node.structIndex);
|
||||
|
|
@ -216,6 +224,14 @@ namespace Nz::ShaderAst
|
|||
OptVal(member.locationIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void AstSerializerBase::Serialize(DeclareVariableStatement& node)
|
||||
{
|
||||
OptVal(node.varIndex);
|
||||
Value(node.varName);
|
||||
Type(node.varType);
|
||||
Node(node.initialExpression);
|
||||
}
|
||||
|
||||
void AstSerializerBase::Serialize(DiscardStatement& /*node*/)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -67,6 +67,20 @@ namespace Nz::ShaderAst
|
|||
m_expressionCategory = ExpressionCategory::RValue;
|
||||
}
|
||||
|
||||
void ShaderAstValueCategory::Visit(SelectOptionExpression& node)
|
||||
{
|
||||
node.truePath->Visit(*this);
|
||||
ExpressionCategory trueExprCategory = m_expressionCategory;
|
||||
|
||||
node.falsePath->Visit(*this);
|
||||
ExpressionCategory falseExprCategory = m_expressionCategory;
|
||||
|
||||
if (trueExprCategory == ExpressionCategory::RValue || falseExprCategory == ExpressionCategory::RValue)
|
||||
m_expressionCategory = ExpressionCategory::RValue;
|
||||
else
|
||||
m_expressionCategory = ExpressionCategory::LValue;
|
||||
}
|
||||
|
||||
void ShaderAstValueCategory::Visit(SwizzleExpression& node)
|
||||
{
|
||||
node.expression->Visit(*this);
|
||||
|
|
|
|||
|
|
@ -29,4 +29,35 @@ namespace Nz::ShaderAst
|
|||
}
|
||||
|
||||
#include <Nazara/Shader/Ast/AstNodeList.hpp>
|
||||
|
||||
ExpressionType ConstantExpression::GetExpressionType() const
|
||||
{
|
||||
return std::visit([&](auto&& arg) -> ShaderAst::ExpressionType
|
||||
{
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
|
||||
if constexpr (std::is_same_v<T, bool>)
|
||||
return PrimitiveType::Boolean;
|
||||
else if constexpr (std::is_same_v<T, float>)
|
||||
return PrimitiveType::Float32;
|
||||
else if constexpr (std::is_same_v<T, Int32>)
|
||||
return PrimitiveType::Int32;
|
||||
else if constexpr (std::is_same_v<T, UInt32>)
|
||||
return PrimitiveType::UInt32;
|
||||
else if constexpr (std::is_same_v<T, Vector2f>)
|
||||
return VectorType{ 2, PrimitiveType::Float32 };
|
||||
else if constexpr (std::is_same_v<T, Vector3f>)
|
||||
return VectorType{ 3, PrimitiveType::Float32 };
|
||||
else if constexpr (std::is_same_v<T, Vector4f>)
|
||||
return VectorType{ 4, PrimitiveType::Float32 };
|
||||
else if constexpr (std::is_same_v<T, Vector2i32>)
|
||||
return VectorType{ 2, PrimitiveType::Int32 };
|
||||
else if constexpr (std::is_same_v<T, Vector3i32>)
|
||||
return VectorType{ 3, PrimitiveType::Int32 };
|
||||
else if constexpr (std::is_same_v<T, Vector4i32>)
|
||||
return VectorType{ 4, PrimitiveType::Int32 };
|
||||
else
|
||||
static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor");
|
||||
}, value);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include <Nazara/Shader/Ast/SanitizeVisitor.hpp>
|
||||
#include <Nazara/Core/CallOnExit.hpp>
|
||||
#include <Nazara/Core/StackArray.hpp>
|
||||
#include <Nazara/Shader/ShaderBuilder.hpp>
|
||||
#include <Nazara/Shader/Ast/AstUtils.hpp>
|
||||
#include <stdexcept>
|
||||
#include <unordered_set>
|
||||
|
|
@ -28,16 +29,18 @@ namespace Nz::ShaderAst
|
|||
|
||||
struct SanitizeVisitor::Context
|
||||
{
|
||||
Options options;
|
||||
std::array<DeclareFunctionStatement*, ShaderStageTypeCount> entryFunctions = {};
|
||||
std::unordered_set<std::string> declaredExternalVar;
|
||||
std::unordered_set<unsigned int> usedBindingIndexes;
|
||||
};
|
||||
|
||||
StatementPtr SanitizeVisitor::Sanitize(StatementPtr& nodePtr, std::string* error)
|
||||
StatementPtr SanitizeVisitor::Sanitize(StatementPtr& nodePtr, const Options& options, std::string* error)
|
||||
{
|
||||
StatementPtr clone;
|
||||
|
||||
Context currentContext;
|
||||
currentContext.options = options;
|
||||
|
||||
m_context = ¤tContext;
|
||||
CallOnExit resetContext([&] { m_context = nullptr; });
|
||||
|
|
@ -483,6 +486,33 @@ namespace Nz::ShaderAst
|
|||
return clone;
|
||||
}
|
||||
|
||||
ExpressionPtr SanitizeVisitor::Clone(SelectOptionExpression& node)
|
||||
{
|
||||
MandatoryExpr(node.truePath);
|
||||
MandatoryExpr(node.falsePath);
|
||||
|
||||
auto condExpr = std::make_unique<ConditionalExpression>();
|
||||
condExpr->truePath = CloneExpression(node.truePath);
|
||||
condExpr->falsePath = CloneExpression(node.falsePath);
|
||||
|
||||
const Identifier* identifier = FindIdentifier(node.optionName);
|
||||
if (!identifier)
|
||||
throw AstError{ "unknown option " + node.optionName };
|
||||
|
||||
if (!std::holds_alternative<Option>(identifier->value))
|
||||
throw AstError{ "expected option identifier" };
|
||||
|
||||
condExpr->optionIndex = std::get<Option>(identifier->value).optionIndex;
|
||||
|
||||
const ExpressionType& leftExprType = GetExpressionType(*condExpr->truePath);
|
||||
if (leftExprType != GetExpressionType(*condExpr->falsePath))
|
||||
throw AstError{ "true path type must match false path type" };
|
||||
|
||||
condExpr->cachedExpressionType = leftExprType;
|
||||
|
||||
return condExpr;
|
||||
}
|
||||
|
||||
ExpressionPtr SanitizeVisitor::Clone(SwizzleExpression& node)
|
||||
{
|
||||
if (node.componentCount > 4)
|
||||
|
|
@ -585,9 +615,13 @@ namespace Nz::ShaderAst
|
|||
{
|
||||
extVar.type = ResolveType(extVar.type);
|
||||
|
||||
ExpressionType varType = extVar.type;
|
||||
ExpressionType varType;
|
||||
if (IsUniformType(extVar.type))
|
||||
varType = std::get<StructType>(std::get<UniformType>(varType).containedType);
|
||||
varType = std::get<StructType>(std::get<UniformType>(extVar.type).containedType);
|
||||
else if (IsSamplerType(extVar.type))
|
||||
varType = extVar.type;
|
||||
else
|
||||
throw AstError{ "External variable " + extVar.name + " is of wrong type: only uniform and sampler are allowed in external blocks" };
|
||||
|
||||
std::size_t varIndex = RegisterVariable(extVar.name, std::move(varType));
|
||||
if (!clone->varIndex)
|
||||
|
|
@ -616,6 +650,7 @@ namespace Nz::ShaderAst
|
|||
clone->entryStage = node.entryStage;
|
||||
clone->name = node.name;
|
||||
clone->funcIndex = m_nextFuncIndex++;
|
||||
clone->optionName = node.optionName;
|
||||
clone->parameters = node.parameters;
|
||||
clone->returnType = ResolveType(node.returnType);
|
||||
|
||||
|
|
@ -635,6 +670,36 @@ namespace Nz::ShaderAst
|
|||
}
|
||||
PopScope();
|
||||
|
||||
if (!clone->optionName.empty())
|
||||
{
|
||||
const Identifier* identifier = FindIdentifier(node.optionName);
|
||||
if (!identifier)
|
||||
throw AstError{ "unknown option " + node.optionName };
|
||||
|
||||
if (!std::holds_alternative<Option>(identifier->value))
|
||||
throw AstError{ "expected option identifier" };
|
||||
|
||||
std::size_t optionIndex = std::get<Option>(identifier->value).optionIndex;
|
||||
|
||||
return ShaderBuilder::ConditionalStatement(optionIndex, std::move(clone));
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
StatementPtr SanitizeVisitor::Clone(DeclareOptionStatement& node)
|
||||
{
|
||||
auto clone = static_unique_pointer_cast<DeclareOptionStatement>(AstCloner::Clone(node));
|
||||
clone->optType = ResolveType(clone->optType);
|
||||
|
||||
if (clone->initialValue && clone->optType != GetExpressionType(*clone->initialValue))
|
||||
throw AstError{ "option " + clone->optName + " initial expression must be of the same type than the option" };
|
||||
|
||||
clone->optIndex = RegisterOption(clone->optName, clone->optType);
|
||||
|
||||
if (m_context->options.removeOptionDeclaration)
|
||||
return ShaderBuilder::NoOp();
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,12 @@ namespace Nz
|
|||
{
|
||||
using AstRecursiveVisitor::Visit;
|
||||
|
||||
void Visit(ShaderAst::ConditionalStatement& node) override
|
||||
{
|
||||
if (TestBit<UInt64>(enabledOptions, node.optionIndex))
|
||||
node.statement->Visit(*this);
|
||||
}
|
||||
|
||||
void Visit(ShaderAst::DeclareFunctionStatement& node) override
|
||||
{
|
||||
// Dismiss function if it's an entry point of another type than the one selected
|
||||
|
|
@ -46,6 +52,7 @@ namespace Nz
|
|||
if (stage != *selectedStage)
|
||||
return;
|
||||
|
||||
assert(!entryPoint);
|
||||
entryPoint = &node;
|
||||
}
|
||||
}
|
||||
|
|
@ -58,6 +65,7 @@ namespace Nz
|
|||
|
||||
std::optional<ShaderStageType> selectedStage;
|
||||
ShaderAst::DeclareFunctionStatement* entryPoint = nullptr;
|
||||
UInt64 enabledOptions = 0;
|
||||
};
|
||||
|
||||
struct Builtin
|
||||
|
|
@ -88,13 +96,15 @@ namespace Nz
|
|||
std::unordered_map<std::size_t, std::string> variableNames;
|
||||
std::vector<InOutField> inputFields;
|
||||
std::vector<InOutField> outputFields;
|
||||
UInt64 enabledOptions = 0;
|
||||
bool isInEntryPoint = false;
|
||||
unsigned int indentLevel = 0;
|
||||
};
|
||||
|
||||
std::string GlslWriter::Generate(std::optional<ShaderStageType> shaderStage, ShaderAst::StatementPtr& shader, const States& conditions)
|
||||
std::string GlslWriter::Generate(std::optional<ShaderStageType> shaderStage, ShaderAst::StatementPtr& shader, const States& states)
|
||||
{
|
||||
State state;
|
||||
state.enabledOptions = states.enabledOptions;
|
||||
state.stage = shaderStage;
|
||||
|
||||
m_currentState = &state;
|
||||
|
|
@ -106,6 +116,7 @@ namespace Nz
|
|||
ShaderAst::StatementPtr sanitizedAst = ShaderAst::Sanitize(shader);
|
||||
|
||||
PreVisitor previsitor;
|
||||
previsitor.enabledOptions = states.enabledOptions;
|
||||
previsitor.selectedStage = shaderStage;
|
||||
sanitizedAst->Visit(previsitor);
|
||||
|
||||
|
|
@ -574,22 +585,16 @@ namespace Nz
|
|||
|
||||
void GlslWriter::Visit(ShaderAst::ConditionalExpression& node)
|
||||
{
|
||||
/*std::size_t conditionIndex = m_context.shader->FindConditionByName(node.conditionName);
|
||||
assert(conditionIndex != ShaderAst::InvalidCondition);
|
||||
|
||||
if (TestBit<Nz::UInt64>(m_context.states->enabledConditions, conditionIndex))
|
||||
if (TestBit<Nz::UInt64>(m_currentState->enabledOptions, node.optionIndex))
|
||||
Visit(node.truePath);
|
||||
else
|
||||
Visit(node.falsePath);*/
|
||||
Visit(node.falsePath);
|
||||
}
|
||||
|
||||
void GlslWriter::Visit(ShaderAst::ConditionalStatement& node)
|
||||
{
|
||||
/*std::size_t conditionIndex = m_context.shader->FindConditionByName(node.conditionName);
|
||||
assert(conditionIndex != ShaderAst::InvalidCondition);
|
||||
|
||||
if (TestBit<Nz::UInt64>(m_context.states->enabledConditions, conditionIndex))
|
||||
Visit(node.statement);*/
|
||||
if (TestBit<Nz::UInt64>(m_currentState->enabledOptions, node.optionIndex))
|
||||
node.statement->Visit(*this);
|
||||
}
|
||||
|
||||
void GlslWriter::Visit(ShaderAst::ConstantExpression& node)
|
||||
|
|
|
|||
|
|
@ -40,13 +40,15 @@ namespace Nz::ShaderLang
|
|||
ForceCLocale forceCLocale;
|
||||
|
||||
std::unordered_map<std::string, TokenType> reservedKeywords = {
|
||||
{ "external", TokenType::External },
|
||||
{ "false", TokenType::BoolFalse },
|
||||
{ "fn", TokenType::FunctionDeclaration },
|
||||
{ "let", TokenType::Let },
|
||||
{ "return", TokenType::Return },
|
||||
{ "struct", TokenType::Struct },
|
||||
{ "true", TokenType::BoolTrue }
|
||||
{ "external", TokenType::External },
|
||||
{ "false", TokenType::BoolFalse },
|
||||
{ "fn", TokenType::FunctionDeclaration },
|
||||
{ "let", TokenType::Let },
|
||||
{ "option", TokenType::Option },
|
||||
{ "return", TokenType::Return },
|
||||
{ "select_opt", TokenType::SelectOpt },
|
||||
{ "struct", TokenType::Struct },
|
||||
{ "true", TokenType::BoolTrue }
|
||||
};
|
||||
|
||||
std::size_t currentPos = 0;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ namespace Nz::ShaderLang
|
|||
{ "builtin", ShaderAst::AttributeType::Builtin },
|
||||
{ "entry", ShaderAst::AttributeType::Entry },
|
||||
{ "layout", ShaderAst::AttributeType::Layout },
|
||||
{ "location", ShaderAst::AttributeType::Location },
|
||||
{ "location", ShaderAst::AttributeType::Location },
|
||||
{ "opt", ShaderAst::AttributeType::Option },
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, ShaderStageType> s_entryPoints = {
|
||||
|
|
@ -90,6 +91,13 @@ namespace Nz::ShaderLang
|
|||
assert(attributes.empty());
|
||||
attributes = ParseAttributes();
|
||||
break;
|
||||
|
||||
case TokenType::Option:
|
||||
if (!attributes.empty())
|
||||
throw UnexpectedToken{};
|
||||
|
||||
context.root->statements.push_back(ParseOptionDeclaration());
|
||||
break;
|
||||
|
||||
case TokenType::FunctionDeclaration:
|
||||
context.root->statements.push_back(ParseFunctionDeclaration(std::move(attributes)));
|
||||
|
|
@ -450,14 +458,15 @@ namespace Nz::ShaderLang
|
|||
|
||||
Expect(Advance(), TokenType::ClosingCurlyBracket);
|
||||
|
||||
std::optional<ShaderStageType> entryPoint;
|
||||
auto func = ShaderBuilder::DeclareFunction(std::move(functionName), std::move(parameters), std::move(functionBody), std::move(returnType));
|
||||
|
||||
for (const auto& [attributeType, arg] : attributes)
|
||||
{
|
||||
switch (attributeType)
|
||||
{
|
||||
case ShaderAst::AttributeType::Entry:
|
||||
{
|
||||
if (entryPoint)
|
||||
if (func->entryStage)
|
||||
throw AttributeError{ "attribute entry must be present once" };
|
||||
|
||||
if (!std::holds_alternative<std::string>(arg))
|
||||
|
|
@ -469,7 +478,19 @@ namespace Nz::ShaderLang
|
|||
if (it == s_entryPoints.end())
|
||||
throw AttributeError{ ("invalid parameter " + argStr + " for entry attribute").c_str() };
|
||||
|
||||
entryPoint = it->second;
|
||||
func->entryStage = it->second;
|
||||
break;
|
||||
}
|
||||
|
||||
case ShaderAst::AttributeType::Option:
|
||||
{
|
||||
if (!func->optionName.empty())
|
||||
throw AttributeError{ "attribute option must be present once" };
|
||||
|
||||
if (!std::holds_alternative<std::string>(arg))
|
||||
throw AttributeError{ "attribute option requires a string parameter" };
|
||||
|
||||
func->optionName = std::get<std::string>(arg);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -477,8 +498,8 @@ namespace Nz::ShaderLang
|
|||
throw AttributeError{ "unhandled attribute for function" };
|
||||
}
|
||||
}
|
||||
|
||||
return ShaderBuilder::DeclareFunction(entryPoint, std::move(functionName), std::move(parameters), std::move(functionBody), std::move(returnType));
|
||||
|
||||
return func;
|
||||
}
|
||||
|
||||
ShaderAst::DeclareFunctionStatement::Parameter Parser::ParseFunctionParameter()
|
||||
|
|
@ -492,6 +513,29 @@ namespace Nz::ShaderLang
|
|||
return { parameterName, parameterType };
|
||||
}
|
||||
|
||||
ShaderAst::StatementPtr Parser::ParseOptionDeclaration()
|
||||
{
|
||||
Expect(Advance(), TokenType::Option);
|
||||
|
||||
std::string optionName = ParseIdentifierAsName();
|
||||
|
||||
Expect(Advance(), TokenType::Colon);
|
||||
|
||||
ShaderAst::ExpressionType optionType = ParseType();
|
||||
|
||||
ShaderAst::ExpressionPtr initialValue;
|
||||
if (Peek().type == TokenType::Assign)
|
||||
{
|
||||
Consume();
|
||||
|
||||
initialValue = ParseExpression();
|
||||
}
|
||||
|
||||
Expect(Advance(), TokenType::Semicolon);
|
||||
|
||||
return ShaderBuilder::DeclareOption(std::move(optionName), std::move(optionType), std::move(initialValue));
|
||||
}
|
||||
|
||||
ShaderAst::StatementPtr Parser::ParseStructDeclaration(std::vector<ShaderAst::Attribute> attributes)
|
||||
{
|
||||
Expect(Advance(), TokenType::Struct);
|
||||
|
|
@ -871,12 +915,35 @@ namespace Nz::ShaderLang
|
|||
|
||||
case TokenType::OpenParenthesis:
|
||||
return ParseParenthesisExpression();
|
||||
|
||||
case TokenType::SelectOpt:
|
||||
return ParseSelectOptExpression();
|
||||
|
||||
default:
|
||||
throw UnexpectedToken{};
|
||||
}
|
||||
}
|
||||
|
||||
ShaderAst::ExpressionPtr Parser::ParseSelectOptExpression()
|
||||
{
|
||||
Expect(Advance(), TokenType::SelectOpt);
|
||||
Expect(Advance(), TokenType::OpenParenthesis);
|
||||
|
||||
std::string optionName = ParseIdentifierAsName();
|
||||
|
||||
Expect(Advance(), TokenType::Comma);
|
||||
|
||||
ShaderAst::ExpressionPtr trueExpr = ParseExpression();
|
||||
|
||||
Expect(Advance(), TokenType::Comma);
|
||||
|
||||
ShaderAst::ExpressionPtr falseExpr = ParseExpression();
|
||||
|
||||
Expect(Advance(), TokenType::ClosingParenthesis);
|
||||
|
||||
return ShaderBuilder::SelectOption(std::move(optionName), std::move(trueExpr), std::move(falseExpr));
|
||||
}
|
||||
|
||||
ShaderAst::AttributeType Parser::ParseIdentifierAsAttributeType()
|
||||
{
|
||||
const Token& identifierToken = Expect(Advance(), TokenType::Identifier);
|
||||
|
|
|
|||
|
|
@ -502,7 +502,7 @@ namespace Nz
|
|||
|
||||
void SpirvAstVisitor::Visit(ShaderAst::ConditionalExpression& node)
|
||||
{
|
||||
if (m_writer.IsConditionEnabled(node.conditionName))
|
||||
if (m_writer.IsOptionEnabled(node.optionIndex))
|
||||
node.truePath->Visit(*this);
|
||||
else
|
||||
node.falsePath->Visit(*this);
|
||||
|
|
@ -510,7 +510,7 @@ namespace Nz
|
|||
|
||||
void SpirvAstVisitor::Visit(ShaderAst::ConditionalStatement& node)
|
||||
{
|
||||
if (m_writer.IsConditionEnabled(node.conditionName))
|
||||
if (m_writer.IsOptionEnabled(node.optionIndex))
|
||||
node.statement->Visit(*this);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ namespace Nz
|
|||
using StructContainer = std::vector<ShaderAst::StructDescription>;
|
||||
|
||||
PreVisitor(const SpirvWriter::States& conditions, SpirvConstantCache& constantCache, std::vector<SpirvAstVisitor::FuncData>& funcs) :
|
||||
m_conditions(conditions),
|
||||
m_states(conditions),
|
||||
m_constantCache(constantCache),
|
||||
m_externalBlockIndex(0),
|
||||
m_funcs(funcs)
|
||||
|
|
@ -80,24 +80,18 @@ namespace Nz
|
|||
|
||||
void Visit(ShaderAst::ConditionalExpression& node) override
|
||||
{
|
||||
/*std::size_t conditionIndex = m_shader.FindConditionByName(node.conditionName);
|
||||
assert(conditionIndex != ShaderAst::InvalidCondition);
|
||||
|
||||
if (TestBit<Nz::UInt64>(m_conditions.enabledConditions, conditionIndex))
|
||||
Visit(node.truePath);
|
||||
if (TestBit<Nz::UInt64>(m_states.enabledOptions, node.optionIndex))
|
||||
node.truePath->Visit(*this);
|
||||
else
|
||||
Visit(node.falsePath);*/
|
||||
node.falsePath->Visit(*this);
|
||||
|
||||
m_constantCache.Register(*m_constantCache.BuildType(node.cachedExpressionType.value()));
|
||||
}
|
||||
|
||||
void Visit(ShaderAst::ConditionalStatement& node) override
|
||||
{
|
||||
/*std::size_t conditionIndex = m_shader.FindConditionByName(node.conditionName);
|
||||
assert(conditionIndex != ShaderAst::InvalidCondition);
|
||||
|
||||
if (TestBit<Nz::UInt64>(m_conditions.enabledConditions, conditionIndex))
|
||||
Visit(node.statement);*/
|
||||
if (TestBit<Nz::UInt64>(m_states.enabledOptions, node.optionIndex))
|
||||
node.statement->Visit(*this);
|
||||
}
|
||||
|
||||
void Visit(ShaderAst::ConstantExpression& node) override
|
||||
|
|
@ -347,7 +341,7 @@ namespace Nz
|
|||
StructContainer declaredStructs;
|
||||
|
||||
private:
|
||||
const SpirvWriter::States& m_conditions;
|
||||
const SpirvWriter::States& m_states;
|
||||
SpirvConstantCache& m_constantCache;
|
||||
std::optional<std::size_t> m_funcIndex;
|
||||
std::size_t m_externalBlockIndex;
|
||||
|
|
@ -390,11 +384,11 @@ namespace Nz
|
|||
{
|
||||
}
|
||||
|
||||
std::vector<UInt32> SpirvWriter::Generate(ShaderAst::StatementPtr& shader, const States& conditions)
|
||||
std::vector<UInt32> SpirvWriter::Generate(ShaderAst::StatementPtr& shader, const States& states)
|
||||
{
|
||||
ShaderAst::StatementPtr sanitizedAst = ShaderAst::Sanitize(shader);
|
||||
|
||||
m_context.states = &conditions;
|
||||
m_context.states = &states;
|
||||
|
||||
State state;
|
||||
m_currentState = &state;
|
||||
|
|
@ -404,7 +398,7 @@ namespace Nz
|
|||
});
|
||||
|
||||
// Register all extended instruction sets
|
||||
PreVisitor preVisitor(conditions, state.constantTypeCache, state.funcs);
|
||||
PreVisitor preVisitor(states, state.constantTypeCache, state.funcs);
|
||||
sanitizedAst->Visit(preVisitor);
|
||||
|
||||
m_currentState->preVisitor = &preVisitor;
|
||||
|
|
@ -559,6 +553,11 @@ namespace Nz
|
|||
return m_currentState->constantTypeCache.GetId(*m_currentState->constantTypeCache.BuildType(type));
|
||||
}
|
||||
|
||||
bool SpirvWriter::IsOptionEnabled(std::size_t optionIndex) const
|
||||
{
|
||||
return TestBit<Nz::UInt64>(m_context.states->enabledOptions, optionIndex);
|
||||
}
|
||||
|
||||
UInt32 SpirvWriter::RegisterConstant(const ShaderAst::ConstantValue& value)
|
||||
{
|
||||
return m_currentState->constantTypeCache.Register(*m_currentState->constantTypeCache.BuildConstant(value));
|
||||
|
|
|
|||
|
|
@ -60,10 +60,10 @@ namespace Nz
|
|||
return stage;
|
||||
}
|
||||
|
||||
std::shared_ptr<ShaderModule> VulkanDevice::InstantiateShaderModule(ShaderStageTypeFlags stages, ShaderLanguage lang, const void* source, std::size_t sourceSize)
|
||||
std::shared_ptr<ShaderModule> VulkanDevice::InstantiateShaderModule(ShaderStageTypeFlags stages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states)
|
||||
{
|
||||
auto stage = std::make_shared<VulkanShaderModule>();
|
||||
if (!stage->Create(*this, stages, lang, source, sourceSize))
|
||||
if (!stage->Create(*this, stages, lang, source, sourceSize, states))
|
||||
throw std::runtime_error("failed to instanciate vulkan shader module");
|
||||
|
||||
return stage;
|
||||
|
|
|
|||
|
|
@ -65,10 +65,10 @@ namespace Nz
|
|||
writer.SetEnv(env);
|
||||
|
||||
std::vector<UInt32> code = writer.Generate(shaderAst, states);
|
||||
return Create(device, shaderStages, ShaderLanguage::SpirV, code.data(), code.size() * sizeof(UInt32));
|
||||
return Create(device, shaderStages, ShaderLanguage::SpirV, code.data(), code.size() * sizeof(UInt32), {});
|
||||
}
|
||||
|
||||
bool VulkanShaderModule::Create(Vk::Device& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize)
|
||||
bool VulkanShaderModule::Create(Vk::Device& device, ShaderStageTypeFlags shaderStages, ShaderLanguage lang, const void* source, std::size_t sourceSize, const ShaderWriter::States& states)
|
||||
{
|
||||
switch (lang)
|
||||
{
|
||||
|
|
@ -89,7 +89,7 @@ namespace Nz
|
|||
|
||||
Nz::ShaderLang::Parser parser;
|
||||
Nz::ShaderAst::StatementPtr shaderAst = parser.Parse(tokens);
|
||||
return Create(device, shaderStages, shaderAst, {});
|
||||
return Create(device, shaderStages, shaderAst, states);
|
||||
}
|
||||
|
||||
case ShaderLanguage::SpirV:
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ Nz::ShaderAst::NodePtr ConditionalExpression::BuildNode(Nz::ShaderAst::Expressio
|
|||
const ShaderGraph& graph = GetGraph();
|
||||
|
||||
const auto& conditionEntry = graph.GetCondition(*m_currentConditionIndex);
|
||||
return Nz::ShaderBuilder::ConditionalExpression(conditionEntry.name, std::move(expressions[0]), std::move(expressions[1]));
|
||||
return Nz::ShaderBuilder::SelectOption(conditionEntry.name, std::move(expressions[0]), std::move(expressions[1]));
|
||||
}
|
||||
|
||||
QString ConditionalExpression::caption() const
|
||||
|
|
|
|||
|
|
@ -454,6 +454,10 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst() const
|
|||
{
|
||||
std::vector<Nz::ShaderAst::StatementPtr> statements;
|
||||
|
||||
// Declare all options
|
||||
for (const auto& condition : m_conditions)
|
||||
statements.push_back(Nz::ShaderBuilder::DeclareOption(condition.name, Nz::ShaderAst::PrimitiveType::Boolean));
|
||||
|
||||
// Declare all structures
|
||||
for (const auto& structInfo : m_structs)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue