From 0c0bd8be989d6b5da5e100161989879709dfd8dd Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Wed, 2 Feb 2022 20:29:33 +1000 Subject: [PATCH] GS/Vulkan: Use fence counter for upload cmdbuffer selection Readbacks don't increment the frame number, but submit the cmdbuffer. Fixes incorrectly rendered status bar in Devil May Cry. --- pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp | 11 ++++------- pcsx2/GS/Renderers/Vulkan/GSTextureVK.cpp | 3 +-- pcsx2/GS/Renderers/Vulkan/GSTextureVK.h | 11 +++++++++++ 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp index 581cd5bb0b..b69a8e7e90 100644 --- a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp +++ b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp @@ -509,8 +509,9 @@ void GSDeviceVK::DoCopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& EndRenderPass(); - sTexVK->TransitionToLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); dTexVK->TransitionToLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + sTexVK->TransitionToLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + sTexVK->SetUsedThisCommandBuffer(); vkCmdCopyImage(g_vulkan_context->GetCurrentCommandBuffer(), sTexVK->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dTexVK->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &ic); @@ -798,10 +799,6 @@ void GSDeviceVK::DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool static_cast(dTex)->TransitionToLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - const VkFramebuffer fb = static_cast(dTex)->GetFramebuffer(false); - if (fb == VK_NULL_HANDLE) - return; - const GSVector4i rc(0, 0, size.x, size.y); EndRenderPass(); OMSetRenderTargets(dTex, nullptr, rc, false); @@ -2099,7 +2096,7 @@ void GSDeviceVK::PSSetShaderResource(int i, GSTexture* sr, bool check_state) vkTex->CommitClear(); vkTex->TransitionToLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); } - vkTex->last_frame_used = m_frame; + vkTex->SetUsedThisCommandBuffer(); view = vkTex->GetView(); } else @@ -2131,9 +2128,9 @@ void GSDeviceVK::SetUtilityTexture(GSTexture* tex, VkSampler sampler) if (tex) { GSTextureVK* vkTex = static_cast(tex); - vkTex->last_frame_used = m_frame; vkTex->CommitClear(); vkTex->TransitionToLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + vkTex->SetUsedThisCommandBuffer(); view = vkTex->GetView(); } else diff --git a/pcsx2/GS/Renderers/Vulkan/GSTextureVK.cpp b/pcsx2/GS/Renderers/Vulkan/GSTextureVK.cpp index 32198ffa35..e31836bad2 100644 --- a/pcsx2/GS/Renderers/Vulkan/GSTextureVK.cpp +++ b/pcsx2/GS/Renderers/Vulkan/GSTextureVK.cpp @@ -151,8 +151,7 @@ void* GSTextureVK::GetNativeHandle() const { return const_cast VkCommandBuffer GSTextureVK::GetCommandBufferForUpdate() { - const u32 frame = GSDeviceVK::GetInstance()->GetFrameNumber(); - if (m_type != Type::Texture || frame == last_frame_used) + if (m_type != Type::Texture || m_use_fence_counter == g_vulkan_context->GetCurrentFenceCounter()) { // Console.WriteLn("Texture update within frame, can't use do beforehand"); GSDeviceVK::GetInstance()->EndRenderPass(); diff --git a/pcsx2/GS/Renderers/Vulkan/GSTextureVK.h b/pcsx2/GS/Renderers/Vulkan/GSTextureVK.h index 4ae4192be3..bf21375a59 100644 --- a/pcsx2/GS/Renderers/Vulkan/GSTextureVK.h +++ b/pcsx2/GS/Renderers/Vulkan/GSTextureVK.h @@ -17,6 +17,7 @@ #include "GS.h" #include "GS/Renderers/Common/GSTexture.h" +#include "common/Vulkan/Context.h" #include "common/Vulkan/Texture.h" class GSTextureVK final : public GSTexture @@ -70,11 +71,21 @@ public: m_clear_value.depth = depth; } + // Call when the texture is bound to the pipeline, or read from in a copy. + __fi void SetUsedThisCommandBuffer() + { + m_use_fence_counter = g_vulkan_context->GetCurrentFenceCounter(); + } + private: VkCommandBuffer GetCommandBufferForUpdate(); Vulkan::Texture m_texture; + // Contains the fence counter when the texture was last used. + // When this matches the current fence counter, the texture was used this command buffer. + u64 m_use_fence_counter = 0; + ClearValue m_clear_value = {}; GSVector4i m_map_area = GSVector4i::zero();