From 134daf3b00d1bf46a3ad4b57405f8844b809bb4f Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sun, 3 Sep 2017 14:04:14 +1000 Subject: Vulkan: Extend the NVIDIA MSAA bug to render-pass based clears Calling vkCmdClearAttachments with a partial rect, or specifying a render area in a render pass with the load op set to clear can cause the GPU to lock up, or raise a bounds violation. This only occurs on MSAA framebuffers, and it seems when there are multiple clears in a single command buffer. Worked around by back to the slow path (drawing quads) when MSAA is enabled. --- Source/Core/VideoBackends/Vulkan/Renderer.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'Source/Core/VideoBackends/Vulkan/Renderer.cpp') diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp index bb8b36481a..7a94572b1e 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp +++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp @@ -375,18 +375,23 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha // If we're not in a render pass (start of the frame), we can use a clear render pass // to discard the data, rather than loading and then clearing. - bool use_clear_render_pass = (color_enable && alpha_enable && z_enable); - if (DriverDetails::HasBug(DriverDetails::BUG_BROKEN_CLEAR_LOADOP_RENDERPASS)) + bool use_clear_attachments = (color_enable && alpha_enable) || z_enable; + bool use_clear_render_pass = + !StateTracker::GetInstance()->InRenderPass() && color_enable && alpha_enable && z_enable; + + // The NVIDIA Vulkan driver causes the GPU to lock up, or throw exceptions if MSAA is enabled, + // a non-full clear rect is specified, and a clear loadop or vkCmdClearAttachments is used. + if (g_ActiveConfig.iMultisamples > 1 && + DriverDetails::HasBug(DriverDetails::BUG_BROKEN_MSAA_CLEAR)) { - // This path cannot be used if the driver implementation doesn't guarantee pixels with no drawn - // geomerty in "this" renderpass won't be cleared use_clear_render_pass = false; + use_clear_attachments = false; } - if (StateTracker::GetInstance()->InRenderPass()) - { - // Prefer not to end a render pass just to do a clear. + + // This path cannot be used if the driver implementation doesn't guarantee pixels with no drawn + // geometry in "this" renderpass won't be cleared + if (DriverDetails::HasBug(DriverDetails::BUG_BROKEN_CLEAR_LOADOP_RENDERPASS)) use_clear_render_pass = false; - } // Fastest path: Use a render pass to clear the buffers. if (use_clear_render_pass) @@ -398,8 +403,7 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha // Fast path: Use vkCmdClearAttachments to clear the buffers within a render path // We can't use this when preserving alpha but clearing color. - if (g_ActiveConfig.iMultisamples == 1 || - !DriverDetails::HasBug(DriverDetails::BUG_BROKEN_MSAA_VKCMDCLEARATTACHMENTS)) + if (use_clear_attachments) { VkClearAttachment clear_attachments[2]; uint32_t num_clear_attachments = 0; -- cgit v1.2.3