From 280de39471aff3587d3b5b67cadd224bc36e7613 Mon Sep 17 00:00:00 2001 From: Crementif <26669564+Crementif@users.noreply.github.com> Date: Sun, 23 Nov 2025 17:23:10 +0100 Subject: [PATCH] vk: Always embed shader source code when RenderDoc (etc.) is attached The only downside is that attaching RenderDoc to Cemu will cause it to ignore the spirv cache. This causes slightly longer load times when RenderDoc is attached and you had a prior shader cache that contained the non-debug shader. --- .../Renderer/Vulkan/RendererShaderVk.cpp | 39 +++++++++---------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp index 403db5bf..f639a9bb 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp @@ -292,8 +292,10 @@ void RendererShaderVk::FinishCompilation() void RendererShaderVk::CompileInternal(bool isRenderThread) { + bool compileWithDebugInfo = ((VulkanRenderer*)g_renderer.get())->IsDebugUtilsEnabled() && vkSetDebugUtilsObjectNameEXT; + // try to retrieve SPIR-V module from cache - if (s_isLoadingShadersVk && (m_isGameShader && !m_isGfxPackShader) && s_spirvCache) + if (s_isLoadingShadersVk && (m_isGameShader && !m_isGfxPackShader) && s_spirvCache && !compileWithDebugInfo) { cemu_assert_debug(m_baseHash != 0); uint64 h1, h2; @@ -329,21 +331,12 @@ void RendererShaderVk::CompileInternal(bool isRenderThread) Shader.setStrings(&cstr, 1); Shader.setEnvInput(glslang::EShSourceGlsl, state, glslang::EShClientVulkan, 100); Shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetClientVersion::EShTargetVulkan_1_1); - Shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetLanguageVersion::EShTargetSpv_1_3); - TBuiltInResource Resources = GetDefaultBuiltInResource(); std::string PreprocessedGLSL; - - VulkanRenderer* vkr = (VulkanRenderer*)g_renderer.get(); - - EShMessages messagesPreprocess; - if (vkr->IsDebugUtilsEnabled() && vkSetDebugUtilsObjectNameEXT) - messagesPreprocess = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules | EShMsgDebugInfo); - else - messagesPreprocess = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules); - glslang::TShader::ForbidIncluder Includer; + TBuiltInResource Resources = GetDefaultBuiltInResource(); + EShMessages messagesPreprocess = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules); if (!Shader.preprocess(&Resources, 450, ENoProfile, false, false, messagesPreprocess, &PreprocessedGLSL, Includer)) { cemuLog_log(LogType::Force, fmt::format("GLSL Preprocessing Failed For {:016x}_{:016x}: \"{}\"", m_baseHash, m_auxHash, Shader.getInfoLog())); @@ -351,14 +344,9 @@ void RendererShaderVk::CompileInternal(bool isRenderThread) return; } - EShMessages messagesParseLink; - if (vkr->IsDebugUtilsEnabled() && vkSetDebugUtilsObjectNameEXT) - messagesParseLink = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules | EShMsgDebugInfo); - else - messagesParseLink = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules); - const char* PreprocessedCStr = PreprocessedGLSL.c_str(); Shader.setStrings(&PreprocessedCStr, 1); + EShMessages messagesParseLink = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules); if (!Shader.parse(&Resources, 100, false, messagesParseLink)) { cemuLog_log(LogType::Force, fmt::format("GLSL parsing failed for {:016x}_{:016x}: \"{}\"", m_baseHash, m_auxHash, Shader.getInfoLog())); @@ -392,9 +380,17 @@ void RendererShaderVk::CompileInternal(bool isRenderThread) glslang::SpvOptions spvOptions; spvOptions.disableOptimizer = false; - spvOptions.generateDebugInfo = (vkr->IsDebugUtilsEnabled() && vkSetDebugUtilsObjectNameEXT); spvOptions.validate = false; spvOptions.optimizeSize = true; + if (compileWithDebugInfo) + { + spvOptions.generateDebugInfo = true; + spvOptions.emitNonSemanticShaderDebugInfo = true; + spvOptions.emitNonSemanticShaderDebugSource = true; + + Shader.addSourceText(m_glslCode.c_str(), (uint32)m_glslCode.size()); + Shader.setSourceFile(fmt::format("shader_{:016x}_{:016x}.glsl", m_baseHash, m_auxHash).c_str()); + } //auto beginTime = benchmarkTimer_start(); @@ -402,8 +398,9 @@ void RendererShaderVk::CompileInternal(bool isRenderThread) //double timeDur = benchmarkTimer_stop(beginTime); //forceLogRemoveMe_printf("Shader GLSL-to-SPIRV compilation took %lfms Size %08x", timeDur, spirvBuffer.size()*4); - - if (s_spirvCache && m_isGameShader && m_isGfxPackShader == false) + + // store in cache, unless it got compiled with debug info or is a modified shader from a gfx pack + if (s_spirvCache && m_isGameShader && m_isGfxPackShader == false && !compileWithDebugInfo) { uint64 h1, h2; GenerateShaderPrecompiledCacheFilename(m_type, m_baseHash, m_auxHash, h1, h2);