Shader: Add module resolver + use modules for engine shaders

This commit is contained in:
Jérôme Leclercq
2022-03-10 21:00:10 +01:00
parent 98bd04e35a
commit db0c1e6e8c
30 changed files with 737 additions and 106 deletions

View File

@@ -1398,7 +1398,7 @@ namespace Nz::ShaderAst
StatementPtr SanitizeVisitor::Clone(ImportStatement& node)
{
if (!m_context->options.moduleCallback)
if (!m_context->options.moduleResolver)
return static_unique_pointer_cast<ImportStatement>(AstCloner::Clone(node));
auto ModulePathAsString = [&]() -> std::string
@@ -1419,7 +1419,7 @@ namespace Nz::ShaderAst
return ss.str();
};
ModulePtr targetModule = m_context->options.moduleCallback(node.modulePath);
ModulePtr targetModule = m_context->options.moduleResolver->Resolve(node.modulePath);
if (!targetModule)
throw AstError{ "module " + ModulePathAsString() + " not found" };
@@ -1506,16 +1506,20 @@ namespace Nz::ShaderAst
AstExportVisitor exportVisitor;
exportVisitor.Visit(*m_context->currentModule->importedModules[moduleIndex].module->rootNode, callbacks);
if (aliasStatements.empty() || m_context->options.removeAliases)
if (aliasStatements.empty())
return ShaderBuilder::NoOp();
// Register module and aliases
// Register aliases
for (auto& aliasPtr : aliasStatements)
Validate(*aliasPtr);
if (m_context->options.removeAliases)
return ShaderBuilder::NoOp();
// Generate alias statements
MultiStatementPtr aliasBlock = std::make_unique<MultiStatement>();
for (auto& aliasPtr : aliasStatements)
{
Validate(*aliasPtr);
aliasBlock->statements.push_back(std::move(aliasPtr));
}
return aliasBlock;
}

View File

@@ -0,0 +1,57 @@
// 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 <Nazara/Shader/DirectoryModuleResolver.hpp>
#include <Nazara/Shader/ShaderLangParser.hpp>
#include <filesystem>
#include <Nazara/Shader/Debug.hpp>
namespace Nz
{
ShaderAst::ModulePtr DirectoryModuleResolver::Resolve(const std::vector<std::string>& modulePath)
{
if (modulePath.empty())
return {};
std::string fullPath;
for (const auto& part : modulePath)
{
if (!fullPath.empty())
fullPath += '/';
fullPath += part;
}
if (auto it = m_knownModules.find(fullPath); it != m_knownModules.end())
return it->second;
VirtualDirectory::Entry entry;
if (!m_searchDirectory->GetEntry(fullPath, &entry))
return {};
ShaderAst::ModulePtr shaderModule;
if (std::holds_alternative<VirtualDirectory::DataPointerEntry>(entry))
{
const auto& content = std::get<VirtualDirectory::DataPointerEntry>(entry);
shaderModule = ShaderLang::Parse(std::string_view(reinterpret_cast<const char*>(content.data), content.size));
}
else if (std::holds_alternative<VirtualDirectory::FileContentEntry>(entry))
{
const auto& content = std::get<VirtualDirectory::FileContentEntry>(entry);
shaderModule = ShaderLang::Parse(std::string_view(reinterpret_cast<const char*>(content.data->data()), content.data->size()));
}
else if (std::holds_alternative<VirtualDirectory::PhysicalFileEntry>(entry))
{
const auto& filePath = std::get<VirtualDirectory::PhysicalFileEntry>(entry);
shaderModule = ShaderLang::ParseFromFile(filePath);
}
if (!shaderModule)
return {};
m_knownModules.emplace(fullPath, shaderModule);
return shaderModule;
}
}

View File

@@ -13,7 +13,6 @@
#include <Nazara/Shader/Ast/AstRecursiveVisitor.hpp>
#include <Nazara/Shader/Ast/AstUtils.hpp>
#include <Nazara/Shader/Ast/EliminateUnusedPassVisitor.hpp>
#include <Nazara/Shader/Ast/SanitizeVisitor.hpp>
#include <optional>
#include <set>
#include <stdexcept>
@@ -173,7 +172,11 @@ namespace Nz
const ShaderAst::Module* targetModule;
if (!states.sanitized)
{
sanitizedModule = Sanitize(module, states.optionValues);
ShaderAst::SanitizeVisitor::Options options = GetSanitizeOptions();
options.optionValues = states.optionValues;
options.moduleResolver = states.shaderModuleResolver;
sanitizedModule = ShaderAst::Sanitize(module, options);
targetModule = sanitizedModule.get();
}
else
@@ -227,11 +230,10 @@ namespace Nz
return s_flipYUniformName;
}
ShaderAst::ModulePtr GlslWriter::Sanitize(const ShaderAst::Module& module, std::unordered_map<UInt32, ShaderAst::ConstantValue> optionValues, std::string* error)
ShaderAst::SanitizeVisitor::Options GlslWriter::GetSanitizeOptions()
{
// Always sanitize for reserved identifiers
ShaderAst::SanitizeVisitor::Options options;
options.optionValues = std::move(optionValues);
options.makeVariableNameUnique = true;
options.reduceLoopsToWhile = true;
options.removeAliases = true;
@@ -246,7 +248,7 @@ namespace Nz
"cross", "dot", "exp", "length", "max", "min", "pow", "texture"
};
return ShaderAst::Sanitize(module, options, error);
return options;
}
void GlslWriter::Append(const ShaderAst::AliasType& /*aliasType*/)

View File

@@ -0,0 +1,11 @@
// 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 <Nazara/Shader/ShaderModuleResolver.hpp>
#include <Nazara/Shader/Debug.hpp>
namespace Nz
{
ShaderModuleResolver::~ShaderModuleResolver() = default;
}

View File

@@ -503,10 +503,12 @@ namespace Nz
if (!states.sanitized)
{
ShaderAst::SanitizeVisitor::Options options;
options.moduleResolver = states.shaderModuleResolver;
options.optionValues = states.optionValues;
options.reduceLoopsToWhile = true;
options.removeAliases = true;
options.removeCompoundAssignments = true;
options.removeConstDeclaration = true;
options.removeMatrixCast = true;
options.removeOptionDeclaration = true;
options.splitMultipleBranches = true;