Shader: Merge AstScopedVisitor, AstValidator and TransformVisitor to SanitizeVisitor

This commit is contained in:
Jérôme Leclercq
2021-04-15 11:20:56 +02:00
parent 8515c9cea1
commit afe3a0ea93
19 changed files with 1027 additions and 1339 deletions

View File

@@ -0,0 +1,112 @@
// 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_SHADERAST_TRANSFORMVISITOR_HPP
#define NAZARA_SHADERAST_TRANSFORMVISITOR_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Shader/Config.hpp>
#include <Nazara/Shader/ShaderAstCloner.hpp>
#include <vector>
namespace Nz::ShaderAst
{
class NAZARA_SHADER_API SanitizeVisitor final : AstCloner
{
public:
inline SanitizeVisitor();
SanitizeVisitor(const SanitizeVisitor&) = delete;
SanitizeVisitor(SanitizeVisitor&&) = delete;
~SanitizeVisitor() = default;
StatementPtr Sanitize(StatementPtr& statement, std::string* error = nullptr);
SanitizeVisitor& operator=(const SanitizeVisitor&) = delete;
SanitizeVisitor& operator=(SanitizeVisitor&&) = delete;
private:
struct Identifier;
const ExpressionType& CheckField(const ExpressionType& structType, const std::string* memberIdentifier, std::size_t remainingMembers, std::size_t* structIndices);
using AstCloner::CloneExpression;
ExpressionPtr Clone(AccessMemberIdentifierExpression& node) override;
ExpressionPtr Clone(AssignExpression& node) override;
ExpressionPtr Clone(BinaryExpression& node) override;
ExpressionPtr Clone(CastExpression& node) override;
ExpressionPtr Clone(ConditionalExpression& node) override;
ExpressionPtr Clone(ConstantExpression& node) override;
ExpressionPtr Clone(IdentifierExpression& node) override;
ExpressionPtr Clone(IntrinsicExpression& 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(DeclareStructStatement& node) override;
StatementPtr Clone(DeclareVariableStatement& node) override;
StatementPtr Clone(ExpressionStatement& node) override;
StatementPtr Clone(MultiStatement& node) override;
inline const Identifier* FindIdentifier(const std::string_view& identifierName) const;
Expression& MandatoryExpr(ExpressionPtr& node);
Statement& MandatoryStatement(StatementPtr& node);
void TypeMustMatch(ExpressionPtr& left, ExpressionPtr& right);
void TypeMustMatch(const ExpressionType& left, const ExpressionType& right);
void PushScope();
void PopScope();
inline std::size_t RegisterFunction(std::string name);
inline std::size_t RegisterStruct(std::string name, StructDescription description);
inline std::size_t RegisterVariable(std::string name, ExpressionType type);
std::size_t ResolveStruct(const ExpressionType& exprType);
std::size_t ResolveStruct(const IdentifierType& identifierType);
std::size_t ResolveStruct(const StructType& structType);
std::size_t ResolveStruct(const UniformType& uniformType);
ExpressionType ResolveType(const ExpressionType& exprType);
struct Alias
{
std::variant<ExpressionType> value;
};
struct Struct
{
std::size_t structIndex;
};
struct Variable
{
std::size_t varIndex;
};
struct Identifier
{
std::string name;
std::variant<Alias, Struct, Variable> value;
};
std::size_t m_nextFuncIndex;
std::vector<Identifier> m_identifiersInScope;
std::vector<StructDescription> m_structs;
std::vector<ExpressionType> m_variables;
std::vector<std::size_t> m_scopeSizes;
struct Context;
Context* m_context;
};
inline StatementPtr Sanitize(StatementPtr& ast, std::string* error = nullptr);
}
#include <Nazara/Shader/Ast/SanitizeVisitor.inl>
#endif

View File

@@ -2,18 +2,17 @@
// 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/Ast/TransformVisitor.hpp>
#include <Nazara/Shader/Ast/SanitizeVisitor.hpp>
#include <Nazara/Shader/Debug.hpp>
namespace Nz::ShaderAst
{
inline TransformVisitor::TransformVisitor() :
m_nextFuncIndex(0),
m_nextVarIndex(0)
inline SanitizeVisitor::SanitizeVisitor() :
m_nextFuncIndex(0)
{
}
inline auto TransformVisitor::FindIdentifier(const std::string_view& identifierName) const -> const Identifier*
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; });
if (it == m_identifiersInScope.rend())
@@ -22,14 +21,14 @@ namespace Nz::ShaderAst
return &*it;
}
inline std::size_t TransformVisitor::RegisterFunction(std::string name)
inline std::size_t SanitizeVisitor::RegisterFunction(std::string name)
{
std::size_t funcIndex = m_nextFuncIndex++;
return funcIndex;
}
inline std::size_t TransformVisitor::RegisterStruct(std::string name, StructDescription description)
inline std::size_t SanitizeVisitor::RegisterStruct(std::string name, StructDescription description)
{
std::size_t structIndex = m_structs.size();
m_structs.emplace_back(std::move(description));
@@ -44,9 +43,10 @@ namespace Nz::ShaderAst
return structIndex;
}
inline std::size_t TransformVisitor::RegisterVariable(std::string name)
inline std::size_t SanitizeVisitor::RegisterVariable(std::string name, ExpressionType type)
{
std::size_t varIndex = m_nextVarIndex++;
std::size_t varIndex = m_variables.size();
m_variables.emplace_back(std::move(type));
m_identifiersInScope.push_back({
std::move(name),
@@ -57,6 +57,12 @@ namespace Nz::ShaderAst
return varIndex;
}
StatementPtr Sanitize(StatementPtr& ast, std::string* error)
{
SanitizeVisitor sanitizer;
return sanitizer.Sanitize(ast, error);
}
}
#include <Nazara/Shader/DebugOff.hpp>

View File

@@ -1,90 +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_SHADERAST_TRANSFORMVISITOR_HPP
#define NAZARA_SHADERAST_TRANSFORMVISITOR_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Shader/Config.hpp>
#include <Nazara/Shader/ShaderAstCloner.hpp>
#include <vector>
namespace Nz::ShaderAst
{
class NAZARA_SHADER_API TransformVisitor : AstCloner
{
public:
inline TransformVisitor();
TransformVisitor(const TransformVisitor&) = delete;
TransformVisitor(TransformVisitor&&) = delete;
~TransformVisitor() = default;
StatementPtr Transform(StatementPtr& statement);
TransformVisitor& operator=(const TransformVisitor&) = delete;
TransformVisitor& operator=(TransformVisitor&&) = delete;
private:
struct Identifier;
ExpressionPtr Clone(AccessMemberIdentifierExpression& node) override;
ExpressionPtr Clone(CastExpression& node) override;
ExpressionPtr Clone(IdentifierExpression& node) override;
ExpressionPtr CloneExpression(ExpressionPtr& expr) override;
inline const Identifier* FindIdentifier(const std::string_view& identifierName) const;
void PushScope();
void PopScope();
inline std::size_t RegisterFunction(std::string name);
inline std::size_t RegisterStruct(std::string name, StructDescription description);
inline std::size_t RegisterVariable(std::string name);
ExpressionType ResolveType(const ExpressionType& exprType);
using AstCloner::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 Struct
{
std::size_t structIndex;
};
struct Variable
{
std::size_t varIndex;
};
struct Identifier
{
std::string name;
std::variant<Alias, Struct, Variable> value;
};
private:
std::size_t m_nextFuncIndex;
std::size_t m_nextVarIndex;
std::vector<Identifier> m_identifiersInScope;
std::vector<StructDescription> m_structs;
std::vector<std::size_t> m_scopeSizes;
};
}
#include <Nazara/Shader/Ast/TransformVisitor.inl>
#endif

View File

@@ -24,12 +24,12 @@ namespace Nz
struct Environment;
using ExtSupportCallback = std::function<bool(const std::string_view& name)>;
GlslWriter();
inline GlslWriter();
GlslWriter(const GlslWriter&) = delete;
GlslWriter(GlslWriter&&) = delete;
~GlslWriter() = default;
std::string Generate(ShaderAst::StatementPtr& shader, const States& conditions = {});
inline std::string Generate(ShaderAst::StatementPtr& shader, const States& conditions = {});
std::string Generate(std::optional<ShaderStageType> shaderStage, ShaderAst::StatementPtr& shader, const States& conditions = {});
void SetEnv(Environment environment);

View File

@@ -7,6 +7,15 @@
namespace Nz
{
inline GlslWriter::GlslWriter() :
m_currentState(nullptr)
{
}
inline std::string GlslWriter::Generate(ShaderAst::StatementPtr& shader, const States& conditions)
{
return Generate(std::nullopt, shader, conditions);
}
}
#include <Nazara/Shader/DebugOff.hpp>

View File

@@ -30,9 +30,11 @@ namespace Nz::ShaderAst
AstCloner& operator=(AstCloner&&) = delete;
protected:
virtual ExpressionPtr CloneExpression(ExpressionPtr& expr);
virtual StatementPtr CloneStatement(StatementPtr& statement);
inline ExpressionPtr CloneExpression(ExpressionPtr& expr);
inline StatementPtr CloneStatement(StatementPtr& statement);
virtual ExpressionPtr CloneExpression(Expression& expr);
virtual StatementPtr CloneStatement(Statement& statement);
virtual ExpressionPtr Clone(AccessMemberIdentifierExpression& node);
virtual ExpressionPtr Clone(AccessMemberIndexExpression& node);

View File

@@ -7,6 +7,22 @@
namespace Nz::ShaderAst
{
ExpressionPtr AstCloner::CloneExpression(ExpressionPtr& expr)
{
if (!expr)
return nullptr;
return CloneExpression(*expr);
}
StatementPtr AstCloner::CloneStatement(StatementPtr& statement)
{
if (!statement)
return nullptr;
return CloneStatement(*statement);
}
inline ExpressionPtr Clone(ExpressionPtr& node)
{
AstCloner cloner;

View File

@@ -1,68 +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_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

View File

@@ -1,38 +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/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>

View File

@@ -1,66 +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_SHADERVALIDATOR_HPP
#define NAZARA_SHADERVALIDATOR_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Shader/Config.hpp>
#include <Nazara/Shader/ShaderAstScopedVisitor.hpp>
#include <Nazara/Utility/Enums.hpp>
namespace Nz::ShaderAst
{
class NAZARA_SHADER_API AstValidator final : public AstScopedVisitor
{
public:
inline AstValidator();
AstValidator(const AstValidator&) = delete;
AstValidator(AstValidator&&) = delete;
~AstValidator() = default;
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);
const ExpressionType& ResolveAlias(const ExpressionType& expressionType);
void Visit(AccessMemberIdentifierExpression& node) override;
void Visit(AssignExpression& node) override;
void Visit(BinaryExpression& node) override;
void Visit(CastExpression& 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;
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(ExpressionStatement& node) override;
void Visit(MultiStatement& node) override;
struct Context;
Context* m_context;
};
NAZARA_SHADER_API bool ValidateAst(StatementPtr& node, std::string* error = nullptr);
}
#include <Nazara/Shader/ShaderAstValidator.inl>
#endif

View File

@@ -1,16 +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/ShaderAstValidator.hpp>
#include <Nazara/Shader/Debug.hpp>
namespace Nz::ShaderAst
{
AstValidator::AstValidator() :
m_context(nullptr)
{
}
}
#include <Nazara/Shader/DebugOff.hpp>