From ed50a0e01a65c5598ae68c301bfadf7a990017c4 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 19 Jan 2021 16:25:17 +0000 Subject: [PATCH] Add workaround for Qualcomm driver issue * Calling vkCmdSetLineWidth() before binding and dispatching a compute pipeline seems to crash on Qualcomm drivers. We rarely need to prepopulate dynamic state without a pipeline bound, so just skip this one state in that case on QC devices. --- renderdoc/driver/vulkan/vk_common.cpp | 3 ++- renderdoc/driver/vulkan/vk_common.h | 7 +++++++ renderdoc/driver/vulkan/vk_state.cpp | 3 +++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/renderdoc/driver/vulkan/vk_common.cpp b/renderdoc/driver/vulkan/vk_common.cpp index 3df226e86..665424ac8 100644 --- a/renderdoc/driver/vulkan/vk_common.cpp +++ b/renderdoc/driver/vulkan/vk_common.cpp @@ -972,9 +972,10 @@ VkDriverInfo::VkDriverInfo(const VkPhysicalDeviceProperties &physProps) } #endif - // not fixed yet + // not fixed yet that I know of qualcommLeakingUBOOffsets = (m_Vendor == GPUVendor::Qualcomm); qualcommDrefNon2DCompileCrash = (m_Vendor == GPUVendor::Qualcomm); + qualcommLineWidthCrash = (m_Vendor == GPUVendor::Qualcomm); } FrameRefType GetRefType(VkDescriptorType descType) diff --git a/renderdoc/driver/vulkan/vk_common.h b/renderdoc/driver/vulkan/vk_common.h index bfcc61324..8b3a1ef80 100644 --- a/renderdoc/driver/vulkan/vk_common.h +++ b/renderdoc/driver/vulkan/vk_common.h @@ -253,6 +253,12 @@ public: // On Qualcomm emitting an image sample operation with DRef and explicit lod will crash on non-2D // textures. Since 2D is the common/expected case, we avoid compiling that case entirely. bool QualcommDrefNon2DCompileCrash() const { return qualcommDrefNon2DCompileCrash; } + // On Qualcomm calling vkCmdSetLineWidth() before binding and dispatching a compute shader will + // crash in vkCmdDispatch. This works around the problem by avoiding setting that dynamic state + // unless there's a graphics pipeline when doing a partial replay, and it's unlikely the user will + // hit the case where it's necessary (doing 'whole pass' partial replay of a subsection of a + // command buffer where we need to apply dynamic state from earlier in the command buffer). + bool QualcommLineWidthDynamicStateCrash() const { return qualcommLineWidthCrash; } // On AMD unfortunately the initial implementation of KHR_buffer_device_address is broken and // produces bad results. bool AMDBufferDeviceAddressBrokenDriver() const { return amdBDABrokenDriver; } @@ -267,6 +273,7 @@ private: bool amdStorageMSAABrokenDriver = false; bool qualcommLeakingUBOOffsets = false; bool qualcommDrefNon2DCompileCrash = false; + bool qualcommLineWidthCrash = false; bool amdBDABrokenDriver = false; }; diff --git a/renderdoc/driver/vulkan/vk_state.cpp b/renderdoc/driver/vulkan/vk_state.cpp index 2aca4f948..a7ef147ec 100644 --- a/renderdoc/driver/vulkan/vk_state.cpp +++ b/renderdoc/driver/vulkan/vk_state.cpp @@ -171,6 +171,9 @@ void VulkanRenderState::BindPipeline(WrappedVulkan *vk, VkCommandBuffer cmd, // state from earlier in the command buffer but there's no pipeline bound yet. for(size_t i = 0; i < VkDynamicCount; i++) dynamicStates[i] = true; + + if(vk->GetDriverInfo().QualcommLineWidthDynamicStateCrash()) + dynamicStates[VkDynamicLineWidth] = false; } if(!views.empty() && dynamicStates[VkDynamicViewport])