From 0fe8f2e40cf4e7a9aec744ce00c502bb1d1a3100 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 1 Jun 2021 04:44:02 +0200 Subject: [PATCH] [vulkan] Acquire next image immediately after presentation vkAcquireNextImageKHR is a blocking call, so doing this immediately after presentation may reduce the amount of time that passes between the application requesing presentation and presentation actually happening on the Vulkan device. Idea based on PR #2075. --- src/vulkan/vulkan_presenter.cpp | 32 +++++++++++++++++++++++--------- src/vulkan/vulkan_presenter.h | 2 ++ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/vulkan/vulkan_presenter.cpp b/src/vulkan/vulkan_presenter.cpp index 5d0f6250..a1013f7c 100644 --- a/src/vulkan/vulkan_presenter.cpp +++ b/src/vulkan/vulkan_presenter.cpp @@ -46,17 +46,18 @@ namespace dxvk::vk { VkResult Presenter::acquireNextImage(PresenterSync& sync, uint32_t& index) { sync = m_semaphores.at(m_frameIndex); - VkResult status = m_vkd->vkAcquireNextImageKHR( - m_vkd->device(), m_swapchain, - std::numeric_limits::max(), - sync.acquire, VK_NULL_HANDLE, &m_imageIndex); + // Don't acquire more than one image at a time + if (m_acquireStatus == VK_NOT_READY) { + m_acquireStatus = m_vkd->vkAcquireNextImageKHR(m_vkd->device(), + m_swapchain, std::numeric_limits::max(), + sync.acquire, VK_NULL_HANDLE, &m_imageIndex); + } - if (status != VK_SUCCESS - && status != VK_SUBOPTIMAL_KHR) - return status; + if (m_acquireStatus != VK_SUCCESS && m_acquireStatus != VK_SUBOPTIMAL_KHR) + return m_acquireStatus; index = m_imageIndex; - return status; + return m_acquireStatus; } @@ -73,10 +74,22 @@ namespace dxvk::vk { info.pImageIndices = &m_imageIndex; info.pResults = nullptr; + VkResult status = m_vkd->vkQueuePresentKHR(m_device.queue, &info); + + if (status != VK_SUCCESS && status != VK_SUBOPTIMAL_KHR) + return status; + + // Try to acquire next image already, in order to hide + // potential delays from the application thread. m_frameIndex += 1; m_frameIndex %= m_semaphores.size(); - return m_vkd->vkQueuePresentKHR(m_device.queue, &info); + sync = m_semaphores.at(m_frameIndex); + + m_acquireStatus = m_vkd->vkAcquireNextImageKHR(m_vkd->device(), + m_swapchain, std::numeric_limits::max(), + sync.acquire, VK_NULL_HANDLE, &m_imageIndex); + return status; } @@ -220,6 +233,7 @@ namespace dxvk::vk { // Invalidate indices m_imageIndex = 0; m_frameIndex = 0; + m_acquireStatus = VK_NOT_READY; return VK_SUCCESS; } diff --git a/src/vulkan/vulkan_presenter.h b/src/vulkan/vulkan_presenter.h index a7cbbf7d..b73874bd 100644 --- a/src/vulkan/vulkan_presenter.h +++ b/src/vulkan/vulkan_presenter.h @@ -182,6 +182,8 @@ namespace dxvk::vk { uint32_t m_imageIndex = 0; uint32_t m_frameIndex = 0; + VkResult m_acquireStatus = VK_NOT_READY; + VkResult getSupportedFormats( std::vector& formats, const PresenterDesc& desc);