From e77960b3b4382b18c42094760e0df4e79520f416 Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Wed, 2 Jan 2019 20:26:08 -0800 Subject: Added swap chain recovery if acquire next image fails in Vulkan backend --- .../GraphicsEngineVulkan/include/SwapChainVkImpl.h | 2 +- .../GraphicsEngineVulkan/src/SwapChainVkImpl.cpp | 40 ++++++++++++++-------- 2 files changed, 27 insertions(+), 15 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h b/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h index 8d830cbc..aada3ab5 100644 --- a/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h @@ -71,7 +71,7 @@ public: private: void CreateVulkanSwapChain(); void InitBuffersAndViews(); - void AcquireNextImage(DeviceContextVkImpl* pDeviceCtxVk); + VkResult AcquireNextImage(DeviceContextVkImpl* pDeviceCtxVk); void RecreateVulkanSwapchain(DeviceContextVkImpl* pImmediateCtxVk); std::shared_ptr m_VulkanInstance; diff --git a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp index 7abde39d..f3837886 100644 --- a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp @@ -97,7 +97,8 @@ SwapChainVkImpl::SwapChainVkImpl(IReferenceCounters* pRefCounters, CreateVulkanSwapChain(); InitBuffersAndViews(); - AcquireNextImage(pDeviceContextVk); + auto res = AcquireNextImage(pDeviceContextVk); + DEV_CHECK_ERR(res == VK_SUCCESS, "Failed to acquire next image for the newly created swap chain"); (void)res; } void SwapChainVkImpl::CreateVulkanSwapChain() @@ -400,24 +401,27 @@ void SwapChainVkImpl::InitBuffersAndViews() m_pDepthBufferDSV = RefCntAutoPtr(pDSV, IID_TextureViewVk); } -void SwapChainVkImpl::AcquireNextImage(DeviceContextVkImpl* pDeviceCtxVk) +VkResult SwapChainVkImpl::AcquireNextImage(DeviceContextVkImpl* pDeviceCtxVk) { auto* pDeviceVk = m_pRenderDevice.RawPtr(); const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); auto res = vkAcquireNextImageKHR(LogicalDevice.GetVkDevice(), m_VkSwapChain, UINT64_MAX, m_ImageAcquiredSemaphores[m_SemaphoreIndex], (VkFence)nullptr, &m_BackBufferIndex); - VERIFY(res == VK_SUCCESS, "Failed to acquire next swap chain image"); (void)res; - - // Next command in the device context must wait for the next image to be acquired - // Unlike fences or events, the act of waiting for a semaphore also unsignals that semaphore (6.4.2) - pDeviceCtxVk->AddWaitSemaphore(m_ImageAcquiredSemaphores[m_SemaphoreIndex], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); - if (!m_SwapChainImagesInitialized[m_BackBufferIndex]) + if (res == VK_SUCCESS) { - // Vulkan validation layers do not like uninitialized memory. - // Clear back buffer first time we acquire it. This will use vkCmdClearColorImage() - pDeviceCtxVk->ClearRenderTarget(GetCurrentBackBufferRTV(), nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); - m_SwapChainImagesInitialized[m_BackBufferIndex] = true; + // Next command in the device context must wait for the next image to be acquired + // Unlike fences or events, the act of waiting for a semaphore also unsignals that semaphore (6.4.2) + pDeviceCtxVk->AddWaitSemaphore(m_ImageAcquiredSemaphores[m_SemaphoreIndex], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); + if (!m_SwapChainImagesInitialized[m_BackBufferIndex]) + { + // Vulkan validation layers do not like uninitialized memory. + // Clear back buffer first time we acquire it. This will use vkCmdClearColorImage() + pDeviceCtxVk->ClearRenderTarget(GetCurrentBackBufferRTV(), nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + m_SwapChainImagesInitialized[m_BackBufferIndex] = true; + } } + + return res; } IMPLEMENT_QUERY_INTERFACE( SwapChainVkImpl, IID_SwapChainVk, TSwapChainBase ) @@ -489,7 +493,14 @@ void SwapChainVkImpl::Present(Uint32 SyncInterval) if (m_SemaphoreIndex >= m_SwapChainDesc.BufferCount) m_SemaphoreIndex = 0; - AcquireNextImage(pImmediateCtxVk); + auto res = AcquireNextImage(pImmediateCtxVk); + if (res == VK_SUBOPTIMAL_KHR || res == VK_ERROR_OUT_OF_DATE_KHR) + { + RecreateVulkanSwapchain(pImmediateCtxVk); + m_SemaphoreIndex = m_SwapChainDesc.BufferCount-1; // To start with 0 index when acquire next image + res = AcquireNextImage(pImmediateCtxVk); + } + DEV_CHECK_ERR(res == VK_SUCCESS, "Failed to acquire next swap chain image"); if (IsDefaultFBBound) { @@ -542,7 +553,8 @@ void SwapChainVkImpl::Resize( Uint32 NewWidth, Uint32 NewHeight ) bool bIsDefaultFBBound = pImmediateCtxVk->IsDefaultFBBound(); RecreateVulkanSwapchain(pImmediateCtxVk); - AcquireNextImage(pImmediateCtxVk); + auto res = AcquireNextImage(pImmediateCtxVk); + DEV_CHECK_ERR(res == VK_SUCCESS, "Failed to acquire next image for the just resized swap chain"); (void)res; if( bIsDefaultFBBound ) { -- cgit v1.2.3