From 08649b7aa803e5c5c22eb4d5b4c538a524fa1511 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Tue, 4 Jul 2023 17:39:14 +1000 Subject: [PATCH] GS/Vulkan: Work around NVIDIA driver clear issue NVIDIA drivers appear to return random garbage when sampling the RT via a feedback loop, if the load op for the render pass is CLEAR. Using vkCmdClearAttachments() doesn't work, so we have to clear the image instead. I'm not sure if this is a spec violation, or what we're doing just happens to be undefined. Given attachment clear doesn't work, I'm inclined to go with the former. --- pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp | 8 ++++++++ pcsx2/GS/Renderers/Vulkan/VKContext.h | 3 +++ 2 files changed, 11 insertions(+) diff --git a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp index e92fd22291..99dac6c5bf 100644 --- a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp +++ b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp @@ -1521,6 +1521,14 @@ void GSDeviceVK::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector { if (vkRt) { + // NVIDIA drivers appear to return random garbage when sampling the RT via a feedback loop, if the load op for + // the render pass is CLEAR. Using vkCmdClearAttachments() doesn't work, so we have to clear the image instead. + if (feedback_loop & FeedbackLoopFlag_ReadAndWriteRT && vkRt->GetState() == GSTexture::State::Cleared && + g_vulkan_context->IsDeviceNVIDIA()) + { + vkRt->CommitClear(); + } + vkRt->TransitionToLayout((feedback_loop & FeedbackLoopFlag_ReadAndWriteRT) ? GSTextureVK::Layout::FeedbackLoop : GSTextureVK::Layout::ColorAttachment); diff --git a/pcsx2/GS/Renderers/Vulkan/VKContext.h b/pcsx2/GS/Renderers/Vulkan/VKContext.h index 98738efbcd..9ec4c8dcf4 100644 --- a/pcsx2/GS/Renderers/Vulkan/VKContext.h +++ b/pcsx2/GS/Renderers/Vulkan/VKContext.h @@ -128,6 +128,9 @@ public: return m_device_properties.limits.maxImageDimension2D; } + /// Returns true if running on an NVIDIA GPU. + __fi bool IsDeviceNVIDIA() const { return (m_device_properties.vendorID == 0x10DE); } + // Creates a simple render pass. __ri VkRenderPass GetRenderPass(VkFormat color_format, VkFormat depth_format, VkAttachmentLoadOp color_load_op = VK_ATTACHMENT_LOAD_OP_LOAD,