Shader: Change module system (no longer based on path)

This commit is contained in:
Jérôme Leclercq
2022-03-13 15:07:43 +01:00
parent 80f9556f8c
commit e40e8eb204
40 changed files with 224 additions and 271 deletions

View File

@@ -221,27 +221,18 @@ namespace Nz
void Graphics::RegisterShaderModules()
{
m_shaderModuleResolver = std::make_shared<DirectoryModuleResolver>();
m_shaderModuleResolver->RegisterModuleFile("Engine/InstanceData", r_instanceDataModule, sizeof(r_instanceDataModule));
m_shaderModuleResolver->RegisterModuleFile("Engine/LightData", r_lightDataModule, sizeof(r_lightDataModule));
m_shaderModuleResolver->RegisterModuleFile("Engine/ViewerData", r_viewerDataModule, sizeof(r_viewerDataModule));
m_shaderModuleResolver = std::make_shared<FilesystemModuleResolver>();
m_shaderModuleResolver->RegisterModule(std::string_view(reinterpret_cast<const char*>(r_instanceDataModule), sizeof(r_instanceDataModule)));
m_shaderModuleResolver->RegisterModule(std::string_view(reinterpret_cast<const char*>(r_lightDataModule), sizeof(r_lightDataModule)));
m_shaderModuleResolver->RegisterModule(std::string_view(reinterpret_cast<const char*>(r_viewerDataModule), sizeof(r_viewerDataModule)));
if (std::filesystem::path shaderPath = "Shaders/Modules"; std::filesystem::is_directory(shaderPath))
m_shaderModuleResolver->RegisterModuleDirectory(shaderPath);
#ifdef NAZARA_DEBUG
// Override embed files with dev files in debug
std::filesystem::path modulePath = "../../src/Nazara/Graphics/Resources/Shaders/Modules";
if (std::filesystem::is_directory(modulePath))
{
for (const auto& dirEntry : std::filesystem::recursive_directory_iterator(modulePath))
{
if (!dirEntry.is_regular_file())
continue;
std::filesystem::path filePath = std::filesystem::relative(dirEntry.path(), modulePath);
filePath.replace_extension();
m_shaderModuleResolver->RegisterModuleFile(filePath.generic_u8string(), dirEntry.path());
}
}
if (std::filesystem::path modulePath = "../../src/Nazara/Graphics/Resources/Shaders/Modules"; std::filesystem::is_directory(modulePath))
m_shaderModuleResolver->RegisterModuleDirectory(modulePath);
#endif
}

View File

@@ -1,6 +1,6 @@
[nzsl_version("1.0")]
module;
module Engine.InstanceData;
[export]
[layout(std140)]
struct InstanceData

View File

@@ -1,5 +1,5 @@
[nzsl_version("1.0")]
module;
module Engine.LightData;
option MaxLightCount: u32 = u32(3); //< FIXME: Fix integral value types

View File

@@ -1,5 +1,5 @@
[nzsl_version("1.0")]
module;
module Engine.ViewerData;
[export]
[layout(std140)]

View File

@@ -1,8 +1,8 @@
[nzsl_version("1.0")]
module;
import Engine/InstanceData;
import Engine/ViewerData;
import Engine.InstanceData;
import Engine.ViewerData;
option HasDiffuseTexture: bool = false;
option HasAlphaTexture: bool = false;

View File

@@ -1,8 +1,8 @@
[nzsl_version("1.0")]
module;
import Engine/InstanceData;
import Engine/ViewerData;
import Engine.InstanceData;
import Engine.ViewerData;
option HasDiffuseTexture: bool = false;
option HasAlphaTexture: bool = false;

View File

@@ -1,9 +1,9 @@
[nzsl_version("1.0")]
module;
import Engine/InstanceData;
import Engine/LightData;
import Engine/ViewerData;
import Engine.InstanceData;
import Engine.LightData;
import Engine.ViewerData;
// Basic material options
option HasDiffuseTexture: bool = false;

View File

@@ -228,7 +228,7 @@ namespace Nz::ShaderAst
StatementPtr AstCloner::Clone(ImportStatement& node)
{
auto clone = std::make_unique<ImportStatement>();
clone->modulePath = node.modulePath;
clone->moduleName = node.moduleName;
return clone;
}

View File

@@ -340,9 +340,7 @@ namespace Nz::ShaderAst
void AstSerializerBase::Serialize(ImportStatement& node)
{
Container(node.modulePath);
for (auto& path : node.modulePath)
Value(path);
Value(node.moduleName);
}
void AstSerializerBase::Serialize(MultiStatement& node)
@@ -385,6 +383,7 @@ namespace Nz::ShaderAst
void ShaderAstSerializer::SerializeModule(ModulePtr& module)
{
m_stream << module->metadata->moduleName;
m_stream << module->metadata->moduleId;
m_stream << module->metadata->shaderLangVersion;
@@ -604,6 +603,7 @@ namespace Nz::ShaderAst
void ShaderAstUnserializer::SerializeModule(ModulePtr& module)
{
std::shared_ptr<Module::Metadata> metadata = std::make_shared<Module::Metadata>();
m_stream >> metadata->moduleName;
m_stream >> metadata->moduleId;
m_stream >> metadata->shaderLangVersion;

View File

@@ -1448,27 +1448,9 @@ namespace Nz::ShaderAst
if (!m_context->options.moduleResolver)
return static_unique_pointer_cast<ImportStatement>(AstCloner::Clone(node));
auto ModulePathAsString = [&]() -> std::string
{
std::ostringstream ss;
bool first = true;
for (const std::string& part : node.modulePath)
{
if (!first)
ss << "/";
ss << part;
first = false;
}
return ss.str();
};
ModulePtr targetModule = m_context->options.moduleResolver->Resolve(node.modulePath);
ModulePtr targetModule = m_context->options.moduleResolver->Resolve(node.moduleName);
if (!targetModule)
throw AstError{ "module " + ModulePathAsString() + " not found" };
throw AstError{ "module " + node.moduleName + " not found" };
std::size_t moduleIndex;
@@ -1500,7 +1482,7 @@ namespace Nz::ShaderAst
std::string error;
sanitizedModule->rootNode = SanitizeInternal(*targetModule->rootNode, &error);
if (!sanitizedModule)
throw AstError{ "module " + ModulePathAsString() + " compilation failed: " + error };
throw AstError{ "module " + node.moduleName + " compilation failed: " + error };
moduleIndex = m_context->modules.size();

View File

@@ -1,56 +0,0 @@
// 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;
ShaderAst::ModulePtr shaderModule;
m_searchDirectory->GetEntry(fullPath, [&](const VirtualDirectory::Entry& entry)
{
if (std::holds_alternative<VirtualDirectory::DataPointerEntry>(entry))
{
const auto& dataContent = std::get<VirtualDirectory::DataPointerEntry>(entry);
shaderModule = ShaderLang::Parse(std::string_view(reinterpret_cast<const char*>(dataContent.data), dataContent.size));
}
else if (std::holds_alternative<VirtualDirectory::FileContentEntry>(entry))
{
const auto& fileContent = std::get<VirtualDirectory::FileContentEntry>(entry);
shaderModule = ShaderLang::Parse(std::string_view(reinterpret_cast<const char*>(fileContent.data.data()), fileContent.data.size()));
}
else if (std::holds_alternative<VirtualDirectory::PhysicalFileEntry>(entry))
{
const auto& physicalEntry = std::get<VirtualDirectory::PhysicalFileEntry>(entry);
shaderModule = ShaderLang::ParseFromFile(physicalEntry.filePath);
}
});
if (!shaderModule)
return {};
m_knownModules.emplace(std::move(fullPath), shaderModule);
return shaderModule;
}
}

View File

@@ -0,0 +1,61 @@
// 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/FilesystemModuleResolver.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/StringExt.hpp>
#include <Nazara/Shader/ShaderLangParser.hpp>
#include <cassert>
#include <Nazara/Shader/Debug.hpp>
namespace Nz
{
void FilesystemModuleResolver::RegisterModule(std::filesystem::path realPath)
{
return RegisterModule(ShaderLang::ParseFromFile(realPath));
}
void FilesystemModuleResolver::RegisterModule(std::string_view moduleSource)
{
return RegisterModule(ShaderLang::Parse(moduleSource));
}
void FilesystemModuleResolver::RegisterModule(ShaderAst::ModulePtr module)
{
assert(module);
std::string moduleName = module->metadata->moduleName;
if (moduleName.empty())
throw std::runtime_error("cannot register anonymous module");
m_modules.emplace(std::move(moduleName), std::move(module));
}
void FilesystemModuleResolver::RegisterModuleDirectory(std::filesystem::path realPath)
{
for (const auto& entry : std::filesystem::recursive_directory_iterator(realPath))
{
if (entry.is_regular_file() && StringEqual(entry.path().extension().generic_u8string(), "nzsl", Nz::CaseIndependent{}))
{
try
{
RegisterModule(entry.path());
}
catch (const std::exception& e)
{
NazaraWarning("failed to register module " + entry.path().generic_u8string() + ": " + e.what());
}
}
}
}
ShaderAst::ModulePtr FilesystemModuleResolver::Resolve(const std::string& moduleName)
{
auto it = m_modules.find(moduleName);
if (it == m_modules.end())
return {};
return it->second;
}
}

View File

@@ -1144,20 +1144,7 @@ namespace Nz
void LangWriter::Visit(ShaderAst::ImportStatement& node)
{
Append("import ");
bool first = true;
for (const std::string& path : node.modulePath)
{
if (!first)
Append("/");
Append(path);
first = false;
}
AppendLine(";");
Append("import ", node.moduleName, ";");
}
void LangWriter::Visit(ShaderAst::IntrinsicExpression& node)

View File

@@ -335,17 +335,12 @@ namespace Nz::ShaderLang
if (!moduleId)
moduleId = Uuid::Generate();
auto module = std::make_shared<ShaderAst::Module>(*moduleVersion, *moduleId);
if (Peek().type == TokenType::Identifier)
if (m_context->module)
{
std::string moduleName = ParseModuleName();
auto module = std::make_shared<ShaderAst::Module>(*moduleVersion, std::move(moduleName), *moduleId);
// Imported module
if (!m_context->module)
throw UnexpectedToken{}; //< "unexpected token before module declaration"
const std::string& identifier = std::get<std::string>(Peek().data);
Consume();
Expect(Advance(), TokenType::OpenCurlyBracket);
m_context->parsingImportedModule = true;
@@ -364,10 +359,17 @@ namespace Nz::ShaderLang
auto& importedModule = m_context->module->importedModules.emplace_back();
importedModule.module = std::move(module);
importedModule.identifier = identifier;
importedModule.identifier = importedModule.module->metadata->moduleName;
}
else
{
std::string moduleName;
if (Peek().type == TokenType::Identifier)
moduleName = ParseModuleName();
auto module = std::make_shared<ShaderAst::Module>(*moduleVersion, std::move(moduleName), *moduleId);
// First declaration
Expect(Advance(), TokenType::Semicolon);
if (m_context->module)
@@ -732,19 +734,11 @@ namespace Nz::ShaderLang
{
Expect(Advance(), TokenType::Import);
std::vector<std::string> modulePath;
modulePath.push_back(ParseIdentifierAsName());
while (Peek().type == TokenType::Divide) //< /
{
Consume();
modulePath.push_back(ParseIdentifierAsName());
}
std::string moduleName = ParseModuleName();
Expect(Advance(), TokenType::Semicolon);
return ShaderBuilder::Import(std::move(modulePath));
return ShaderBuilder::Import(std::move(moduleName));
}
ShaderAst::StatementPtr Parser::ParseOptionDeclaration()
@@ -1371,6 +1365,19 @@ namespace Nz::ShaderLang
return std::get<std::string>(identifierToken.data);
}
std::string Parser::ParseModuleName()
{
std::string moduleName = ParseIdentifierAsName();
while (Peek().type == TokenType::Dot)
{
Consume();
moduleName += '.';
moduleName += ParseIdentifierAsName();
}
return moduleName;
}
ShaderAst::ExpressionPtr Parser::ParseType()
{
// Handle () as no type