From 4a29fdb3f20f8733af90f9803c0918d2997fdb1a Mon Sep 17 00:00:00 2001 From: Stenzek Date: Mon, 8 May 2023 22:03:06 +1000 Subject: [PATCH] GS/Vulkan: Ensure restarted render passes don't clear We don't want to wipe out what's done, and we don't know the clear values anyway. --- pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp | 2 +- pcsx2/GS/Renderers/Vulkan/VKContext.cpp | 29 ++++++++++++++++++++++++ pcsx2/GS/Renderers/Vulkan/VKContext.h | 3 +++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp index 626ec4a769..e363cbdecc 100644 --- a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp +++ b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp @@ -2952,7 +2952,7 @@ void GSDeviceVK::ExecuteCommandBufferAndRestartRenderPass(bool wait_for_completi OMSetRenderTargets(current_rt, current_ds, scissor, current_feedback_loop); // restart render pass - BeginRenderPass(render_pass, render_pass_area); + BeginRenderPass(g_vulkan_context->GetRenderPassForRestarting(render_pass), render_pass_area); } } diff --git a/pcsx2/GS/Renderers/Vulkan/VKContext.cpp b/pcsx2/GS/Renderers/Vulkan/VKContext.cpp index 7cd9b5dfe8..2322a39d57 100644 --- a/pcsx2/GS/Renderers/Vulkan/VKContext.cpp +++ b/pcsx2/GS/Renderers/Vulkan/VKContext.cpp @@ -933,6 +933,35 @@ bool VKContext::CreateTextureStreamBuffer() return true; } +VkRenderPass VKContext::GetRenderPassForRestarting(VkRenderPass pass) +{ + for (const auto& it : m_render_pass_cache) + { + if (it.second != pass) + continue; + + RenderPassCacheKey modified_key; + modified_key.key = it.first; + if (modified_key.color_load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) + modified_key.color_load_op = VK_ATTACHMENT_LOAD_OP_LOAD; + if (modified_key.depth_load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) + modified_key.depth_load_op = VK_ATTACHMENT_LOAD_OP_LOAD; + if (modified_key.stencil_load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) + modified_key.stencil_load_op = VK_ATTACHMENT_LOAD_OP_LOAD; + + if (modified_key.key == it.first) + return pass; + + auto fit = m_render_pass_cache.find(modified_key.key); + if (fit != m_render_pass_cache.end()) + return fit->second; + + return CreateCachedRenderPass(modified_key); + } + + return pass; +} + VkCommandBuffer VKContext::GetCurrentInitCommandBuffer() { FrameResources& res = m_frame_resources[m_current_frame]; diff --git a/pcsx2/GS/Renderers/Vulkan/VKContext.h b/pcsx2/GS/Renderers/Vulkan/VKContext.h index 3c1794398b..98738efbcd 100644 --- a/pcsx2/GS/Renderers/Vulkan/VKContext.h +++ b/pcsx2/GS/Renderers/Vulkan/VKContext.h @@ -157,6 +157,9 @@ public: return CreateCachedRenderPass(key); } + // Gets a non-clearing version of the specified render pass. Slow, don't call in hot path. + VkRenderPass GetRenderPassForRestarting(VkRenderPass pass); + // These command buffers are allocated per-frame. They are valid until the command buffer // is submitted, after that you should call these functions again. __fi u32 GetCurrentCommandBufferIndex() const { return m_current_frame; }