Add storing shader asset includes paths in compact format for portability

This commit is contained in:
Wojtek Figat
2023-11-04 15:26:18 +01:00
parent 50bcbf980e
commit 19752e4f3b
4 changed files with 159 additions and 96 deletions

View File

@@ -33,7 +33,6 @@
#include "Editor/Editor.h"
#include "Editor/ProjectInfo.h"
#endif
#if COMPILE_WITH_D3D_SHADER_COMPILER
#include "DirectX/ShaderCompilerD3D.h"
#endif
@@ -55,6 +54,49 @@ namespace ShadersCompilationImpl
CriticalSection Locker;
Array<ShaderCompiler*> Compilers;
Array<ShaderCompiler*> ReadyCompilers;
#if USE_EDITOR
const ProjectInfo* FindProjectByName(const ProjectInfo* project, HashSet<const ProjectInfo*>& projects, const StringView& projectName)
{
if (!project || projects.Contains(project))
return nullptr;
projects.Add(project);
// Check the project name
if (project->Name == projectName)
return project;
// Search referenced projects
for (const auto& reference : project->References)
{
const ProjectInfo* result = FindProjectByName(reference.Project, projects, projectName);
if (result)
return result;
}
return nullptr;
}
const ProjectInfo* FindProjectByPath(const ProjectInfo* project, HashSet<const ProjectInfo*>& projects, const StringView& projectPath)
{
if (!project || projects.Contains(project))
return nullptr;
projects.Add(project);
// Search referenced projects (depth first to handle plugin projects first)
for (const auto& reference : project->References)
{
const ProjectInfo* result = FindProjectByPath(reference.Project, projects, projectPath);
if (result)
return result;
}
// Check the project path
if (projectPath.StartsWith(project->ProjectFolderPath))
return project;
return nullptr;
}
#endif
}
using namespace ShadersCompilationImpl;
@@ -361,11 +403,89 @@ void ShadersCompilation::ExtractShaderIncludes(byte* shaderCache, int32 shaderCa
{
String& include = includes.AddOne();
stream.ReadString(&include, 11);
include = ShadersCompilation::ResolveShaderPath(include);
DateTime lastEditTime;
stream.Read(lastEditTime);
}
}
String ShadersCompilation::ResolveShaderPath(StringView path)
{
// Skip to the last root start './' but preserve the leading one
for (int32 i = path.Length() - 2; i >= 2; i--)
{
if (StringUtils::Compare(path.Get() + i, TEXT("./"), 2) == 0)
{
path = path.Substring(i);
break;
}
}
// Find the included file path
String result;
#if USE_EDITOR
if (path.StartsWith(StringView(TEXT("./"), 2)))
{
int32 projectNameEnd = -1;
for (int32 i = 2; i < path.Length(); i++)
{
if (path[i] == '/')
{
projectNameEnd = i;
break;
}
}
if (projectNameEnd == -1)
return String::Empty; // Invalid project path
StringView projectName = path.Substring(2, projectNameEnd - 2);
if (projectName.StartsWith(StringView(TEXT("FlaxPlatforms"))))
{
// Hard-coded redirect to platform-specific includes
result = Globals::StartupFolder / TEXT("Source/Platforms");
}
else
{
HashSet<const ProjectInfo*> projects;
const ProjectInfo* project = FindProjectByName(Editor::Project, projects, StringView(projectName.Get(), projectNameEnd - 2));
if (project)
result = project->ProjectFolderPath / TEXT("/Source/Shaders/");
else
return String::Empty;
}
result /= path.Substring(projectNameEnd + 1);
}
#else
if (path.StartsWith(StringView(TEXT("./Flax/"), 7)))
{
// Engine project relative shader path
result = Globals::StartupFolder / TEXT("Source/Shaders") / path.Substring(6);
}
#endif
else
{
// Absolute shader path
result = path;
}
return result;
}
String ShadersCompilation::CompactShaderPath(StringView path)
{
#if USE_EDITOR
// Try to use file path relative to the project shader sources folder
HashSet<const ProjectInfo*> projects;
const ProjectInfo* project = FindProjectByPath(Editor::Project, projects, path);
if (project)
{
String projectSourcesPath = project->ProjectFolderPath / TEXT("/Source/Shaders/");
if (path.StartsWith(projectSourcesPath))
return String::Format(TEXT("./{}/{}"), project->Name, path.Substring(projectSourcesPath.Length()));
}
#endif
return String(path);
}
#if USE_EDITOR
namespace