diff --git a/common/Vulkan/Context.cpp b/common/Vulkan/Context.cpp index 2e2279819a..49c2706a28 100644 --- a/common/Vulkan/Context.cpp +++ b/common/Vulkan/Context.cpp @@ -1268,6 +1268,8 @@ namespace Vulkan 1, present_swap_chain->GetSwapChainPtr(), present_swap_chain->GetCurrentImageIndexPtr(), nullptr}; + present_swap_chain->ReleaseCurrentImage(); + VkResult res = vkQueuePresentKHR(m_present_queue, &present_info); if (res != VK_SUCCESS) { @@ -1276,7 +1278,13 @@ namespace Vulkan LOG_VULKAN_ERROR(res, "vkQueuePresentKHR failed: "); m_last_present_failed.store(true); + return; } + + // Grab the next image as soon as possible, that way we spend less time blocked on the next + // submission. Don't care if it fails, we'll deal with that at the presentation call site. + // Credit to dxvk for the idea. + present_swap_chain->AcquireNextImage(); } void Context::WaitForPresentComplete() diff --git a/common/Vulkan/SwapChain.cpp b/common/Vulkan/SwapChain.cpp index b1677a910c..8e1bac2890 100644 --- a/common/Vulkan/SwapChain.cpp +++ b/common/Vulkan/SwapChain.cpp @@ -690,6 +690,7 @@ namespace Vulkan vkDestroyFramebuffer(g_vulkan_context->GetDevice(), it.framebuffer, nullptr); } m_images.clear(); + m_image_acquire_result.reset(); } void SwapChain::DestroySwapChain() @@ -705,6 +706,9 @@ namespace Vulkan VkResult SwapChain::AcquireNextImage() { + if (m_image_acquire_result.has_value()) + return m_image_acquire_result.value(); + if (!m_swap_chain) return VK_ERROR_SURFACE_LOST_KHR; @@ -723,9 +727,15 @@ namespace Vulkan } } + m_image_acquire_result = res; return res; } + void SwapChain::ReleaseCurrentImage() + { + m_image_acquire_result.reset(); + } + bool SwapChain::ResizeSwapChain(u32 new_width, u32 new_height, float new_scale) { DestroySwapChainImages(); diff --git a/common/Vulkan/SwapChain.h b/common/Vulkan/SwapChain.h index 73834bddad..9172eb2a0f 100644 --- a/common/Vulkan/SwapChain.h +++ b/common/Vulkan/SwapChain.h @@ -20,6 +20,7 @@ #include "common/Vulkan/Texture.h" #include "common/Vulkan/Loader.h" #include +#include #include namespace Vulkan @@ -74,6 +75,7 @@ namespace Vulkan __fi VkSemaphore GetRenderingFinishedSemaphore() const { return m_images[m_current_image].rendering_finished_semaphore; } __fi const VkSemaphore* GetRenderingFinishedSemaphorePtr() const { return &m_images[m_current_image].rendering_finished_semaphore; } VkResult AcquireNextImage(); + void ReleaseCurrentImage(); bool RecreateSurface(const WindowInfo& new_wi); bool ResizeSwapChain(u32 new_width = 0, u32 new_height = 0, float new_scale = 1.0f); @@ -122,5 +124,6 @@ namespace Vulkan VkSwapchainKHR m_swap_chain = VK_NULL_HANDLE; std::vector m_images; u32 m_current_image = 0; + std::optional m_image_acquire_result; }; } // namespace Vulkan diff --git a/pcsx2/Frontend/VulkanHostDisplay.cpp b/pcsx2/Frontend/VulkanHostDisplay.cpp index 8dbeee7785..3e92e42dd4 100644 --- a/pcsx2/Frontend/VulkanHostDisplay.cpp +++ b/pcsx2/Frontend/VulkanHostDisplay.cpp @@ -353,6 +353,8 @@ bool VulkanHostDisplay::BeginPresent(bool frame_skip) VkResult res = m_swap_chain->AcquireNextImage(); if (res != VK_SUCCESS) { + m_swap_chain->ReleaseCurrentImage(); + if (res == VK_SUBOPTIMAL_KHR || res == VK_ERROR_OUT_OF_DATE_KHR) { ResizeWindow(0, 0, m_window_info.surface_scale);