From 960ab64d98c15e3df085a2e93234e1353cbff967 Mon Sep 17 00:00:00 2001 From: SirLynix Date: Sun, 27 Mar 2022 14:06:58 +0200 Subject: [PATCH] Shader: Add SourceLocation members TODO: Fill from Parser and use them for error throwing in SanitizeVisitor --- include/Nazara/Shader/Ast/AstCompare.hpp | 4 + include/Nazara/Shader/Ast/AstCompare.inl | 57 ++++++ include/Nazara/Shader/Ast/AstSerializer.hpp | 22 ++- include/Nazara/Shader/Ast/AstSerializer.inl | 9 + include/Nazara/Shader/Ast/ExpressionType.hpp | 2 + include/Nazara/Shader/Ast/Nodes.hpp | 15 +- include/Nazara/Shader/ShaderBuilder.inl | 7 +- include/Nazara/Shader/ShaderLangErrors.hpp | 17 +- include/Nazara/Shader/ShaderLangErrors.inl | 40 ---- .../Shader/ShaderLangSourceLocation.hpp | 36 ++++ .../Shader/ShaderLangSourceLocation.inl | 51 ++++++ src/Nazara/Shader/Ast/AstSerializer.cpp | 173 ++++++++++++------ src/Nazara/Shader/Ast/SanitizeVisitor.cpp | 25 +-- src/Nazara/Shader/GlslWriter.cpp | 4 +- src/Nazara/Shader/LangWriter.cpp | 4 +- 15 files changed, 329 insertions(+), 137 deletions(-) create mode 100644 include/Nazara/Shader/ShaderLangSourceLocation.hpp create mode 100644 include/Nazara/Shader/ShaderLangSourceLocation.inl diff --git a/include/Nazara/Shader/Ast/AstCompare.hpp b/include/Nazara/Shader/Ast/AstCompare.hpp index 58613d77b..74fef5a08 100644 --- a/include/Nazara/Shader/Ast/AstCompare.hpp +++ b/include/Nazara/Shader/Ast/AstCompare.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -23,12 +24,15 @@ namespace Nz::ShaderAst template bool Compare(const T& lhs, const T& rhs); template bool Compare(const std::array& lhs, const std::array& rhs); + template bool Compare(const std::shared_ptr& lhs, const std::shared_ptr& rhs); template bool Compare(const std::vector& lhs, const std::vector& rhs); template bool Compare(const std::unique_ptr& lhs, const std::unique_ptr& rhs); template bool Compare(const ExpressionValue& lhs, const ExpressionValue& rhs); + inline bool Compare(const AccessIdentifierExpression::Identifier& lhs, const AccessIdentifierExpression::Identifier& rhs); inline bool Compare(const BranchStatement::ConditionalStatement& lhs, const BranchStatement::ConditionalStatement& rhs); inline bool Compare(const DeclareExternalStatement::ExternalVar& lhs, const DeclareExternalStatement::ExternalVar& rhs); inline bool Compare(const DeclareFunctionStatement::Parameter& lhs, const DeclareFunctionStatement::Parameter& rhs); + inline bool Compare(const ShaderLang::SourceLocation& lhs, const ShaderLang::SourceLocation& rhs); inline bool Compare(const StructDescription& lhs, const StructDescription& rhs); inline bool Compare(const StructDescription::StructMember& lhs, const StructDescription::StructMember& rhs); diff --git a/include/Nazara/Shader/Ast/AstCompare.inl b/include/Nazara/Shader/Ast/AstCompare.inl index bcb46a28e..517853a3d 100644 --- a/include/Nazara/Shader/Ast/AstCompare.inl +++ b/include/Nazara/Shader/Ast/AstCompare.inl @@ -13,6 +13,9 @@ namespace Nz::ShaderAst if (lhs.GetType() != rhs.GetType()) return false; + if (!Compare(lhs.sourceLocation, rhs.sourceLocation)) + return false; + switch (lhs.GetType()) { case NodeType::None: break; @@ -70,6 +73,9 @@ namespace Nz::ShaderAst if (lhs.GetType() != rhs.GetType()) return false; + if (!Compare(lhs.sourceLocation, rhs.sourceLocation)) + return false; + switch (lhs.GetType()) { case NodeType::None: break; @@ -101,6 +107,17 @@ namespace Nz::ShaderAst return true; } + template + bool Compare(const std::shared_ptr& lhs, const std::shared_ptr& rhs) + { + if (lhs == nullptr) + return rhs == nullptr; + else if (rhs == nullptr) + return false; + + return Compare(*lhs, *rhs); + } + template bool Compare(const std::vector& lhs, const std::vector& rhs) { @@ -153,6 +170,17 @@ namespace Nz::ShaderAst return true; } + bool Compare(const AccessIdentifierExpression::Identifier& lhs, const AccessIdentifierExpression::Identifier& rhs) + { + if (!Compare(lhs.identifier, rhs.identifier)) + return false; + + if (!Compare(lhs.sourceLocation, rhs.sourceLocation)) + return false; + + return true; + } + inline bool Compare(const BranchStatement::ConditionalStatement& lhs, const BranchStatement::ConditionalStatement& rhs) { if (!Compare(lhs.condition, rhs.condition)) @@ -178,6 +206,9 @@ namespace Nz::ShaderAst if (!Compare(lhs.type, rhs.type)) return false; + if (!Compare(lhs.sourceLocation, rhs.sourceLocation)) + return false; + return true; } @@ -189,6 +220,29 @@ namespace Nz::ShaderAst if (!Compare(lhs.type, rhs.type)) return false; + if (!Compare(lhs.sourceLocation, rhs.sourceLocation)) + return false; + + return true; + } + + bool Compare(const ShaderLang::SourceLocation& lhs, const ShaderLang::SourceLocation& rhs) + { + if (!Compare(lhs.endColumn, rhs.endColumn)) + return false; + + if (!Compare(lhs.endLine, rhs.endLine)) + return false; + + if (!Compare(lhs.startColumn, rhs.startColumn)) + return false; + + if (!Compare(lhs.startLine, rhs.startLine)) + return false; + + if (!Compare(lhs.file, rhs.file)) + return false; + return true; } @@ -223,6 +277,9 @@ namespace Nz::ShaderAst if (!Compare(lhs.type, rhs.type)) return false; + if (!Compare(lhs.sourceLocation, rhs.sourceLocation)) + return false; + return true; } diff --git a/include/Nazara/Shader/Ast/AstSerializer.hpp b/include/Nazara/Shader/Ast/AstSerializer.hpp index dba8f483c..15dee98a7 100644 --- a/include/Nazara/Shader/Ast/AstSerializer.hpp +++ b/include/Nazara/Shader/Ast/AstSerializer.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include namespace Nz::ShaderAst @@ -43,7 +44,6 @@ namespace Nz::ShaderAst void Serialize(TypeExpression& node); void Serialize(VariableValueExpression& node); void Serialize(UnaryExpression& node); - void SerializeExpressionCommon(Expression& expr); void Serialize(BranchStatement& node); void Serialize(ConditionalStatement& node); @@ -65,6 +65,9 @@ namespace Nz::ShaderAst void Serialize(ScopedStatement& node); void Serialize(WhileStatement& node); + void SerializeExpressionCommon(Expression& expr); + void SerializeNodeCommon(ShaderAst::Node& node); + protected: template void Container(T& container); template void Enum(T& enumVal); @@ -75,11 +78,14 @@ namespace Nz::ShaderAst virtual bool IsWriting() const = 0; - virtual void SerializeModule(ModulePtr& module) = 0; - virtual void Node(ExpressionPtr& node) = 0; virtual void Node(StatementPtr& node) = 0; + virtual void SerializeModule(ModulePtr& module) = 0; + virtual void SharedString(std::shared_ptr& val) = 0; + + inline void SourceLoc(ShaderLang::SourceLocation& sourceLoc); + virtual void Type(ExpressionType& type) = 0; virtual void Value(bool& val) = 0; @@ -110,11 +116,11 @@ namespace Nz::ShaderAst private: using AstSerializerBase::Serialize; - void SerializeModule(ModulePtr& module) override; - bool IsWriting() const override; void Node(ExpressionPtr& node) override; void Node(StatementPtr& node) override; + void SerializeModule(ModulePtr& module) override; + void SharedString(std::shared_ptr& val) override; void Type(ExpressionType& type) override; void Value(bool& val) override; void Value(float& val) override; @@ -131,6 +137,7 @@ namespace Nz::ShaderAst void Value(UInt32& val) override; void Value(UInt64& val) override; + std::unordered_map m_stringIndices; ByteStream& m_stream; }; @@ -145,11 +152,11 @@ namespace Nz::ShaderAst private: using AstSerializerBase::Serialize; - void SerializeModule(ModulePtr& module) override; - bool IsWriting() const override; void Node(ExpressionPtr& node) override; void Node(StatementPtr& node) override; + void SerializeModule(ModulePtr& module) override; + void SharedString(std::shared_ptr& val) override; void Type(ExpressionType& type) override; void Value(bool& val) override; void Value(float& val) override; @@ -166,6 +173,7 @@ namespace Nz::ShaderAst void Value(UInt32& val) override; void Value(UInt64& val) override; + std::vector> m_strings; ByteStream& m_stream; }; diff --git a/include/Nazara/Shader/Ast/AstSerializer.inl b/include/Nazara/Shader/Ast/AstSerializer.inl index e0e60d04e..655cce786 100644 --- a/include/Nazara/Shader/Ast/AstSerializer.inl +++ b/include/Nazara/Shader/Ast/AstSerializer.inl @@ -166,6 +166,15 @@ namespace Nz::ShaderAst } } + inline void AstSerializerBase::SourceLoc(ShaderLang::SourceLocation& sourceLoc) + { + SharedString(sourceLoc.file); + Value(sourceLoc.endColumn); + Value(sourceLoc.endLine); + Value(sourceLoc.startColumn); + Value(sourceLoc.startLine); + } + inline void AstSerializerBase::SizeT(std::size_t& val) { bool isWriting = IsWriting(); diff --git a/include/Nazara/Shader/Ast/ExpressionType.hpp b/include/Nazara/Shader/Ast/ExpressionType.hpp index e699c3435..499da2578 100644 --- a/include/Nazara/Shader/Ast/ExpressionType.hpp +++ b/include/Nazara/Shader/Ast/ExpressionType.hpp @@ -8,6 +8,7 @@ #define NAZARA_SHADER_AST_EXPRESSIONTYPE_HPP #include +#include #include #include #include @@ -166,6 +167,7 @@ namespace Nz::ShaderAst ExpressionValue locationIndex; ExpressionValue type; std::string name; + ShaderLang::SourceLocation sourceLocation; }; ExpressionValue layout; diff --git a/include/Nazara/Shader/Ast/Nodes.hpp b/include/Nazara/Shader/Ast/Nodes.hpp index 2a6ca6c2d..d5119ccae 100644 --- a/include/Nazara/Shader/Ast/Nodes.hpp +++ b/include/Nazara/Shader/Ast/Nodes.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -41,6 +42,8 @@ namespace Nz::ShaderAst Node& operator=(const Node&) = delete; Node& operator=(Node&&) noexcept = default; + + ShaderLang::SourceLocation sourceLocation; }; // Expressions @@ -69,7 +72,13 @@ namespace Nz::ShaderAst NodeType GetType() const override; void Visit(AstExpressionVisitor& visitor) override; - std::vector identifiers; + struct Identifier + { + std::string identifier; + ShaderLang::SourceLocation sourceLocation; + }; + + std::vector identifiers; ExpressionPtr expr; }; @@ -317,6 +326,7 @@ namespace Nz::ShaderAst ExpressionValue bindingIndex; ExpressionValue bindingSet; ExpressionValue type; + ShaderLang::SourceLocation sourceLocation; }; std::vector externalVars; @@ -330,9 +340,10 @@ namespace Nz::ShaderAst struct Parameter { - ExpressionValue type; std::optional varIndex; std::string name; + ExpressionValue type; + ShaderLang::SourceLocation sourceLocation; }; std::optional funcIndex; diff --git a/include/Nazara/Shader/ShaderBuilder.inl b/include/Nazara/Shader/ShaderBuilder.inl index 48841a53d..b7116e353 100644 --- a/include/Nazara/Shader/ShaderBuilder.inl +++ b/include/Nazara/Shader/ShaderBuilder.inl @@ -12,7 +12,12 @@ namespace Nz::ShaderBuilder { auto accessMemberNode = std::make_unique(); accessMemberNode->expr = std::move(expr); - accessMemberNode->identifiers = std::move(memberIdentifiers); + accessMemberNode->identifiers.reserve(memberIdentifiers.size()); + for (std::string& identifier : memberIdentifiers) + { + auto& identifierEntry = accessMemberNode->identifiers.emplace_back(); + identifierEntry.identifier = std::move(identifier); + } return accessMemberNode; } diff --git a/include/Nazara/Shader/ShaderLangErrors.hpp b/include/Nazara/Shader/ShaderLangErrors.hpp index 4c67287aa..6a0c81340 100644 --- a/include/Nazara/Shader/ShaderLangErrors.hpp +++ b/include/Nazara/Shader/ShaderLangErrors.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -18,22 +19,6 @@ namespace Nz::ShaderLang { - struct SourceLocation - { - inline SourceLocation(); - inline SourceLocation(unsigned int line, unsigned int column, std::shared_ptr file); - inline SourceLocation(unsigned int line, unsigned int startColumn, unsigned int endColumn, std::shared_ptr file); - inline SourceLocation(unsigned int startLine, unsigned int endLine, unsigned int startColumn, unsigned int endColumn, std::shared_ptr file); - - inline bool IsValid() const; - - std::shared_ptr file; //< Since the same file will be used for every node, prevent holding X time the same path - unsigned int endColumn; - unsigned int endLine; - unsigned int startColumn; - unsigned int startLine; - }; - enum class ErrorCategory { Ast, diff --git a/include/Nazara/Shader/ShaderLangErrors.inl b/include/Nazara/Shader/ShaderLangErrors.inl index 33bcdbeb8..a1eb39bb6 100644 --- a/include/Nazara/Shader/ShaderLangErrors.inl +++ b/include/Nazara/Shader/ShaderLangErrors.inl @@ -7,46 +7,6 @@ namespace Nz::ShaderLang { - inline SourceLocation::SourceLocation() : - endColumn(0), - endLine(0), - startColumn(0), - startLine(0) - { - } - - inline SourceLocation::SourceLocation(unsigned int Line, unsigned int Column, std::shared_ptr File) : - file(std::move(File)), - endColumn(Column), - endLine(Line), - startColumn(Column), - startLine(Line) - { - } - - inline SourceLocation::SourceLocation(unsigned int Line, unsigned int StartColumn, unsigned int EndColumn, std::shared_ptr File) : - file(std::move(File)), - endColumn(EndColumn), - endLine(Line), - startColumn(StartColumn), - startLine(Line) - { - } - - inline SourceLocation::SourceLocation(unsigned int StartLine, unsigned int EndLine, unsigned int StartColumn, unsigned int EndColumn, std::shared_ptr File) : - file(std::move(File)), - endColumn(EndColumn), - endLine(EndLine), - startColumn(StartColumn), - startLine(StartLine) - { - } - - inline bool SourceLocation::IsValid() const - { - return startLine != 0 && endLine != 0 && endColumn != 0 && startColumn != 0; - } - inline Error::Error(SourceLocation sourceLocation, ErrorCategory errorCategory, unsigned int errorType) noexcept : m_errorCategory(errorCategory), m_sourceLocation(std::move(sourceLocation)), diff --git a/include/Nazara/Shader/ShaderLangSourceLocation.hpp b/include/Nazara/Shader/ShaderLangSourceLocation.hpp new file mode 100644 index 000000000..5af6768fa --- /dev/null +++ b/include/Nazara/Shader/ShaderLangSourceLocation.hpp @@ -0,0 +1,36 @@ +// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Shader module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_SHADER_SHADERLANGSOURCELOCATION_HPP +#define NAZARA_SHADER_SHADERLANGSOURCELOCATION_HPP + +#include +#include +#include +#include + +namespace Nz::ShaderLang +{ + struct SourceLocation + { + inline SourceLocation(); + inline SourceLocation(unsigned int line, unsigned int column, std::shared_ptr file); + inline SourceLocation(unsigned int line, unsigned int startColumn, unsigned int endColumn, std::shared_ptr file); + inline SourceLocation(unsigned int startLine, unsigned int endLine, unsigned int startColumn, unsigned int endColumn, std::shared_ptr file); + + inline bool IsValid() const; + + std::shared_ptr file; //< Since the same file will be used for every node, prevent holding X time the same path + UInt32 endColumn; + UInt32 endLine; + UInt32 startColumn; + UInt32 startLine; + }; +} + +#include + +#endif // NAZARA_SHADER_SHADERLANGSOURCELOCATION_HPP diff --git a/include/Nazara/Shader/ShaderLangSourceLocation.inl b/include/Nazara/Shader/ShaderLangSourceLocation.inl new file mode 100644 index 000000000..4e3c3cc54 --- /dev/null +++ b/include/Nazara/Shader/ShaderLangSourceLocation.inl @@ -0,0 +1,51 @@ +// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Shader module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz::ShaderLang +{ + inline SourceLocation::SourceLocation() : + endColumn(0), + endLine(0), + startColumn(0), + startLine(0) + { + } + + inline SourceLocation::SourceLocation(unsigned int Line, unsigned int Column, std::shared_ptr File) : + file(std::move(File)), + endColumn(Column), + endLine(Line), + startColumn(Column), + startLine(Line) + { + } + + inline SourceLocation::SourceLocation(unsigned int Line, unsigned int StartColumn, unsigned int EndColumn, std::shared_ptr File) : + file(std::move(File)), + endColumn(EndColumn), + endLine(Line), + startColumn(StartColumn), + startLine(Line) + { + } + + inline SourceLocation::SourceLocation(unsigned int StartLine, unsigned int EndLine, unsigned int StartColumn, unsigned int EndColumn, std::shared_ptr File) : + file(std::move(File)), + endColumn(EndColumn), + endLine(EndLine), + startColumn(StartColumn), + startLine(StartLine) + { + } + + inline bool SourceLocation::IsValid() const + { + return startLine != 0 && endLine != 0 && endColumn != 0 && startColumn != 0; + } +} + +#include diff --git a/src/Nazara/Shader/Ast/AstSerializer.cpp b/src/Nazara/Shader/Ast/AstSerializer.cpp index a6e553966..cc01b2197 100644 --- a/src/Nazara/Shader/Ast/AstSerializer.cpp +++ b/src/Nazara/Shader/Ast/AstSerializer.cpp @@ -26,12 +26,14 @@ namespace Nz::ShaderAst #define NAZARA_SHADERAST_EXPRESSION(Node) void Visit(Node& node) override \ { \ m_serializer.Serialize(node); \ + m_serializer.SerializeNodeCommon(node); \ m_serializer.SerializeExpressionCommon(node); \ } #define NAZARA_SHADERAST_STATEMENT(Node) void Visit(Node& node) override \ { \ m_serializer.Serialize(node); \ + m_serializer.SerializeNodeCommon(node); \ } #include @@ -45,8 +47,11 @@ namespace Nz::ShaderAst Node(node.expr); Container(node.identifiers); - for (std::string& identifier : node.identifiers) - Value(identifier); + for (auto& identifier : node.identifiers) + { + Value(identifier.identifier); + SourceLoc(identifier.sourceLocation); + } } void AstSerializerBase::Serialize(AccessIndexExpression& node) @@ -204,11 +209,6 @@ namespace Nz::ShaderAst Node(node.expression); } - void AstSerializerBase::SerializeExpressionCommon(Expression& expr) - { - OptType(expr.cachedExpressionType); - } - void AstSerializerBase::Serialize(BranchStatement& node) { Container(node.condStatements); @@ -235,6 +235,14 @@ namespace Nz::ShaderAst Node(node.expression); } + void AstSerializerBase::Serialize(DeclareConstStatement& node) + { + OptVal(node.constIndex); + Value(node.name); + ExprValue(node.type); + Node(node.expression); + } + void AstSerializerBase::Serialize(DeclareExternalStatement& node) { ExprValue(node.bindingSet); @@ -247,17 +255,10 @@ namespace Nz::ShaderAst ExprValue(extVar.type); ExprValue(extVar.bindingIndex); ExprValue(extVar.bindingSet); + SourceLoc(extVar.sourceLocation); } } - void AstSerializerBase::Serialize(DeclareConstStatement& node) - { - OptVal(node.constIndex); - Value(node.name); - ExprValue(node.type); - Node(node.expression); - } - void AstSerializerBase::Serialize(DeclareFunctionStatement& node) { Value(node.name); @@ -274,6 +275,7 @@ namespace Nz::ShaderAst Value(parameter.name); ExprValue(parameter.type); OptVal(parameter.varIndex); + SourceLoc(parameter.sourceLocation); } Container(node.statements); @@ -305,6 +307,7 @@ namespace Nz::ShaderAst ExprValue(member.builtin); ExprValue(member.cond); ExprValue(member.locationIndex); + SourceLoc(member.sourceLocation); } } @@ -378,6 +381,16 @@ namespace Nz::ShaderAst Node(node.body); } + void AstSerializerBase::SerializeExpressionCommon(Expression& expr) + { + OptType(expr.cachedExpressionType); + } + + void AstSerializerBase::SerializeNodeCommon(ShaderAst::Node& node) + { + SourceLoc(node.sourceLocation); + } + void ShaderAstSerializer::Serialize(ModulePtr& module) { m_stream << s_shaderAstMagicNumber << s_shaderAstCurrentVersion; @@ -387,23 +400,6 @@ namespace Nz::ShaderAst m_stream.FlushBits(); } - void ShaderAstSerializer::SerializeModule(ModulePtr& module) - { - m_stream << module->metadata->moduleName; - m_stream << module->metadata->moduleId; - m_stream << module->metadata->shaderLangVersion; - - Container(module->importedModules); - for (auto& importedModule : module->importedModules) - { - Value(importedModule.identifier); - SerializeModule(importedModule.module); - } - - ShaderSerializerVisitor visitor(*this); - module->rootNode->Visit(visitor); - } - bool ShaderAstSerializer::IsWriting() const { return true; @@ -432,6 +428,44 @@ namespace Nz::ShaderAst node->Visit(visitor); } } + + void ShaderAstSerializer::SerializeModule(ModulePtr& module) + { + m_stream << module->metadata->moduleName; + m_stream << module->metadata->moduleId; + m_stream << module->metadata->shaderLangVersion; + + Container(module->importedModules); + for (auto& importedModule : module->importedModules) + { + Value(importedModule.identifier); + SerializeModule(importedModule.module); + } + + ShaderSerializerVisitor visitor(*this); + module->rootNode->Visit(visitor); + } + + void ShaderAstSerializer::SharedString(std::shared_ptr& val) + { + bool hasValue = (val != nullptr); + Value(hasValue); + + if (hasValue) + { + auto it = m_stringIndices.find(*val); + bool newString = (it == m_stringIndices.end()); + Value(newString); + + if (newString) + { + Value(const_cast(*val)); //< won't be used for writing + m_stringIndices.emplace(*val, m_stringIndices.size()); + } + else + Value(it->second); //< string index + } + } void ShaderAstSerializer::Type(ExpressionType& type) { @@ -606,29 +640,6 @@ namespace Nz::ShaderAst return module; } - void ShaderAstUnserializer::SerializeModule(ModulePtr& module) - { - std::shared_ptr metadata = std::make_shared(); - m_stream >> metadata->moduleName; - m_stream >> metadata->moduleId; - m_stream >> metadata->shaderLangVersion; - - std::vector importedModules; - Container(importedModules); - for (auto& importedModule : importedModules) - { - Value(const_cast(importedModule.identifier)); //< not used for writing - SerializeModule(importedModule.module); - } - - MultiStatementPtr rootNode = std::make_unique(); - - ShaderSerializerVisitor visitor(*this); - rootNode->Visit(visitor); - - module = std::make_shared(std::move(metadata), std::move(rootNode), std::move(importedModules)); - } - bool ShaderAstUnserializer::IsWriting() const { return false; @@ -686,6 +697,58 @@ namespace Nz::ShaderAst } } + void ShaderAstUnserializer::SerializeModule(ModulePtr& module) + { + std::shared_ptr metadata = std::make_shared(); + m_stream >> metadata->moduleName; + m_stream >> metadata->moduleId; + m_stream >> metadata->shaderLangVersion; + + std::vector importedModules; + Container(importedModules); + for (auto& importedModule : importedModules) + { + Value(const_cast(importedModule.identifier)); //< not used for writing + SerializeModule(importedModule.module); + } + + MultiStatementPtr rootNode = std::make_unique(); + + ShaderSerializerVisitor visitor(*this); + rootNode->Visit(visitor); + + module = std::make_shared(std::move(metadata), std::move(rootNode), std::move(importedModules)); + } + + void ShaderAstUnserializer::SharedString(std::shared_ptr& val) + { + bool hasValue; + Value(hasValue); + + if (hasValue) + { + bool newString; + Value(newString); + + if (newString) + { + std::string newStr; + Value(newStr); + + val = std::make_shared(std::move(newStr)); + m_strings.emplace_back(val); + } + else + { + UInt32 strIndex; + Value(strIndex); + + assert(strIndex < m_strings.size()); + val = m_strings[strIndex]; + } + } + } + void ShaderAstUnserializer::Type(ExpressionType& type) { UInt8 typeIndex; diff --git a/src/Nazara/Shader/Ast/SanitizeVisitor.cpp b/src/Nazara/Shader/Ast/SanitizeVisitor.cpp index b00f7dd3d..764cbe3fe 100644 --- a/src/Nazara/Shader/Ast/SanitizeVisitor.cpp +++ b/src/Nazara/Shader/Ast/SanitizeVisitor.cpp @@ -306,16 +306,16 @@ namespace Nz::ShaderAst std::size_t moduleIndex = m_context->moduleIndices.Retrieve(identifierData->index); const auto& env = *m_context->modules[moduleIndex].environment; - identifierData = FindIdentifier(env, node.identifiers.front()); + identifierData = FindIdentifier(env, node.identifiers.front().identifier); if (identifierData) return HandleIdentifier(identifierData); } } ExpressionPtr indexedExpr = CloneExpression(node.expr); - for (const std::string& identifier : node.identifiers) + for (const auto& identifierEntry : node.identifiers) { - if (identifier.empty()) + if (identifierEntry.identifier.empty()) throw AstError{ "empty identifier" }; const ExpressionType* exprType = GetExpressionType(*indexedExpr); @@ -326,12 +326,12 @@ namespace Nz::ShaderAst // TODO: Add proper support for methods if (IsSamplerType(resolvedType)) { - if (identifier == "Sample") + if (identifierEntry.identifier == "Sample") { // TODO: Add a MethodExpression? auto identifierExpr = std::make_unique(); identifierExpr->expr = std::move(indexedExpr); - identifierExpr->identifiers.push_back(identifier); + identifierExpr->identifiers.emplace_back().identifier = identifierEntry.identifier; MethodType methodType; methodType.methodIndex = 0; //< FIXME @@ -342,7 +342,7 @@ namespace Nz::ShaderAst indexedExpr = std::move(identifierExpr); } else - throw AstError{ "type has no method " + identifier }; + throw AstError{ "type has no method " + identifierEntry.identifier }; } else if (IsStructType(resolvedType)) { @@ -367,7 +367,7 @@ namespace Nz::ShaderAst continue; } - if (field.name == identifier) + if (field.name == identifierEntry.identifier) { fieldPtr = &field; break; @@ -377,7 +377,7 @@ namespace Nz::ShaderAst } if (!fieldPtr) - throw AstError{ "unknown field " + identifier }; + throw AstError{ "unknown field " + identifierEntry.identifier }; if (m_context->options.useIdentifierAccessesForStructs) { @@ -394,8 +394,9 @@ namespace Nz::ShaderAst else accessIdentifierPtr = static_cast(indexedExpr.get()); - accessIdentifierPtr->identifiers.push_back(fieldPtr->name); accessIdentifierPtr->cachedExpressionType = ResolveTypeExpr(fieldPtr->type); + + accessIdentifierPtr->identifiers.emplace_back().identifier = fieldPtr->name; } else { @@ -411,7 +412,7 @@ namespace Nz::ShaderAst else if (IsPrimitiveType(resolvedType) || IsVectorType(resolvedType)) { // Swizzle expression - std::size_t swizzleComponentCount = identifier.size(); + std::size_t swizzleComponentCount = identifierEntry.identifier.size(); if (swizzleComponentCount > 4) throw AstError{ "cannot swizzle more than four elements" }; @@ -419,7 +420,7 @@ namespace Nz::ShaderAst { for (std::size_t j = 0; j < swizzleComponentCount; ++j) { - if (ToSwizzleIndex(identifier[j]) != 0) + if (ToSwizzleIndex(identifierEntry.identifier[j]) != 0) throw AstError{ "invalid swizzle" }; //throw ShaderLang::CompilerInvalidSwizzleError{}; } @@ -452,7 +453,7 @@ namespace Nz::ShaderAst swizzle->componentCount = swizzleComponentCount; for (std::size_t j = 0; j < swizzleComponentCount; ++j) - swizzle->components[j] = ToSwizzleIndex(identifier[j]); + swizzle->components[j] = ToSwizzleIndex(identifierEntry.identifier[j]); Validate(*swizzle); diff --git a/src/Nazara/Shader/GlslWriter.cpp b/src/Nazara/Shader/GlslWriter.cpp index 890ab1519..64353d582 100644 --- a/src/Nazara/Shader/GlslWriter.cpp +++ b/src/Nazara/Shader/GlslWriter.cpp @@ -833,8 +833,8 @@ namespace Nz assert(exprType); assert(IsStructType(*exprType)); - for (const std::string& identifier : node.identifiers) - Append(".", identifier); + for (const auto& identifierEntry : node.identifiers) + Append(".", identifierEntry.identifier); } void GlslWriter::Visit(ShaderAst::AccessIndexExpression& node) diff --git a/src/Nazara/Shader/LangWriter.cpp b/src/Nazara/Shader/LangWriter.cpp index b68fd1f37..22d30bde3 100644 --- a/src/Nazara/Shader/LangWriter.cpp +++ b/src/Nazara/Shader/LangWriter.cpp @@ -736,8 +736,8 @@ namespace Nz { Visit(node.expr, true); - for (const std::string& identifier : node.identifiers) - Append(".", identifier); + for (const auto& identifierEntry : node.identifiers) + Append(".", identifierEntry.identifier); } void LangWriter::Visit(ShaderAst::AccessIndexExpression& node)