Shader: Rework scope handling
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Shader/Config.hpp>
|
||||
#include <Nazara/Shader/ShaderAstRecursiveVisitor.hpp>
|
||||
#include <Nazara/Shader/ShaderAstScopedVisitor.hpp>
|
||||
#include <Nazara/Shader/ShaderWriter.hpp>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class NAZARA_SHADER_API GlslWriter : public ShaderWriter, public ShaderAst::AstRecursiveVisitor
|
||||
class NAZARA_SHADER_API GlslWriter : public ShaderWriter, public ShaderAst::AstScopedVisitor
|
||||
{
|
||||
public:
|
||||
struct Environment;
|
||||
@@ -57,8 +57,8 @@ 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);
|
||||
void AppendField(std::size_t scopeId, const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers);
|
||||
void AppendEntryPoint(ShaderStageType shaderStage, ShaderAst::StatementPtr& shader);
|
||||
void AppendField(const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers);
|
||||
void AppendLine(const std::string& txt = {});
|
||||
template<typename... Args> void AppendLine(Args&&... params);
|
||||
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
// 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_SHADERASTCACHE_HPP
|
||||
#define NAZARA_SHADERASTCACHE_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Shader/Config.hpp>
|
||||
#include <Nazara/Shader/ShaderAstExpressionType.hpp>
|
||||
#include <Nazara/Utility/Enums.hpp>
|
||||
|
||||
namespace Nz::ShaderAst
|
||||
{
|
||||
struct AstCache
|
||||
{
|
||||
struct Identifier;
|
||||
|
||||
struct Alias
|
||||
{
|
||||
std::variant<ExpressionType> value;
|
||||
};
|
||||
|
||||
struct Variable
|
||||
{
|
||||
ExpressionType type;
|
||||
};
|
||||
|
||||
struct Identifier
|
||||
{
|
||||
std::string name;
|
||||
std::variant<Alias, Variable, StructDescription> value;
|
||||
};
|
||||
|
||||
struct Scope
|
||||
{
|
||||
std::optional<std::size_t> parentScopeIndex;
|
||||
std::vector<Identifier> identifiers;
|
||||
};
|
||||
|
||||
inline void Clear();
|
||||
inline const Identifier* FindIdentifier(std::size_t startingScopeId, const std::string& identifierName) const;
|
||||
inline std::size_t GetScopeId(const Node* node) const;
|
||||
|
||||
std::array<DeclareFunctionStatement*, ShaderStageTypeCount> entryFunctions = {};
|
||||
std::unordered_map<const Expression*, ExpressionType> nodeExpressionType;
|
||||
std::unordered_map<const Node*, std::size_t> scopeIdByNode;
|
||||
std::vector<Scope> scopes;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Shader/ShaderAstCache.inl>
|
||||
|
||||
#endif
|
||||
@@ -1,45 +0,0 @@
|
||||
// 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/ShaderAstCache.hpp>
|
||||
#include <Nazara/Shader/Debug.hpp>
|
||||
|
||||
namespace Nz::ShaderAst
|
||||
{
|
||||
inline void AstCache::Clear()
|
||||
{
|
||||
entryFunctions.fill(nullptr);
|
||||
nodeExpressionType.clear();
|
||||
scopeIdByNode.clear();
|
||||
scopes.clear();
|
||||
}
|
||||
|
||||
inline auto AstCache::FindIdentifier(std::size_t startingScopeId, const std::string& identifierName) const -> const Identifier*
|
||||
{
|
||||
assert(startingScopeId < scopes.size());
|
||||
|
||||
std::optional<std::size_t> scopeId = startingScopeId;
|
||||
do
|
||||
{
|
||||
const auto& scope = scopes[*scopeId];
|
||||
auto it = std::find_if(scope.identifiers.rbegin(), scope.identifiers.rend(), [&](const auto& identifier) { return identifier.name == identifierName; });
|
||||
if (it != scope.identifiers.rend())
|
||||
return &*it;
|
||||
|
||||
scopeId = scope.parentScopeIndex;
|
||||
} while (scopeId);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline std::size_t AstCache::GetScopeId(const Node* node) const
|
||||
{
|
||||
auto it = scopeIdByNode.find(node);
|
||||
assert(it != scopeIdByNode.end());
|
||||
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Shader/DebugOff.hpp>
|
||||
@@ -33,7 +33,7 @@ namespace Nz::ShaderAst
|
||||
ExpressionPtr CloneExpression(ExpressionPtr& expr);
|
||||
StatementPtr CloneStatement(StatementPtr& statement);
|
||||
|
||||
virtual std::unique_ptr<DeclareFunctionStatement> Clone(DeclareFunctionStatement& node);
|
||||
virtual StatementPtr Clone(DeclareFunctionStatement& node);
|
||||
|
||||
using AstExpressionVisitor::Visit;
|
||||
using AstStatementVisitor::Visit;
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
// 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_SHADERASTEXPRESSIONTYPE_HPP
|
||||
#define NAZARA_SHADERASTEXPRESSIONTYPE_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Shader/Config.hpp>
|
||||
#include <Nazara/Shader/ShaderAstExpressionVisitor.hpp>
|
||||
#include <Nazara/Shader/Ast/ExpressionType.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace Nz::ShaderAst
|
||||
{
|
||||
struct AstCache;
|
||||
|
||||
class NAZARA_SHADER_API ExpressionTypeVisitor : public AstExpressionVisitor
|
||||
{
|
||||
public:
|
||||
ExpressionTypeVisitor() = default;
|
||||
ExpressionTypeVisitor(const ExpressionTypeVisitor&) = delete;
|
||||
ExpressionTypeVisitor(ExpressionTypeVisitor&&) = delete;
|
||||
~ExpressionTypeVisitor() = default;
|
||||
|
||||
ExpressionType GetExpressionType(Expression& expression, AstCache* cache);
|
||||
|
||||
ExpressionTypeVisitor& operator=(const ExpressionTypeVisitor&) = delete;
|
||||
ExpressionTypeVisitor& operator=(ExpressionTypeVisitor&&) = delete;
|
||||
|
||||
private:
|
||||
ExpressionType GetExpressionTypeInternal(Expression& expression);
|
||||
ExpressionType ResolveAlias(Expression& expression, ExpressionType expressionType);
|
||||
|
||||
void Visit(Expression& expression);
|
||||
|
||||
void Visit(AccessMemberExpression& node) override;
|
||||
void Visit(AssignExpression& node) override;
|
||||
void Visit(BinaryExpression& node) override;
|
||||
void Visit(CastExpression& node) override;
|
||||
void Visit(ConditionalExpression& node) override;
|
||||
void Visit(ConstantExpression& node) override;
|
||||
void Visit(IdentifierExpression& node) override;
|
||||
void Visit(IntrinsicExpression& node) override;
|
||||
void Visit(SwizzleExpression& node) override;
|
||||
|
||||
AstCache* m_cache;
|
||||
std::optional<ExpressionType> m_lastExpressionType;
|
||||
};
|
||||
|
||||
inline ExpressionType GetExpressionType(Expression& expression, AstCache* cache = nullptr);
|
||||
}
|
||||
|
||||
#include <Nazara/Shader/ShaderAstExpressionType.inl>
|
||||
|
||||
#endif
|
||||
@@ -1,17 +0,0 @@
|
||||
// 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/ShaderAstExpressionType.hpp>
|
||||
#include <Nazara/Shader/Debug.hpp>
|
||||
|
||||
namespace Nz::ShaderAst
|
||||
{
|
||||
inline ExpressionType GetExpressionType(Expression& expression, AstCache* cache)
|
||||
{
|
||||
ExpressionTypeVisitor visitor;
|
||||
return visitor.GetExpressionType(expression, cache);
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Shader/DebugOff.hpp>
|
||||
68
include/Nazara/Shader/ShaderAstScopedVisitor.hpp
Normal file
68
include/Nazara/Shader/ShaderAstScopedVisitor.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright (C) 2020 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Shader generator"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SHADER_SCOPED_VISITOR_HPP
|
||||
#define NAZARA_SHADER_SCOPED_VISITOR_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Shader/Config.hpp>
|
||||
#include <Nazara/Shader/ShaderAstRecursiveVisitor.hpp>
|
||||
|
||||
namespace Nz::ShaderAst
|
||||
{
|
||||
class NAZARA_SHADER_API AstScopedVisitor : public AstRecursiveVisitor
|
||||
{
|
||||
public:
|
||||
struct Identifier;
|
||||
|
||||
AstScopedVisitor() = default;
|
||||
~AstScopedVisitor() = default;
|
||||
|
||||
inline const Identifier* FindIdentifier(const std::string_view& identifierName) const;
|
||||
|
||||
void ScopedVisit(StatementPtr& nodePtr);
|
||||
|
||||
using AstRecursiveVisitor::Visit;
|
||||
void Visit(BranchStatement& node) override;
|
||||
void Visit(ConditionalStatement& node) override;
|
||||
void Visit(DeclareExternalStatement& node) override;
|
||||
void Visit(DeclareFunctionStatement& node) override;
|
||||
void Visit(DeclareStructStatement& node) override;
|
||||
void Visit(DeclareVariableStatement& node) override;
|
||||
void Visit(MultiStatement& node) override;
|
||||
|
||||
struct Alias
|
||||
{
|
||||
std::variant<ExpressionType> value;
|
||||
};
|
||||
|
||||
struct Variable
|
||||
{
|
||||
ExpressionType type;
|
||||
};
|
||||
|
||||
struct Identifier
|
||||
{
|
||||
std::string name;
|
||||
std::variant<Alias, Variable, StructDescription> value;
|
||||
};
|
||||
|
||||
protected:
|
||||
void PushScope();
|
||||
void PopScope();
|
||||
|
||||
inline void RegisterStruct(StructDescription structDesc);
|
||||
inline void RegisterVariable(std::string name, ExpressionType type);
|
||||
|
||||
private:
|
||||
std::vector<Identifier> m_identifiersInScope;
|
||||
std::vector<std::size_t> m_scopeSizes;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Shader/ShaderAstScopedVisitor.inl>
|
||||
|
||||
#endif
|
||||
38
include/Nazara/Shader/ShaderAstScopedVisitor.inl
Normal file
38
include/Nazara/Shader/ShaderAstScopedVisitor.inl
Normal file
@@ -0,0 +1,38 @@
|
||||
// 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/ShaderAstScopedVisitor.hpp>
|
||||
#include <Nazara/Shader/Debug.hpp>
|
||||
|
||||
namespace Nz::ShaderAst
|
||||
{
|
||||
inline auto AstScopedVisitor::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; });
|
||||
if (it == m_identifiersInScope.rend())
|
||||
return nullptr;
|
||||
|
||||
return &*it;
|
||||
}
|
||||
|
||||
inline void AstScopedVisitor::RegisterStruct(StructDescription structDesc)
|
||||
{
|
||||
std::string name = structDesc.name;
|
||||
|
||||
m_identifiersInScope.push_back({
|
||||
std::move(name),
|
||||
std::move(structDesc)
|
||||
});
|
||||
}
|
||||
|
||||
inline void AstScopedVisitor::RegisterVariable(std::string name, ExpressionType type)
|
||||
{
|
||||
m_identifiersInScope.push_back({
|
||||
std::move(name),
|
||||
Variable { std::move(type) }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Shader/DebugOff.hpp>
|
||||
@@ -9,13 +9,12 @@
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Shader/Config.hpp>
|
||||
#include <Nazara/Shader/ShaderAstCache.hpp>
|
||||
#include <Nazara/Shader/ShaderAstRecursiveVisitor.hpp>
|
||||
#include <Nazara/Shader/ShaderAstScopedVisitor.hpp>
|
||||
#include <Nazara/Utility/Enums.hpp>
|
||||
|
||||
namespace Nz::ShaderAst
|
||||
{
|
||||
class NAZARA_SHADER_API AstValidator : public AstRecursiveVisitor
|
||||
class NAZARA_SHADER_API AstValidator final : public AstScopedVisitor
|
||||
{
|
||||
public:
|
||||
inline AstValidator();
|
||||
@@ -23,28 +22,24 @@ namespace Nz::ShaderAst
|
||||
AstValidator(AstValidator&&) = delete;
|
||||
~AstValidator() = default;
|
||||
|
||||
bool Validate(StatementPtr& node, std::string* error = nullptr, AstCache* cache = nullptr);
|
||||
bool Validate(StatementPtr& node, std::string* error = nullptr);
|
||||
|
||||
private:
|
||||
const ExpressionType& GetExpressionType(Expression& expression);
|
||||
Expression& MandatoryExpr(ExpressionPtr& node);
|
||||
Statement& MandatoryStatement(StatementPtr& node);
|
||||
void TypeMustMatch(ExpressionPtr& left, ExpressionPtr& right);
|
||||
void TypeMustMatch(const ExpressionType& left, const ExpressionType& right);
|
||||
|
||||
ExpressionType CheckField(const std::string& structName, const std::string* memberIdentifier, std::size_t remainingMembers);
|
||||
|
||||
AstCache::Scope& EnterScope();
|
||||
void ExitScope();
|
||||
|
||||
void RegisterExpressionType(Expression& node, ExpressionType expressionType);
|
||||
void RegisterScope(Node& node);
|
||||
const ExpressionType& ResolveAlias(const ExpressionType& expressionType);
|
||||
|
||||
void Visit(AccessMemberExpression& node) override;
|
||||
void Visit(AssignExpression& node) override;
|
||||
void Visit(BinaryExpression& node) override;
|
||||
void Visit(CastExpression& node) override;
|
||||
void Visit(ConditionalExpression& node) override;
|
||||
void Visit(ConstantExpression& node) override;
|
||||
void Visit(ConditionalExpression& node) override;
|
||||
void Visit(IdentifierExpression& node) override;
|
||||
void Visit(IntrinsicExpression& node) override;
|
||||
void Visit(SwizzleExpression& node) override;
|
||||
@@ -54,17 +49,15 @@ namespace Nz::ShaderAst
|
||||
void Visit(DeclareExternalStatement& node) override;
|
||||
void Visit(DeclareFunctionStatement& node) override;
|
||||
void Visit(DeclareStructStatement& node) override;
|
||||
void Visit(DeclareVariableStatement& node) override;
|
||||
void Visit(ExpressionStatement& node) override;
|
||||
void Visit(MultiStatement& node) override;
|
||||
void Visit(ReturnStatement& node) override;
|
||||
|
||||
struct Context;
|
||||
|
||||
Context* m_context;
|
||||
};
|
||||
|
||||
NAZARA_SHADER_API bool ValidateAst(StatementPtr& node, std::string* error = nullptr, AstCache* cache = nullptr);
|
||||
NAZARA_SHADER_API bool ValidateAst(StatementPtr& node, std::string* error = nullptr);
|
||||
}
|
||||
|
||||
#include <Nazara/Shader/ShaderAstValidator.inl>
|
||||
|
||||
@@ -56,6 +56,8 @@ namespace Nz::ShaderAst
|
||||
|
||||
Expression& operator=(const Expression&) = delete;
|
||||
Expression& operator=(Expression&&) noexcept = default;
|
||||
|
||||
std::optional<ExpressionType> cachedExpressionType;
|
||||
};
|
||||
|
||||
struct NAZARA_SHADER_API AccessMemberExpression : public Expression
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Nz
|
||||
class NAZARA_SHADER_API SpirvAstVisitor : public ShaderAst::ExpressionVisitorExcept, public ShaderAst::StatementVisitorExcept
|
||||
{
|
||||
public:
|
||||
inline SpirvAstVisitor(SpirvWriter& writer, std::vector<SpirvBlock>& blocks, ShaderAst::AstCache* cache);
|
||||
inline SpirvAstVisitor(SpirvWriter& writer, std::vector<SpirvBlock>& blocks);
|
||||
SpirvAstVisitor(const SpirvAstVisitor&) = delete;
|
||||
SpirvAstVisitor(SpirvAstVisitor&&) = delete;
|
||||
~SpirvAstVisitor() = default;
|
||||
@@ -53,10 +53,10 @@ namespace Nz
|
||||
SpirvAstVisitor& operator=(SpirvAstVisitor&&) = delete;
|
||||
|
||||
private:
|
||||
inline const ShaderAst::ExpressionType& GetExpressionType(ShaderAst::Expression& expr) const;
|
||||
void PushResultId(UInt32 value);
|
||||
UInt32 PopResultId();
|
||||
|
||||
ShaderAst::AstCache* m_cache;
|
||||
std::vector<SpirvBlock>& m_blocks;
|
||||
std::vector<UInt32> m_resultIds;
|
||||
SpirvBlock* m_currentBlock;
|
||||
|
||||
@@ -7,13 +7,18 @@
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline SpirvAstVisitor::SpirvAstVisitor(SpirvWriter& writer, std::vector<SpirvBlock>& blocks, ShaderAst::AstCache* cache) :
|
||||
m_cache(cache),
|
||||
inline SpirvAstVisitor::SpirvAstVisitor(SpirvWriter& writer, std::vector<SpirvBlock>& blocks) :
|
||||
m_blocks(blocks),
|
||||
m_writer(writer)
|
||||
{
|
||||
m_currentBlock = &m_blocks.back();
|
||||
}
|
||||
|
||||
inline const ShaderAst::ExpressionType& SpirvAstVisitor::GetExpressionType(ShaderAst::Expression& expr) const
|
||||
{
|
||||
assert(expr.cachedExpressionType);
|
||||
return expr.cachedExpressionType.value();
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Shader/DebugOff.hpp>
|
||||
|
||||
@@ -31,11 +31,14 @@ namespace Nz
|
||||
~SpirvConstantCache();
|
||||
|
||||
struct Constant;
|
||||
struct Identifier;
|
||||
struct Type;
|
||||
|
||||
using ConstantPtr = std::shared_ptr<Constant>;
|
||||
using TypePtr = std::shared_ptr<Type>;
|
||||
|
||||
using IdentifierCallback = std::function<TypePtr(const std::string& identifier)>;
|
||||
|
||||
struct Bool {};
|
||||
|
||||
struct Float
|
||||
@@ -63,6 +66,11 @@ namespace Nz
|
||||
UInt32 columnCount;
|
||||
};
|
||||
|
||||
struct Identifier
|
||||
{
|
||||
std::string name;
|
||||
};
|
||||
|
||||
struct Image
|
||||
{
|
||||
std::optional<SpirvAccessQualifier> qualifier;
|
||||
@@ -104,7 +112,7 @@ namespace Nz
|
||||
std::vector<Member> members;
|
||||
};
|
||||
|
||||
using AnyType = std::variant<Bool, Float, Function, Image, Integer, Matrix, Pointer, SampledImage, Structure, Vector, Void>;
|
||||
using AnyType = std::variant<Bool, Float, Function, Identifier, Image, Integer, Matrix, Pointer, SampledImage, Structure, Vector, Void>;
|
||||
|
||||
struct ConstantBool
|
||||
{
|
||||
@@ -166,6 +174,8 @@ namespace Nz
|
||||
UInt32 Register(Type t);
|
||||
UInt32 Register(Variable v);
|
||||
|
||||
void SetIdentifierCallback(IdentifierCallback callback);
|
||||
|
||||
void Write(SpirvSection& annotations, SpirvSection& constants, SpirvSection& debugInfos);
|
||||
|
||||
SpirvConstantCache& operator=(const SpirvConstantCache& cache) = delete;
|
||||
@@ -181,6 +191,7 @@ namespace Nz
|
||||
static TypePtr BuildType(const ShaderAst::NoType& type);
|
||||
static TypePtr BuildType(const ShaderAst::PrimitiveType& type);
|
||||
static TypePtr BuildType(const ShaderAst::SamplerType& type);
|
||||
static TypePtr BuildType(const ShaderAst::StructDescription& structDesc);
|
||||
static TypePtr BuildType(const ShaderAst::VectorType& type);
|
||||
|
||||
private:
|
||||
@@ -193,6 +204,7 @@ namespace Nz
|
||||
|
||||
void WriteStruct(const Structure& structData, UInt32 resultId, SpirvSection& annotations, SpirvSection& constants, SpirvSection& debugInfos);
|
||||
|
||||
IdentifierCallback m_identifierCallback;
|
||||
std::unique_ptr<Internal> m_internal;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user