diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureVk.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureVk.cpp index a62741e4..80dcb4d7 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureVk.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureVk.cpp @@ -87,7 +87,7 @@ LatteTextureVk::LatteTextureVk(class VulkanRenderer* vkRenderer, Latte::E_DIM di if (vkCreateImage(m_vkr->GetLogicalDevice(), &imageInfo, nullptr, &vkObjTex->m_image) != VK_SUCCESS) m_vkr->UnrecoverableError("Failed to create texture image"); - if (m_vkr->IsDebugUtilsEnabled() && vkSetDebugUtilsObjectNameEXT) + if (m_vkr->IsDebugMarkersEnabled()) { VkDebugUtilsObjectNameInfoEXT objName{}; objName.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT; diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp index 403db5bf..f6549e3c 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp @@ -271,7 +271,7 @@ void RendererShaderVk::CreateVkShaderModule(std::span spirvBuffer) } // set debug name - if (vkr->IsDebugUtilsEnabled() && vkSetDebugUtilsObjectNameEXT) + if (vkr->IsDebugMarkersEnabled()) { VkDebugUtilsObjectNameInfoEXT objName{}; objName.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT; @@ -292,8 +292,10 @@ void RendererShaderVk::FinishCompilation() void RendererShaderVk::CompileInternal(bool isRenderThread) { + const bool compileWithDebugInfo = ((VulkanRenderer*)g_renderer.get())->IsTracingToolEnabled(); + // 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); diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp index 5a7d8f4e..a1340a94 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp @@ -446,8 +446,6 @@ VulkanRenderer::VulkanRenderer() } CheckDeviceExtensionSupport(m_physicalDevice, m_featureControl); // todo - merge this with GetDeviceFeatures and separate from IsDeviceSuitable? - if (m_featureControl.debugMarkersSupported) - cemuLog_log(LogType::Force, "Debug: Frame debugger attached, will use vkDebugMarkerSetObjectNameEXT"); DetermineVendor(); GetDeviceFeatures(); @@ -582,10 +580,14 @@ VulkanRenderer::VulkanRenderer() debugCallback.pfnUserCallback = &DebugUtilsCallback; vkCreateDebugUtilsMessengerEXT(m_instance, &debugCallback, nullptr, &m_debugCallback); + + cemuLog_log(LogType::Force, "Debug: Vulkan validation layer enabled, vkCreateDebugUtilsMessengerEXT will be used to log validation errors"); } - if (m_featureControl.instanceExtensions.debug_utils) - cemuLog_log(LogType::Force, "Using available debug function: vkCreateDebugUtilsMessengerEXT()"); + if (this->IsTracingToolEnabled()) + cemuLog_log(LogType::Force, "Debug: Tracing tool detected, will recompile all shaders with debug info enabled. This disables the SPIR-V cache."); + if (this->IsDebugMarkersEnabled()) + cemuLog_log(LogType::Force, "Debug: Detected tool capable of using debug markers, will use vkDebugMarkerSetObjectNameEXT to identify Vulkan objects"); // set initial viewport and scissor box size m_state.currentViewport.width = 4; @@ -1256,8 +1258,9 @@ bool VulkanRenderer::CheckDeviceExtensionSupport(const VkPhysicalDevice device, // dynamic rendering doesn't provide any benefits for us right now. Driver implementations are very unoptimized as of Feb 2022 info.deviceExtensions.present_wait = isExtensionAvailable(VK_KHR_PRESENT_WAIT_EXTENSION_NAME) && isExtensionAvailable(VK_KHR_PRESENT_ID_EXTENSION_NAME); - // check for framedebuggers - info.debugMarkersSupported = false; + // check for validation layers and frame debuggers + info.usingDebugMarkerTool = false; + info.usingTracingTool = false; if (info.deviceExtensions.tooling_info && vkGetPhysicalDeviceToolPropertiesEXT) { uint32_t toolCount = 0; @@ -1268,8 +1271,10 @@ bool VulkanRenderer::CheckDeviceExtensionSupport(const VkPhysicalDevice device, { for (auto& itr : toolProperties) { - if ((itr.purposes & VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT) != 0) - info.debugMarkersSupported = true; + if ((itr.purposes & VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT) != 0 && info.instanceExtensions.debug_utils && vkSetDebugUtilsObjectNameEXT) + info.usingDebugMarkerTool = true; + if ((itr.purposes & VK_TOOL_PURPOSE_TRACING_BIT) != 0) + info.usingTracingTool = true; } } } diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h index 7290fdd7..fabf7490 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h @@ -482,7 +482,8 @@ private: uint32 nonCoherentAtomSize = 256; }limits; - bool debugMarkersSupported{ false }; // frame debugger is attached + bool usingDebugMarkerTool{ false }; // validation layer or other tool capable of handling debug markers is used + bool usingTracingTool{ false }; // frame debugger or other API replaying tool is used bool disableMultithreadedCompilation{ false }; // for old nvidia drivers }m_featureControl{}; @@ -937,7 +938,8 @@ public: bool GetDisableMultithreadedCompilation() const { return m_featureControl.disableMultithreadedCompilation; } bool UseTFViaSSBO() const { return m_featureControl.mode.useTFEmulationViaSSBO; } bool HasSPRIVRoundingModeRTE32() const { return m_featureControl.shaderFloatControls.shaderRoundingModeRTEFloat32; } - bool IsDebugUtilsEnabled() const { return m_featureControl.debugMarkersSupported && m_featureControl.instanceExtensions.debug_utils; } + bool IsDebugMarkersEnabled() const { return m_featureControl.usingDebugMarkerTool; } + bool IsTracingToolEnabled() const { return m_featureControl.usingTracingTool; } private: diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp index 32ef7007..03e0d2bf 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp @@ -245,7 +245,7 @@ void compilePipelineThread_queue(PipelineCompiler* v) bool VulkanRenderer::IsAsyncPipelineAllowed(uint32 numIndices) { // frame debuggers dont handle async well (as of 2020) - if (IsDebugUtilsEnabled() && vkSetDebugUtilsObjectNameEXT) + if (IsTracingToolEnabled()) return false; CachedFBOVk* currentFBO = m_state.activeFBO;