From f6610b5b0c39c60a42ddac14a2ccc12171ac3c7e Mon Sep 17 00:00:00 2001 From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com> Date: Thu, 24 Jul 2025 09:02:33 +0200 Subject: [PATCH 1/7] GL: use unique_ptr for prgramBinaryCache --- .../HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp | 13 +++++-------- .../HW/Latte/Renderer/OpenGL/RendererShaderGL.h | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp index cae5314029..3c8ccb2422 100644 --- a/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp +++ b/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp @@ -266,8 +266,8 @@ void RendererShaderGL::ShaderCacheLoading_begin(uint64 cacheTitleId) { const uint32 cacheMagic = GeneratePrecompiledCacheId(); const std::string cacheFilename = fmt::format("{:016x}_gl.bin", cacheTitleId); - s_programBinaryCache = FileCache::Open(ActiveSettings::GetCachePath("shaderCache/precompiled/{}", cacheFilename), true, cacheMagic); - if (s_programBinaryCache == nullptr) + s_programBinaryCache.reset(FileCache::Open(ActiveSettings::GetCachePath("shaderCache/precompiled/{}", cacheFilename), true, cacheMagic)); + if (!s_programBinaryCache) cemuLog_log(LogType::Force, "Unable to open OpenGL precompiled cache {}", cacheFilename); } s_isLoadingShaders = true; @@ -280,13 +280,10 @@ void RendererShaderGL::ShaderCacheLoading_end() void RendererShaderGL::ShaderCacheLoading_Close() { - if(s_programBinaryCache) - { - delete s_programBinaryCache; - s_programBinaryCache = nullptr; - } + s_programBinaryCache.reset(); g_compiled_shaders_total = 0; g_compiled_shaders_async = 0; } -FileCache* RendererShaderGL::s_programBinaryCache{}; + +std::unique_ptr RendererShaderGL::s_programBinaryCache{}; diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.h b/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.h index 60c51cc13d..a5a24ca5a7 100644 --- a/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.h +++ b/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.h @@ -37,6 +37,6 @@ class RendererShaderGL : public RendererShader bool m_shader_attached{ false }; bool m_isCompiled{ false }; - static class FileCache* s_programBinaryCache; + static std::unique_ptr s_programBinaryCache; }; From 25c8f0a5ff6824e61e6be7e0d22a47f0e1e29fe9 Mon Sep 17 00:00:00 2001 From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com> Date: Thu, 24 Jul 2025 09:15:50 +0200 Subject: [PATCH 2/7] Remove unused isRendererThread argument from PreponeCompilation --- src/Cafe/HW/Latte/Core/LatteShader.cpp | 6 +++--- src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp | 2 +- src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp | 2 +- src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.h | 2 +- src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp | 4 ++-- src/Cafe/HW/Latte/Renderer/RendererShader.h | 2 +- src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp | 8 ++++---- src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h | 4 ++-- .../HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.cpp | 8 ++++---- src/Cafe/HW/Latte/Renderer/Vulkan/VulkanSurfaceCopy.cpp | 6 +++--- 10 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/Cafe/HW/Latte/Core/LatteShader.cpp b/src/Cafe/HW/Latte/Core/LatteShader.cpp index d9f0a5ddfc..3e6bf41e51 100644 --- a/src/Cafe/HW/Latte/Core/LatteShader.cpp +++ b/src/Cafe/HW/Latte/Core/LatteShader.cpp @@ -767,7 +767,7 @@ LatteDecompilerShader* LatteShader_CompileSeparableVertexShader(uint64 baseHash, if (g_renderer->GetType() == RendererAPI::OpenGL) { if (vertexShader->shader) - vertexShader->shader->PreponeCompilation(true); + vertexShader->shader->PreponeCompilation(); LatteShader_FinishCompilation(vertexShader); } @@ -796,7 +796,7 @@ LatteDecompilerShader* LatteShader_CompileSeparableGeometryShader(uint64 baseHas if (g_renderer->GetType() == RendererAPI::OpenGL) { if (geometryShader->shader) - geometryShader->shader->PreponeCompilation(true); + geometryShader->shader->PreponeCompilation(); LatteShader_FinishCompilation(geometryShader); } @@ -825,7 +825,7 @@ LatteDecompilerShader* LatteShader_CompileSeparablePixelShader(uint64 baseHash, if (g_renderer->GetType() == RendererAPI::OpenGL) { if (pixelShader->shader) - pixelShader->shader->PreponeCompilation(true); + pixelShader->shader->PreponeCompilation(); LatteShader_FinishCompilation(pixelShader); } diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp index 571961f4f2..030dfbfe90 100644 --- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp +++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp @@ -868,7 +868,7 @@ RendererShaderGL* rectsEmulationGS_generateShaderGL(LatteDecompilerShader* verte gsSrc.append("}\r\n"); auto glShader = new RendererShaderGL(RendererShader::ShaderType::kGeometry, 0, 0, false, false, gsSrc); - glShader->PreponeCompilation(true); + glShader->PreponeCompilation(); return glShader; } diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp index 3c8ccb2422..60a1830d98 100644 --- a/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp +++ b/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp @@ -157,7 +157,7 @@ RendererShaderGL::~RendererShaderGL() glDeleteProgram(m_program); } -void RendererShaderGL::PreponeCompilation(bool isRenderThread) +void RendererShaderGL::PreponeCompilation() { // the logic for initiating compilation is currently in the constructor // here we only guarantee that it is finished before we return diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.h b/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.h index a5a24ca5a7..3238b4230b 100644 --- a/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.h +++ b/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.h @@ -10,7 +10,7 @@ class RendererShaderGL : public RendererShader virtual ~RendererShaderGL(); - void PreponeCompilation(bool isRenderThread) override; + void PreponeCompilation() override; bool IsCompiled() override; bool WaitForCompiled() override; diff --git a/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp b/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp index afe53a16cb..e37e054cbf 100644 --- a/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp +++ b/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp @@ -121,8 +121,8 @@ RendererOutputShader::RendererOutputShader(const std::string& vertex_source, con m_vertex_shader.reset(g_renderer->shader_create(RendererShader::ShaderType::kVertex, 0, 0, vertex_source, false, false)); m_fragment_shader.reset(g_renderer->shader_create(RendererShader::ShaderType::kFragment, 0, 0, finalFragmentSrc, false, false)); - m_vertex_shader->PreponeCompilation(true); - m_fragment_shader->PreponeCompilation(true); + m_vertex_shader->PreponeCompilation(); + m_fragment_shader->PreponeCompilation(); if (!m_vertex_shader->WaitForCompiled()) throw std::exception(); diff --git a/src/Cafe/HW/Latte/Renderer/RendererShader.h b/src/Cafe/HW/Latte/Renderer/RendererShader.h index e3f254c600..9906eff61c 100644 --- a/src/Cafe/HW/Latte/Renderer/RendererShader.h +++ b/src/Cafe/HW/Latte/Renderer/RendererShader.h @@ -14,7 +14,7 @@ class RendererShader ShaderType GetType() const { return m_type; } - virtual void PreponeCompilation(bool isRenderThread) = 0; // if shader not yet compiled, compile it synchronously (if possible) or alternatively wait for compilation. After this function IsCompiled() is guaranteed to be true + virtual void PreponeCompilation() = 0; // if shader not yet compiled, compile it synchronously (if possible) or alternatively wait for compilation. After this function IsCompiled() is guaranteed to be true virtual bool IsCompiled() = 0; virtual bool WaitForCompiled() = 0; diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp index 665a5da3bb..558aa0e2f7 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp @@ -174,7 +174,7 @@ class _ShaderVkThreadPool job->m_compilationState.setValue(RendererShaderVk::COMPILATION_STATE::COMPILING); s_compilationQueueMutex.unlock(); // compile - job->CompileInternal(false); + job->CompileInternal(); ++g_compiled_shaders_async; // mark as compiled cemu_assert_debug(job->m_compilationState.getValue() == RendererShaderVk::COMPILATION_STATE::COMPILING); @@ -280,7 +280,7 @@ void RendererShaderVk::FinishCompilation() m_glslCode.shrink_to_fit(); } -void RendererShaderVk::CompileInternal(bool isRenderThread) +void RendererShaderVk::CompileInternal() { // try to retrieve SPIR-V module from cache if (s_isLoadingShadersVk && (m_isGameShader && !m_isGfxPackShader) && s_spirvCache) @@ -412,7 +412,7 @@ void RendererShaderVk::CompileInternal(bool isRenderThread) FinishCompilation(); } -void RendererShaderVk::PreponeCompilation(bool isRenderThread) +void RendererShaderVk::PreponeCompilation() { ShaderVkThreadPool.s_compilationQueueMutex.lock(); bool isStillQueued = m_compilationState.hasState(COMPILATION_STATE::QUEUED); @@ -432,7 +432,7 @@ void RendererShaderVk::PreponeCompilation(bool isRenderThread) else { // compile synchronously - CompileInternal(isRenderThread); + CompileInternal(); m_compilationState.setValue(COMPILATION_STATE::DONE); } } diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h index f9c3ede140..b9ece7edaf 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h @@ -52,12 +52,12 @@ class RendererShaderVk : public RendererShader s_dependencyLock.unlock(); } - void PreponeCompilation(bool isRenderThread) override; + void PreponeCompilation() override; bool IsCompiled() override; bool WaitForCompiled() override; private: - void CompileInternal(bool isRenderThread); + void CompileInternal(); void FinishCompilation(); diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.cpp index 7555c03af9..bdc4ffa576 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineCompiler.cpp @@ -159,7 +159,7 @@ RendererShaderVk* rectsEmulationGS_generate(LatteDecompilerShader* vertexShader, gsSrc.append("}\r\n"); auto vkShader = new RendererShaderVk(RendererShader::ShaderType::kGeometry, 0, 0, false, false, gsSrc); - vkShader->PreponeCompilation(true); + vkShader->PreponeCompilation(); return vkShader; } @@ -966,11 +966,11 @@ bool PipelineCompiler::Compile(bool forceCompile, bool isRenderThread, bool show { // if some shader stages are not compiled yet, compile them now if (m_vkVertexShader && m_vkVertexShader->IsCompiled() == false) - m_vkVertexShader->PreponeCompilation(isRenderThread); + m_vkVertexShader->PreponeCompilation(); if (m_vkPixelShader && m_vkPixelShader->IsCompiled() == false) - m_vkPixelShader->PreponeCompilation(isRenderThread); + m_vkPixelShader->PreponeCompilation(); if (m_vkGeometryShader && m_vkGeometryShader->IsCompiled() == false) - m_vkGeometryShader->PreponeCompilation(isRenderThread); + m_vkGeometryShader->PreponeCompilation(); } if (shaderStages.empty()) diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanSurfaceCopy.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanSurfaceCopy.cpp index e3e4201202..33386399ae 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanSurfaceCopy.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanSurfaceCopy.cpp @@ -181,7 +181,7 @@ RendererShaderVk* _vkGenSurfaceCopyShader_vs() std::string shaderStr(vsShaderSrc); auto vkShader = new RendererShaderVk(RendererShader::ShaderType::kVertex, 0, 0, false, false, shaderStr); - vkShader->PreponeCompilation(true); + vkShader->PreponeCompilation(); return vkShader; } @@ -199,7 +199,7 @@ RendererShaderVk* _vkGenSurfaceCopyShader_ps_colorToDepth() std::string shaderStr(psShaderSrc); auto vkShader = new RendererShaderVk(RendererShader::ShaderType::kFragment, 0, 0, false, false, shaderStr); - vkShader->PreponeCompilation(true); + vkShader->PreponeCompilation(); return vkShader; } @@ -218,7 +218,7 @@ RendererShaderVk* _vkGenSurfaceCopyShader_ps_depthToColor() std::string shaderStr(psShaderSrc); auto vkShader = new RendererShaderVk(RendererShader::ShaderType::kFragment, 0, 0, false, false, shaderStr); - vkShader->PreponeCompilation(true); + vkShader->PreponeCompilation(); return vkShader; } From 55d2ac0e43028cf07ad428cda12af46d981d0d36 Mon Sep 17 00:00:00 2001 From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com> Date: Thu, 24 Jul 2025 09:38:53 +0200 Subject: [PATCH 3/7] Remove LatteShader_FinishCompilation CleanupAfterCompile is already done in LatteShader_CreateRendererShader WaitForCompiled is already done in PreponeCompilation --- src/Cafe/HW/Latte/Core/LatteShader.cpp | 19 +++---------------- src/Cafe/HW/Latte/Core/LatteShader.h | 1 - src/Cafe/HW/Latte/Core/LatteShaderCache.cpp | 5 ++++- src/Cafe/HW/Latte/Core/LatteShaderGL.cpp | 2 ++ 4 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/Cafe/HW/Latte/Core/LatteShader.cpp b/src/Cafe/HW/Latte/Core/LatteShader.cpp index 3e6bf41e51..886b6f38a4 100644 --- a/src/Cafe/HW/Latte/Core/LatteShader.cpp +++ b/src/Cafe/HW/Latte/Core/LatteShader.cpp @@ -357,19 +357,6 @@ void LatteShader_CreateRendererShader(LatteDecompilerShader* shader, bool compil LatteShader_CleanupAfterCompile(shader); } -void LatteShader_FinishCompilation(LatteDecompilerShader* shader) -{ - if (shader->hasError) - { - cemuLog_logDebug(LogType::Force, "LatteShader_finishCompilation(): Skipped because of error in shader {:x}", shader->baseHash); - return; - } - shader->shader->WaitForCompiled(); - - LatteShader_prepareSeparableUniforms(shader); - LatteShader_CleanupAfterCompile(shader); -} - void LatteSHRC_RegisterShader(LatteDecompilerShader* shader, uint64 baseHash, uint64 auxHash) { auto& cache = LatteSHRC_GetCacheByType(shader->shaderType); @@ -768,7 +755,7 @@ LatteDecompilerShader* LatteShader_CompileSeparableVertexShader(uint64 baseHash, { if (vertexShader->shader) vertexShader->shader->PreponeCompilation(); - LatteShader_FinishCompilation(vertexShader); + LatteShader_prepareSeparableUniforms(vertexShader); } LatteSHRC_RegisterShader(vertexShader, vertexShader->baseHash, vertexShader->auxHash); @@ -797,7 +784,7 @@ LatteDecompilerShader* LatteShader_CompileSeparableGeometryShader(uint64 baseHas { if (geometryShader->shader) geometryShader->shader->PreponeCompilation(); - LatteShader_FinishCompilation(geometryShader); + LatteShader_prepareSeparableUniforms(geometryShader); } LatteSHRC_RegisterShader(geometryShader, geometryShader->baseHash, geometryShader->auxHash); @@ -826,7 +813,7 @@ LatteDecompilerShader* LatteShader_CompileSeparablePixelShader(uint64 baseHash, { if (pixelShader->shader) pixelShader->shader->PreponeCompilation(); - LatteShader_FinishCompilation(pixelShader); + LatteShader_prepareSeparableUniforms(pixelShader); } LatteSHRC_RegisterShader(pixelShader, _shaderBaseHash_ps, psAuxHash); diff --git a/src/Cafe/HW/Latte/Core/LatteShader.h b/src/Cafe/HW/Latte/Core/LatteShader.h index f8dc6d1a3b..42e952dd0f 100644 --- a/src/Cafe/HW/Latte/Core/LatteShader.h +++ b/src/Cafe/HW/Latte/Core/LatteShader.h @@ -99,7 +99,6 @@ void LatteShader_GetDecompilerOptions(struct LatteDecompilerOptions& options, La LatteDecompilerShader* LatteShader_CreateShaderFromDecompilerOutput(LatteDecompilerOutput_t& decompilerOutput, uint64 baseHash, bool calculateAuxHash, uint64 optionalAuxHash, uint32* contextRegister); void LatteShader_CreateRendererShader(LatteDecompilerShader* shader, bool compileAsync); -void LatteShader_FinishCompilation(LatteDecompilerShader* shader); void LatteShader_prepareSeparableUniforms(LatteDecompilerShader* shader); diff --git a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp index 737e92012a..9ea3db5ad5 100644 --- a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp +++ b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp @@ -108,7 +108,10 @@ void LatteShaderCache_updateCompileQueue(sint32 maxRemainingEntries) break; auto shader = shaderCompileQueue.entry[0].shader; if (shader) - LatteShader_FinishCompilation(shader); + { + shader->shader->PreponeCompilation(); + LatteShader_prepareSeparableUniforms(shader); + } LatteShaderCache_removeFromCompileQueue(0); } } diff --git a/src/Cafe/HW/Latte/Core/LatteShaderGL.cpp b/src/Cafe/HW/Latte/Core/LatteShaderGL.cpp index b8cb0ce1be..3384b60c61 100644 --- a/src/Cafe/HW/Latte/Core/LatteShaderGL.cpp +++ b/src/Cafe/HW/Latte/Core/LatteShaderGL.cpp @@ -28,6 +28,8 @@ void LatteShader_prepareSeparableUniforms(LatteDecompilerShader* shader) { if (g_renderer->GetType() == RendererAPI::Vulkan) return; + if(shader->hasError) + return; auto shaderGL = (RendererShaderGL*)shader->shader; // setup uniform info From a96435a5ddac43222f78d76867c991ba2e81b8d5 Mon Sep 17 00:00:00 2001 From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com> Date: Thu, 24 Jul 2025 09:43:46 +0200 Subject: [PATCH 4/7] ShaderCache: theoretical loading speedup by first checking to see if a shader later in the queue is already compiled --- src/Cafe/HW/Latte/Core/LatteShaderCache.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp index 9ea3db5ad5..2e0b98d7c5 100644 --- a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp +++ b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp @@ -102,6 +102,18 @@ void LatteShaderCache_removeFromCompileQueue(sint32 index) */ void LatteShaderCache_updateCompileQueue(sint32 maxRemainingEntries) { + // remove any shaders that are already done + for (size_t i = 0; i < shaderCompileQueue.count; i++) + { + auto shaderEntry = shaderCompileQueue.entry[i].shader; + if (!shaderEntry) + continue; + if (shaderEntry->shader->IsCompiled()) + { + LatteShader_prepareSeparableUniforms(shaderEntry); + LatteShaderCache_removeFromCompileQueue(i); + } + } while (true) { if (shaderCompileQueue.count <= maxRemainingEntries) From 328509e719468f7c574ab0047ed3b5ebcab4353a Mon Sep 17 00:00:00 2001 From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com> Date: Thu, 24 Jul 2025 09:45:02 +0200 Subject: [PATCH 5/7] GL: delay shader error check and program linking to improve parallel shader compilation --- .../Renderer/OpenGL/RendererShaderGL.cpp | 83 +++++++++---------- 1 file changed, 39 insertions(+), 44 deletions(-) diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp index 60a1830d98..f872328a70 100644 --- a/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp +++ b/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp @@ -109,37 +109,13 @@ RendererShaderGL::RendererShaderGL(ShaderType type, uint64 baseHash, uint64 auxH glShaderSource(m_shader_object, 1, &c_str, &size); glCompileShader(m_shader_object); - GLint log_length; - glGetShaderiv(m_shader_object, GL_INFO_LOG_LENGTH, &log_length); - if (log_length > 0) - { - char log[2048]{}; - GLsizei log_size; - glGetShaderInfoLog(m_shader_object, std::min(log_length, sizeof(log) - 1), &log_size, log); - cemuLog_log(LogType::Force, "Error/Warning in shader:"); - cemuLog_log(LogType::Force, log); - } - // set debug name - if (LaunchSettings::NSightModeEnabled()) + if (LaunchSettings::NSightModeEnabled()) { auto objNameStr = fmt::format("shader_{:016x}_{:016x}", m_baseHash, m_auxHash); glObjectLabel(GL_SHADER, m_shader_object, objNameStr.size(), objNameStr.c_str()); } - m_program = glCreateProgram(); - glProgramParameteri(m_program, GL_PROGRAM_SEPARABLE, GL_TRUE); - glProgramParameteri(m_program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); - glAttachShader(m_program, m_shader_object); - m_shader_attached = true; - glLinkProgram(m_program); - - storeBinary(); - - // count shader compilation - if (!s_isLoadingShaders) - ++g_compiled_shaders_total; - // we can throw away the GLSL code to conserve RAM m_glslSource.clear(); m_glslSource.shrink_to_fit(); @@ -168,47 +144,61 @@ void RendererShaderGL::PreponeCompilation() bool RendererShaderGL::IsCompiled() { - cemu_assert_debug(false); - return true; + if(m_isCompiled) + return true; + GLint isShaderComplete; + glGetShaderiv(m_shader_object, GL_COMPLETION_STATUS_ARB, &isShaderComplete); + if(isShaderComplete) + WaitForCompiled(); // since COMPLETION_STATUS == true, this should be very fast + return m_isCompiled; } bool RendererShaderGL::WaitForCompiled() { char infoLog[8 * 1024]; + GLint log_length; if (m_isCompiled) return true; + + // count shader compilation + if (!s_isLoadingShaders) + ++g_compiled_shaders_total; + // check if compilation was successful GLint compileStatus = GL_FALSE; glGetShaderiv(m_shader_object, GL_COMPILE_STATUS, &compileStatus); - if (compileStatus == 0) + if (compileStatus == GL_FALSE) { - uint32 infoLogLength, tempLength; - glGetShaderiv(m_shader_object, GL_INFO_LOG_LENGTH, (GLint *)&infoLogLength); - if (infoLogLength != 0) + glGetShaderiv(m_shader_object, GL_INFO_LOG_LENGTH, &log_length); + if (log_length > 0) { - tempLength = sizeof(infoLog) - 1; - glGetShaderInfoLog(m_shader_object, std::min(infoLogLength, tempLength), (GLsizei*)&tempLength, (GLcharARB*)infoLog); - infoLog[tempLength] = '\0'; - cemuLog_log(LogType::Force, "Compile error in shader. Log:"); + glGetShaderInfoLog(m_shader_object, sizeof(infoLog), &log_length, infoLog); + cemuLog_log(LogType::Force, "Error/Warning in shader:"); cemuLog_log(LogType::Force, infoLog); } + if (m_shader_object != 0) glDeleteShader(m_shader_object); m_isCompiled = true; return false; } + + m_program = glCreateProgram(); + glProgramParameteri(m_program, GL_PROGRAM_SEPARABLE, GL_TRUE); + glProgramParameteri(m_program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); + glAttachShader(m_program, m_shader_object); + m_shader_attached = true; + glLinkProgram(m_program); + // get shader binary GLint linkStatus = GL_FALSE; glGetProgramiv(m_program, GL_LINK_STATUS, &linkStatus); - if (linkStatus == 0) + if (linkStatus == GL_FALSE) { - uint32 infoLogLength, tempLength; - glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, (GLint *)&infoLogLength); - if (infoLogLength != 0) + glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, (GLint *)&log_length); + if (log_length != 0) { - tempLength = sizeof(infoLog) - 1; - glGetProgramInfoLog(m_program, std::min(infoLogLength, tempLength), (GLsizei*)&tempLength, (GLcharARB*)infoLog); - infoLog[tempLength] = '\0'; + glGetProgramInfoLog(m_program, sizeof(infoLog), &log_length, (GLcharARB*)infoLog); cemuLog_log(LogType::Force, "Link error in shader. Log:"); cemuLog_log(LogType::Force, infoLog); } @@ -216,8 +206,13 @@ bool RendererShaderGL::WaitForCompiled() return false; } - /*glDetachShader(m_program, m_shader_object); - m_shader_attached = false;*/ + storeBinary(); + + glDetachShader(m_program, m_shader_object); + m_shader_attached = false; + glDeleteShader(m_shader_object); + m_shader_object = 0; + m_isCompiled = true; return true; } From 7a4c539a00e89b90b35e1b32fd8e1a059eb518ff Mon Sep 17 00:00:00 2001 From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com> Date: Thu, 24 Jul 2025 10:18:59 +0200 Subject: [PATCH 6/7] only use GL_COMPLETION_STATUS_ARB when the extension is used --- .../HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp index f872328a70..d432160236 100644 --- a/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp +++ b/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp @@ -146,9 +146,16 @@ bool RendererShaderGL::IsCompiled() { if(m_isCompiled) return true; - GLint isShaderComplete; + + if(!glMaxShaderCompilerThreadsARB) + { + WaitForCompiled(); + return true; + } + + GLint isShaderComplete = 0; glGetShaderiv(m_shader_object, GL_COMPLETION_STATUS_ARB, &isShaderComplete); - if(isShaderComplete) + if (isShaderComplete) WaitForCompiled(); // since COMPLETION_STATUS == true, this should be very fast return m_isCompiled; } From 069fe64aa01bfbfe9486ba649dfcec1906a8b466 Mon Sep 17 00:00:00 2001 From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com> Date: Thu, 24 Jul 2025 10:55:32 +0200 Subject: [PATCH 7/7] immediately issue link call as well --- .../Renderer/OpenGL/RendererShaderGL.cpp | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp index d432160236..ac5275c86c 100644 --- a/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp +++ b/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp @@ -116,6 +116,13 @@ RendererShaderGL::RendererShaderGL(ShaderType type, uint64 baseHash, uint64 auxH glObjectLabel(GL_SHADER, m_shader_object, objNameStr.size(), objNameStr.c_str()); } + m_program = glCreateProgram(); + glProgramParameteri(m_program, GL_PROGRAM_SEPARABLE, GL_TRUE); + glProgramParameteri(m_program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); + glAttachShader(m_program, m_shader_object); + m_shader_attached = true; + glLinkProgram(m_program); + // we can throw away the GLSL code to conserve RAM m_glslSource.clear(); m_glslSource.shrink_to_fit(); @@ -153,9 +160,12 @@ bool RendererShaderGL::IsCompiled() return true; } - GLint isShaderComplete = 0; + GLint isShaderComplete = 0, isProgramComplete = 0; glGetShaderiv(m_shader_object, GL_COMPLETION_STATUS_ARB, &isShaderComplete); - if (isShaderComplete) + if(!isShaderComplete) + return false; + glGetProgramiv(m_program, GL_COMPLETION_STATUS_ARB, &isProgramComplete); + if (isProgramComplete) WaitForCompiled(); // since COMPLETION_STATUS == true, this should be very fast return m_isCompiled; } @@ -186,17 +196,13 @@ bool RendererShaderGL::WaitForCompiled() if (m_shader_object != 0) glDeleteShader(m_shader_object); + if (m_program != 0) + glDeleteProgram(m_program); + m_program = m_shader_object = 0; m_isCompiled = true; return false; } - m_program = glCreateProgram(); - glProgramParameteri(m_program, GL_PROGRAM_SEPARABLE, GL_TRUE); - glProgramParameteri(m_program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); - glAttachShader(m_program, m_shader_object); - m_shader_attached = true; - glLinkProgram(m_program); - // get shader binary GLint linkStatus = GL_FALSE; glGetProgramiv(m_program, GL_LINK_STATUS, &linkStatus);