Revert "Remove resource system voodoo and make some lines slightly more readable"

This reverts commit 9bc869e1a6.

Revert "Fix race condition"

This reverts commit 883e3ce907.

Revert "Run the GLSL compiler on the worker thread"

This reverts commit da0ff9ab04.
This commit is contained in:
Magnus Norddahl 2025-04-13 17:15:13 +02:00
commit 3823196765
9 changed files with 62 additions and 104 deletions

View file

@ -742,17 +742,11 @@ FileReader FResourceFile::GetEntryReader(uint32_t entry, int readertype, int rea
else
{
FileReader fri;
if (readertype == READER_NEW || !mainThread)
fri.OpenFile(FileName, Entries[entry].Position, Entries[entry].CompressedSize);
else
fri.OpenFilePart(Reader, Entries[entry].Position, Entries[entry].CompressedSize);
if (readertype == READER_NEW || !mainThread) fri.OpenFile(FileName, Entries[entry].Position, Entries[entry].CompressedSize);
else fri.OpenFilePart(Reader, Entries[entry].Position, Entries[entry].CompressedSize);
int flags = DCF_TRANSFEROWNER | DCF_EXCEPTIONS;
if (readertype == READER_CACHED)
flags |= DCF_CACHED;
else if (readerflags & READERFLAG_SEEKABLE)
flags |= DCF_SEEKABLE;
if (readertype == READER_CACHED) flags |= DCF_CACHED;
else if (readerflags & READERFLAG_SEEKABLE) flags |= DCF_SEEKABLE;
OpenDecompressor(fr, fri, Entries[entry].Length, Entries[entry].Method, flags);
}
}

View file

@ -276,7 +276,6 @@ VkVertexFormat *VkRenderPassManager::GetVertexFormat(int index)
VulkanPipelineLayout* VkRenderPassManager::GetPipelineLayout(bool levelmesh, int UserUniformSize)
{
std::unique_lock lock(PipelineLayoutsMutex);
auto &layout = PipelineLayouts[levelmesh][UserUniformSize];
if (layout)
return layout.get();
@ -525,38 +524,34 @@ PipelineData* VkRenderPassSetup::GetSpecializedPipeline(const VkPipelineKey& key
{
// We haven't seen this before. Build it on the worker thread.
SpecializedPipelines[key] = {}; // Mark as seen
struct TaskData
{
VkPipelineKey key;
std::unique_ptr<GraphicsPipelineBuilder> builder;
std::unique_ptr<VulkanPipeline> pipeline;
UniformStructHolder uniforms;
};
auto data = std::make_shared<TaskData>();
data->key = key;
// Compile the GLSL on the main thread (mainly due to the resource system)
UniformStructHolder uniforms;
data->builder = CreatePipeline(key, false, uniforms);
SpecializedPipelines[key].Uniforms = uniforms;
// Schedule the pipeline building on a worker thread
VkPipelineKey k = key;
auto passManager = fb->GetRenderPassManager();
passManager->RunOnWorkerThread([=]() {
auto builder = CreatePipeline(data->key, false, data->uniforms);
cycle_t ct;
ct.ResetAndClock();
data->pipeline = builder->Create(fb->GetDevice());
data->pipeline = data->builder->Create(fb->GetDevice());
ct.Unclock();
const auto duration = ct.TimeMS();
passManager->RunOnMainThread([=]() {
auto& slot = SpecializedPipelines[k];
if (!slot.pipeline)
{
slot.pipeline = std::move(data->pipeline);
slot.Uniforms = std::move(data->uniforms);
}
pipeline_time += duration;
++pipeline_count;
@ -615,7 +610,7 @@ std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreateWithStats(GraphicsPipel
std::unique_ptr<GraphicsPipelineBuilder> VkRenderPassSetup::CreatePipeline(const VkPipelineKey& key, bool isUberShader, UniformStructHolder& Uniforms)
{
VkShaderProgram* program = fb->GetShaderManager()->GetGameShader(key.ShaderKey, isUberShader);
VkShaderProgram* program = fb->GetShaderManager()->Get(key.ShaderKey, isUberShader);
Uniforms.Clear();
Uniforms = program->Uniforms;
@ -728,19 +723,19 @@ void VkRenderPassSetup::PrecompileFragmentShaderLibrary(const VkPipelineKey& key
struct TaskData
{
VkPipelineKey key;
std::unique_ptr<GraphicsPipelineBuilder> builder;
std::unique_ptr<VulkanPipeline> pipeline;
};
auto data = std::make_shared<TaskData>();
data->key = key;
data->builder = CreateFragmentShaderLibrary(key, isUberShader);
auto passManager = fb->GetRenderPassManager();
passManager->RunOnWorkerThread([=]() {
cycle_t ct;
ct.ResetAndClock();
data->pipeline = CreateFragmentShaderLibrary(data->key, isUberShader)->Create(fb->GetDevice());
data->pipeline = data->builder->Create(fb->GetDevice());
ct.Unclock();
const auto duration = ct.TimeMS();
@ -772,7 +767,7 @@ VulkanPipeline* VkRenderPassSetup::GetFragmentShaderLibrary(const VkPipelineKey&
std::unique_ptr<VulkanPipeline> VkRenderPassSetup::LinkPipeline(const VkPipelineKey& key, bool isUberShader, UniformStructHolder& Uniforms)
{
VkShaderProgram* program = fb->GetShaderManager()->GetGameShader(key.ShaderKey, isUberShader);
VkShaderProgram* program = fb->GetShaderManager()->Get(key.ShaderKey, isUberShader);
Uniforms.Clear();
Uniforms = program->Uniforms;
@ -802,7 +797,7 @@ std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreateVertexInputLibrary(int
std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreateVertexShaderLibrary(const VkPipelineKey& key, bool isUberShader)
{
VkShaderProgram* program = fb->GetShaderManager()->GetGameShader(key.ShaderKey, isUberShader);
VkShaderProgram* program = fb->GetShaderManager()->Get(key.ShaderKey, isUberShader);
GraphicsPipelineBuilder builder;
builder.Cache(fb->GetRenderPassManager()->GetCache());
builder.Flags(VK_PIPELINE_CREATE_LIBRARY_BIT_KHR);
@ -817,7 +812,7 @@ std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreateVertexShaderLibrary(con
std::unique_ptr<GraphicsPipelineBuilder> VkRenderPassSetup::CreateFragmentShaderLibrary(const VkPipelineKey& key, bool isUberShader)
{
VkShaderProgram* program = fb->GetShaderManager()->GetGameShader(key.ShaderKey, isUberShader);
VkShaderProgram* program = fb->GetShaderManager()->Get(key.ShaderKey, isUberShader);
auto builder = std::make_unique<GraphicsPipelineBuilder>();
builder->Cache(fb->GetRenderPassManager()->GetCache());
builder->Flags(VK_PIPELINE_CREATE_LIBRARY_BIT_KHR);

View file

@ -11,7 +11,6 @@
#include <map>
#include <thread>
#include <condition_variable>
#include <mutex>
class VulkanRenderDevice;
class ColorBlendAttachmentBuilder;
@ -185,7 +184,6 @@ private:
VulkanRenderDevice* fb = nullptr;
std::map<VkRenderPassKey, std::unique_ptr<VkRenderPassSetup>> RenderPassSetup;
std::mutex PipelineLayoutsMutex;
std::map<int, std::unique_ptr<VulkanPipelineLayout>> PipelineLayouts[2];
std::vector<VkVertexFormat> VertexFormats;

View file

@ -91,15 +91,11 @@ void VkShaderManager::Deinit()
RemoveVkPPShader(PPShaders.back());
}
VkShaderProgram* VkShaderManager::GetGameShader(const VkShaderKey& key, bool isUberShader)
VkShaderProgram* VkShaderManager::Get(const VkShaderKey& key, bool isUberShader)
{
std::unique_lock lock(GameShaders.Mutex);
std::unique_ptr<VkShaderProgram>& program = isUberShader ? GameShaders.Generic[key.GeneralizedShaderKey()] : GameShaders.Specialized[key];
if (program)
return program.get();
program = std::make_unique<VkShaderProgram>();
VkShaderProgram& program = isUberShader ? generic[key.GeneralizedShaderKey()] : specialized[key];
if (program.frag)
return &program;
const char* mainvp = "shaders/scene/vert_main.glsl";
const char* mainfp = "shaders/scene/frag_main.glsl";
@ -131,9 +127,9 @@ VkShaderProgram* VkShaderManager::GetGameShader(const VkShaderKey& key, bool isU
customKey.Layout.AlphaTest = false;
const auto& desc = effectshaders[key.SpecialEffect];
program->vert = LoadVertShader(desc.ShaderName, mainvp, nullptr, desc.defines, key, nullptr, isUberShader);
program.vert = LoadVertShader(desc.ShaderName, mainvp, nullptr, desc.defines, key, nullptr, isUberShader);
if (!key.NoFragmentShader)
program->frag = LoadFragShader(desc.ShaderName, desc.fp1, desc.fp2, desc.fp3, desc.fp4, desc.fp5, desc.defines, key, nullptr, isUberShader);
program.frag = LoadFragShader(desc.ShaderName, desc.fp1, desc.fp2, desc.fp3, desc.fp4, desc.fp5, desc.defines, key, nullptr, isUberShader);
}
else
{
@ -171,9 +167,9 @@ VkShaderProgram* VkShaderManager::GetGameShader(const VkShaderKey& key, bool isU
if (key.EffectState < FIRST_USER_SHADER)
{
const auto& desc = defaultshaders[key.EffectState];
program->vert = LoadVertShader(desc.ShaderName, mainvp, nullptr, desc.Defines, key, nullptr, isUberShader);
program.vert = LoadVertShader(desc.ShaderName, mainvp, nullptr, desc.Defines, key, nullptr, isUberShader);
if (!key.NoFragmentShader)
program->frag = LoadFragShader(desc.ShaderName, mainfp, desc.material_lump, desc.mateffect_lump, desc.lightmodel_lump_shared, desc.lightmodel_lump, desc.Defines, key, nullptr, isUberShader);
program.frag = LoadFragShader(desc.ShaderName, mainfp, desc.material_lump, desc.mateffect_lump, desc.lightmodel_lump_shared, desc.lightmodel_lump, desc.Defines, key, nullptr, isUberShader);
}
else
{
@ -181,14 +177,14 @@ VkShaderProgram* VkShaderManager::GetGameShader(const VkShaderKey& key, bool isU
const FString& name = ExtractFileBase(desc.shader.GetChars());
FString defines = defaultshaders[desc.shaderType].Defines + desc.defines;
program->vert = LoadVertShader(name, mainvp, desc.vertshader.IsEmpty() ? nullptr : desc.vertshader.GetChars(), defines.GetChars(), key, &desc, isUberShader);
program.vert = LoadVertShader(name, mainvp, desc.vertshader.IsEmpty() ? nullptr : desc.vertshader.GetChars(), defines.GetChars(), key, &desc, isUberShader);
if (!key.NoFragmentShader)
program->frag = LoadFragShader(name, mainfp, desc.shader.GetChars(), defaultshaders[desc.shaderType].mateffect_lump, defaultshaders[desc.shaderType].lightmodel_lump_shared, defaultshaders[desc.shaderType].lightmodel_lump, defines.GetChars(), key, &desc, isUberShader);
program.frag = LoadFragShader(name, mainfp, desc.shader.GetChars(), defaultshaders[desc.shaderType].mateffect_lump, defaultshaders[desc.shaderType].lightmodel_lump_shared, defaultshaders[desc.shaderType].lightmodel_lump, defines.GetChars(), key, &desc, isUberShader);
desc.Uniforms.WriteUniforms(program->Uniforms);
desc.Uniforms.WriteUniforms(program.Uniforms);
}
}
return program.get();
return &program;
}
enum class FieldCondition
@ -634,12 +630,12 @@ FString VkShaderManager::GetVersionBlock()
FString VkShaderManager::LoadPublicShaderLump(const char* lumpname)
{
return fb->GetShaderCache()->GetPublicFile(lumpname)->Code;
return fb->GetShaderCache()->GetPublicFile(lumpname).Code;
}
FString VkShaderManager::LoadPrivateShaderLump(const char* lumpname)
{
return fb->GetShaderCache()->GetPrivateFile(lumpname)->Code;
return fb->GetShaderCache()->GetPrivateFile(lumpname).Code;
}
VkPPShader* VkShaderManager::GetVkShader(PPShader* shader)

View file

@ -4,7 +4,6 @@
#include <memory>
#include <list>
#include <map>
#include <mutex>
#include "vectors.h"
#include "matrix.h"
#include "name.h"
@ -169,7 +168,7 @@ public:
void Deinit();
VkShaderProgram* GetGameShader(const VkShaderKey& key, bool isUberShader);
VkShaderProgram* Get(const VkShaderKey& key, bool isUberShader);
bool CompileNextShader() { return true; }
@ -195,12 +194,8 @@ private:
VulkanRenderDevice* fb = nullptr;
struct
{
std::mutex Mutex;
std::map<uint64_t, std::unique_ptr<VkShaderProgram>> Generic;
std::map<VkShaderKey, std::unique_ptr<VkShaderProgram>> Specialized;
} GameShaders;
std::map<uint64_t, VkShaderProgram> generic;
std::map<VkShaderKey, VkShaderProgram> specialized;
std::list<VkPPShader*> PPShaders;

View file

@ -30,8 +30,6 @@ std::vector<uint32_t> VkShaderCache::Compile(ShaderType type, const TArrayView<V
{
// Is this something we already compiled before?
std::unique_lock lock(CacheMutex);
FString checksum = CalcSha1(type, sources);
auto it = CodeCache.find(checksum);
if (it != CodeCache.end())
@ -45,8 +43,8 @@ std::vector<uint32_t> VkShaderCache::Compile(ShaderType type, const TArrayView<V
bool foundChanges = false;
for (const VkCachedInclude& includeinfo : cacheinfo.Includes)
{
const VkCachedShaderLump* lumpinfo = includeinfo.PrivateLump ? GetPrivateFile(includeinfo.LumpName) : GetPublicFile(includeinfo.LumpName);
if (lumpinfo->Checksum != includeinfo.Checksum)
const VkCachedShaderLump& lumpinfo = includeinfo.PrivateLump ? GetPrivateFile(includeinfo.LumpName) : GetPublicFile(includeinfo.LumpName);
if (lumpinfo.Checksum != includeinfo.Checksum)
{
foundChanges = true;
break;
@ -65,8 +63,6 @@ std::vector<uint32_t> VkShaderCache::Compile(ShaderType type, const TArrayView<V
}
}
lock.unlock();
// No match or out of date
// Compile it and store the dependencies:
@ -82,8 +78,6 @@ std::vector<uint32_t> VkShaderCache::Compile(ShaderType type, const TArrayView<V
cachedCompile.Code = compiler.Compile(fb->GetDevice());
cachedCompile.LastUsed = LaunchTime;
lock.lock();
auto& c = CodeCache[checksum];
c = std::move(cachedCompile);
return c.Code;
@ -94,12 +88,12 @@ ShaderIncludeResult VkShaderCache::OnInclude(VkCachedCompile& cachedCompile, FSt
if (depth > 8)
I_Error("Too much include recursion!");
const VkCachedShaderLump* file = system ? GetPrivateFile(headerName) : GetPublicFile(headerName);
const VkCachedShaderLump& file = system ? GetPrivateFile(headerName) : GetPublicFile(headerName);
VkCachedInclude cacheinfo;
cacheinfo.LumpName = headerName;
cacheinfo.PrivateLump = system;
cacheinfo.Checksum = file->Checksum;
cacheinfo.Checksum = file.Checksum;
cachedCompile.Includes.push_back(std::move(cacheinfo));
FString includeguardname;
@ -110,7 +104,7 @@ ShaderIncludeResult VkShaderCache::OnInclude(VkCachedCompile& cachedCompile, FSt
code << "#ifndef " << includeguardname.GetChars() << "\n";
code << "#define " << includeguardname.GetChars() << "\n";
code << "#line 1\n";
code << includeFilter(file->Code.GetChars()) << "\n";
code << includeFilter(file.Code.GetChars()) << "\n";
code << "#endif\n";
return ShaderIncludeResult(headerName.GetChars(), code.GetChars());
@ -135,45 +129,34 @@ FString VkShaderCache::CalcSha1(const FString& str)
return sha1.final();
}
const VkCachedShaderLump* VkShaderCache::GetPublicFile(const FString& lumpname)
const VkCachedShaderLump& VkShaderCache::GetPublicFile(const FString& lumpname)
{
std::unique_lock lock(FileMutex);
auto it = PublicFiles.find(lumpname);
if (it != PublicFiles.end())
return it->second.get();
return it->second;
auto cacheinfo = std::make_unique<VkCachedShaderLump>();
cacheinfo->Code = LoadPublicShaderLump(lumpname.GetChars());
cacheinfo->Checksum = CalcSha1(cacheinfo->Code);
VkCachedShaderLump cacheinfo;
cacheinfo.Code = LoadPublicShaderLump(lumpname.GetChars());
cacheinfo.Checksum = CalcSha1(cacheinfo.Code);
auto& result = PublicFiles[lumpname];
result = std::move(cacheinfo);
return result.get();
return result;
}
const VkCachedShaderLump* VkShaderCache::GetPrivateFile(const FString& lumpname)
const VkCachedShaderLump& VkShaderCache::GetPrivateFile(const FString& lumpname)
{
std::unique_lock lock(FileMutex);
auto it = PrivateFiles.find(lumpname);
if (it != PrivateFiles.end())
return it->second.get();
return it->second;
auto cacheinfo = std::make_unique<VkCachedShaderLump>();
cacheinfo->Code = LoadPrivateShaderLump(lumpname.GetChars());
cacheinfo->Checksum = CalcSha1(cacheinfo->Code);
VkCachedShaderLump cacheinfo;
cacheinfo.Code = LoadPrivateShaderLump(lumpname.GetChars());
cacheinfo.Checksum = CalcSha1(cacheinfo.Code);
auto& result = PrivateFiles[lumpname];
result = std::move(cacheinfo);
return result.get();
}
FString GetStringFromLumpThreadsafe(int lump)
{
auto reader = fileSystem.OpenFileReader(lump, FileSys::READER_NEW, 0);
auto data = reader.Read();
return FString(static_cast<const char*>(data.data()), data.size());
return result;
}
FString VkShaderCache::LoadPublicShaderLump(const char* lumpname)
@ -181,14 +164,14 @@ FString VkShaderCache::LoadPublicShaderLump(const char* lumpname)
int lump = fileSystem.CheckNumForFullName(lumpname, 0);
if (lump == -1) lump = fileSystem.CheckNumForFullName(lumpname);
if (lump == -1) I_Error("Unable to load '%s'", lumpname);
return GetStringFromLumpThreadsafe(lump);
return GetStringFromLump(lump);
}
FString VkShaderCache::LoadPrivateShaderLump(const char* lumpname)
{
int lump = fileSystem.CheckNumForFullName(lumpname, 0);
if (lump == -1) I_Error("Unable to load '%s'", lumpname);
return GetStringFromLumpThreadsafe(lump);
return GetStringFromLump(lump);
}
static uint8_t readUInt8(FileReader& fr) { uint8_t v = 0; fr.Read(&v, 1); return v; }

View file

@ -50,8 +50,8 @@ public:
std::vector<uint32_t> Compile(ShaderType type, const TArrayView<VkShaderSource>& sources, const std::function<FString(FString)>& includeFilter = {});
const VkCachedShaderLump* GetPublicFile(const FString& lumpname);
const VkCachedShaderLump* GetPrivateFile(const FString& lumpname);
const VkCachedShaderLump& GetPublicFile(const FString& lumpname);
const VkCachedShaderLump& GetPrivateFile(const FString& lumpname);
private:
void Load();
@ -70,12 +70,9 @@ private:
VulkanRenderDevice* fb = nullptr;
std::mutex CacheMutex;
std::map<FString, VkCachedShaderLump> PublicFiles;
std::map<FString, VkCachedShaderLump> PrivateFiles;
std::map<FString, VkCachedCompile> CodeCache;
std::mutex FileMutex;
std::map<FString, std::unique_ptr<VkCachedShaderLump>> PublicFiles;
std::map<FString, std::unique_ptr<VkCachedShaderLump>> PrivateFiles;
};
class CachedGLSLCompiler

View file

@ -651,12 +651,12 @@ void VkLevelMesh::CreateViewerObjects()
FString VkLevelMesh::LoadPrivateShaderLump(const char* lumpname)
{
return fb->GetShaderCache()->GetPrivateFile(lumpname)->Code;
return fb->GetShaderCache()->GetPrivateFile(lumpname).Code;
}
FString VkLevelMesh::LoadPublicShaderLump(const char* lumpname)
{
return fb->GetShaderCache()->GetPublicFile(lumpname)->Code;
return fb->GetShaderCache()->GetPublicFile(lumpname).Code;
}
/////////////////////////////////////////////////////////////////////////////

View file

@ -610,12 +610,12 @@ int VkLightmapper::GetRaytracePipelineIndex()
FString VkLightmapper::LoadPrivateShaderLump(const char* lumpname)
{
return fb->GetShaderCache()->GetPrivateFile(lumpname)->Code;
return fb->GetShaderCache()->GetPrivateFile(lumpname).Code;
}
FString VkLightmapper::LoadPublicShaderLump(const char* lumpname)
{
return fb->GetShaderCache()->GetPublicFile(lumpname)->Code;
return fb->GetShaderCache()->GetPublicFile(lumpname).Code;
}
void VkLightmapper::CreateRaytracePipeline()