mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-12-12 10:37:02 +00:00
Vulkan: Always embed shader source code when RenderDoc, Nsight or other frame debuggers are attached (#1733)
This commit is contained in:
parent
bb3fb81fb6
commit
51c1e80ba7
5 changed files with 38 additions and 34 deletions
|
|
@ -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)
|
if (vkCreateImage(m_vkr->GetLogicalDevice(), &imageInfo, nullptr, &vkObjTex->m_image) != VK_SUCCESS)
|
||||||
m_vkr->UnrecoverableError("Failed to create texture image");
|
m_vkr->UnrecoverableError("Failed to create texture image");
|
||||||
|
|
||||||
if (m_vkr->IsDebugUtilsEnabled() && vkSetDebugUtilsObjectNameEXT)
|
if (m_vkr->IsDebugMarkersEnabled())
|
||||||
{
|
{
|
||||||
VkDebugUtilsObjectNameInfoEXT objName{};
|
VkDebugUtilsObjectNameInfoEXT objName{};
|
||||||
objName.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
|
objName.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
|
||||||
|
|
|
||||||
|
|
@ -271,7 +271,7 @@ void RendererShaderVk::CreateVkShaderModule(std::span<uint32> spirvBuffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
// set debug name
|
// set debug name
|
||||||
if (vkr->IsDebugUtilsEnabled() && vkSetDebugUtilsObjectNameEXT)
|
if (vkr->IsDebugMarkersEnabled())
|
||||||
{
|
{
|
||||||
VkDebugUtilsObjectNameInfoEXT objName{};
|
VkDebugUtilsObjectNameInfoEXT objName{};
|
||||||
objName.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
|
objName.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
|
||||||
|
|
@ -292,8 +292,10 @@ void RendererShaderVk::FinishCompilation()
|
||||||
|
|
||||||
void RendererShaderVk::CompileInternal(bool isRenderThread)
|
void RendererShaderVk::CompileInternal(bool isRenderThread)
|
||||||
{
|
{
|
||||||
|
const bool compileWithDebugInfo = ((VulkanRenderer*)g_renderer.get())->IsTracingToolEnabled();
|
||||||
|
|
||||||
// try to retrieve SPIR-V module from cache
|
// 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);
|
cemu_assert_debug(m_baseHash != 0);
|
||||||
uint64 h1, h2;
|
uint64 h1, h2;
|
||||||
|
|
@ -329,21 +331,12 @@ void RendererShaderVk::CompileInternal(bool isRenderThread)
|
||||||
Shader.setStrings(&cstr, 1);
|
Shader.setStrings(&cstr, 1);
|
||||||
Shader.setEnvInput(glslang::EShSourceGlsl, state, glslang::EShClientVulkan, 100);
|
Shader.setEnvInput(glslang::EShSourceGlsl, state, glslang::EShClientVulkan, 100);
|
||||||
Shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetClientVersion::EShTargetVulkan_1_1);
|
Shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetClientVersion::EShTargetVulkan_1_1);
|
||||||
|
|
||||||
Shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetLanguageVersion::EShTargetSpv_1_3);
|
Shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetLanguageVersion::EShTargetSpv_1_3);
|
||||||
|
|
||||||
TBuiltInResource Resources = GetDefaultBuiltInResource();
|
|
||||||
std::string PreprocessedGLSL;
|
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;
|
glslang::TShader::ForbidIncluder Includer;
|
||||||
|
TBuiltInResource Resources = GetDefaultBuiltInResource();
|
||||||
|
EShMessages messagesPreprocess = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules);
|
||||||
if (!Shader.preprocess(&Resources, 450, ENoProfile, false, false, messagesPreprocess, &PreprocessedGLSL, Includer))
|
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()));
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
EShMessages messagesParseLink;
|
|
||||||
if (vkr->IsDebugUtilsEnabled() && vkSetDebugUtilsObjectNameEXT)
|
|
||||||
messagesParseLink = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules | EShMsgDebugInfo);
|
|
||||||
else
|
|
||||||
messagesParseLink = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules);
|
|
||||||
|
|
||||||
const char* PreprocessedCStr = PreprocessedGLSL.c_str();
|
const char* PreprocessedCStr = PreprocessedGLSL.c_str();
|
||||||
Shader.setStrings(&PreprocessedCStr, 1);
|
Shader.setStrings(&PreprocessedCStr, 1);
|
||||||
|
EShMessages messagesParseLink = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules);
|
||||||
if (!Shader.parse(&Resources, 100, false, messagesParseLink))
|
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()));
|
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;
|
glslang::SpvOptions spvOptions;
|
||||||
spvOptions.disableOptimizer = false;
|
spvOptions.disableOptimizer = false;
|
||||||
spvOptions.generateDebugInfo = (vkr->IsDebugUtilsEnabled() && vkSetDebugUtilsObjectNameEXT);
|
|
||||||
spvOptions.validate = false;
|
spvOptions.validate = false;
|
||||||
spvOptions.optimizeSize = true;
|
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();
|
//auto beginTime = benchmarkTimer_start();
|
||||||
|
|
||||||
|
|
@ -402,8 +398,9 @@ void RendererShaderVk::CompileInternal(bool isRenderThread)
|
||||||
|
|
||||||
//double timeDur = benchmarkTimer_stop(beginTime);
|
//double timeDur = benchmarkTimer_stop(beginTime);
|
||||||
//forceLogRemoveMe_printf("Shader GLSL-to-SPIRV compilation took %lfms Size %08x", timeDur, spirvBuffer.size()*4);
|
//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;
|
uint64 h1, h2;
|
||||||
GenerateShaderPrecompiledCacheFilename(m_type, m_baseHash, m_auxHash, h1, h2);
|
GenerateShaderPrecompiledCacheFilename(m_type, m_baseHash, m_auxHash, h1, h2);
|
||||||
|
|
|
||||||
|
|
@ -446,8 +446,6 @@ VulkanRenderer::VulkanRenderer()
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckDeviceExtensionSupport(m_physicalDevice, m_featureControl); // todo - merge this with GetDeviceFeatures and separate from IsDeviceSuitable?
|
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();
|
DetermineVendor();
|
||||||
GetDeviceFeatures();
|
GetDeviceFeatures();
|
||||||
|
|
@ -582,10 +580,14 @@ VulkanRenderer::VulkanRenderer()
|
||||||
debugCallback.pfnUserCallback = &DebugUtilsCallback;
|
debugCallback.pfnUserCallback = &DebugUtilsCallback;
|
||||||
|
|
||||||
vkCreateDebugUtilsMessengerEXT(m_instance, &debugCallback, nullptr, &m_debugCallback);
|
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)
|
if (this->IsTracingToolEnabled())
|
||||||
cemuLog_log(LogType::Force, "Using available debug function: vkCreateDebugUtilsMessengerEXT()");
|
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
|
// set initial viewport and scissor box size
|
||||||
m_state.currentViewport.width = 4;
|
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
|
// 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);
|
info.deviceExtensions.present_wait = isExtensionAvailable(VK_KHR_PRESENT_WAIT_EXTENSION_NAME) && isExtensionAvailable(VK_KHR_PRESENT_ID_EXTENSION_NAME);
|
||||||
|
|
||||||
// check for framedebuggers
|
// check for validation layers and frame debuggers
|
||||||
info.debugMarkersSupported = false;
|
info.usingDebugMarkerTool = false;
|
||||||
|
info.usingTracingTool = false;
|
||||||
if (info.deviceExtensions.tooling_info && vkGetPhysicalDeviceToolPropertiesEXT)
|
if (info.deviceExtensions.tooling_info && vkGetPhysicalDeviceToolPropertiesEXT)
|
||||||
{
|
{
|
||||||
uint32_t toolCount = 0;
|
uint32_t toolCount = 0;
|
||||||
|
|
@ -1268,8 +1271,10 @@ bool VulkanRenderer::CheckDeviceExtensionSupport(const VkPhysicalDevice device,
|
||||||
{
|
{
|
||||||
for (auto& itr : toolProperties)
|
for (auto& itr : toolProperties)
|
||||||
{
|
{
|
||||||
if ((itr.purposes & VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT) != 0)
|
if ((itr.purposes & VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT) != 0 && info.instanceExtensions.debug_utils && vkSetDebugUtilsObjectNameEXT)
|
||||||
info.debugMarkersSupported = true;
|
info.usingDebugMarkerTool = true;
|
||||||
|
if ((itr.purposes & VK_TOOL_PURPOSE_TRACING_BIT) != 0)
|
||||||
|
info.usingTracingTool = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -482,7 +482,8 @@ private:
|
||||||
uint32 nonCoherentAtomSize = 256;
|
uint32 nonCoherentAtomSize = 256;
|
||||||
}limits;
|
}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
|
bool disableMultithreadedCompilation{ false }; // for old nvidia drivers
|
||||||
|
|
||||||
}m_featureControl{};
|
}m_featureControl{};
|
||||||
|
|
@ -937,7 +938,8 @@ public:
|
||||||
bool GetDisableMultithreadedCompilation() const { return m_featureControl.disableMultithreadedCompilation; }
|
bool GetDisableMultithreadedCompilation() const { return m_featureControl.disableMultithreadedCompilation; }
|
||||||
bool UseTFViaSSBO() const { return m_featureControl.mode.useTFEmulationViaSSBO; }
|
bool UseTFViaSSBO() const { return m_featureControl.mode.useTFEmulationViaSSBO; }
|
||||||
bool HasSPRIVRoundingModeRTE32() const { return m_featureControl.shaderFloatControls.shaderRoundingModeRTEFloat32; }
|
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:
|
private:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -245,7 +245,7 @@ void compilePipelineThread_queue(PipelineCompiler* v)
|
||||||
bool VulkanRenderer::IsAsyncPipelineAllowed(uint32 numIndices)
|
bool VulkanRenderer::IsAsyncPipelineAllowed(uint32 numIndices)
|
||||||
{
|
{
|
||||||
// frame debuggers dont handle async well (as of 2020)
|
// frame debuggers dont handle async well (as of 2020)
|
||||||
if (IsDebugUtilsEnabled() && vkSetDebugUtilsObjectNameEXT)
|
if (IsTracingToolEnabled())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
CachedFBOVk* currentFBO = m_state.activeFBO;
|
CachedFBOVk* currentFBO = m_state.activeFBO;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue