diff options
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
5 files changed, 59 insertions, 34 deletions
diff --git a/Graphics/GraphicsEngineVulkan/include/CommandQueueVkImpl.h b/Graphics/GraphicsEngineVulkan/include/CommandQueueVkImpl.h index f2503737..ca07d3ef 100644 --- a/Graphics/GraphicsEngineVulkan/include/CommandQueueVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/CommandQueueVkImpl.h @@ -58,12 +58,12 @@ public: virtual Uint64 Submit(const VkSubmitInfo& SubmitInfo)override final; - virtual void Present(const VkPresentInfoKHR& PresentInfo)override final; + virtual VkResult Present(const VkPresentInfoKHR& PresentInfo)override final; virtual VkQueue GetVkQueue()override final{return m_VkQueue;} virtual uint32_t GetQueueFamilyIndex()const override final { return m_QueueFamilyIndex; } - + virtual Uint64 WaitForIdle()override final; virtual Uint64 GetCompletedFenceValue()override final; diff --git a/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h b/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h index 9c448ce1..6028d785 100644 --- a/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h @@ -67,11 +67,12 @@ public: } virtual ITextureViewVk* GetDepthBufferDSV()override final{return m_pDepthBufferDSV;} - + private: void CreateVulkanSwapChain(); void InitBuffersAndViews(); void AcquireNextImage(DeviceContextVkImpl* pDeviceCtxVk); + void RecreateVulkanSwapchain(DeviceContextVkImpl* pImmediateCtxVk); std::shared_ptr<const VulkanUtilities::VulkanInstance> m_VulkanInstance; VkSurfaceKHR m_VkSurface = VK_NULL_HANDLE; diff --git a/Graphics/GraphicsEngineVulkan/interface/CommandQueueVk.h b/Graphics/GraphicsEngineVulkan/interface/CommandQueueVk.h index a6175961..c10db2ca 100644 --- a/Graphics/GraphicsEngineVulkan/interface/CommandQueueVk.h +++ b/Graphics/GraphicsEngineVulkan/interface/CommandQueueVk.h @@ -54,7 +54,7 @@ public: virtual Uint64 Submit(const VkSubmitInfo& SubmitInfo) = 0; /// Presents the current swap chain image on the screen - virtual void Present(const VkPresentInfoKHR& PresentInfo) = 0; + virtual VkResult Present(const VkPresentInfoKHR& PresentInfo) = 0; /// Returns Vulkan command queue. May return VK_NULL_HANDLE if queue is anavailable virtual VkQueue GetVkQueue() = 0; diff --git a/Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp index 53a1d193..5dd6b813 100644 --- a/Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp @@ -119,11 +119,10 @@ void CommandQueueVkImpl::SignalFence(VkFence vkFence) DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to submit command buffer to the command queue"); } -void CommandQueueVkImpl::Present(const VkPresentInfoKHR& PresentInfo) +VkResult CommandQueueVkImpl::Present(const VkPresentInfoKHR& PresentInfo) { std::lock_guard<std::mutex> Lock(m_QueueMutex); - auto Result = vkQueuePresentKHR(m_VkQueue, &PresentInfo); - DEV_CHECK_ERR(Result == VK_SUCCESS, "Present failed"); + return vkQueuePresentKHR(m_VkQueue, &PresentInfo); } } diff --git a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp index c9c0a8f3..8a8d4ebd 100644 --- a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp @@ -77,8 +77,14 @@ SwapChainVkImpl::SwapChainVkImpl(IReferenceCounters* pRefCounters, #elif defined(VK_USE_PLATFORM_XCB_KHR) VkXcbSurfaceCreateInfoKHR surfaceCreateInfo = {}; surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; - surfaceCreateInfo.connection = 0;//connection; - surfaceCreateInfo.window = 0;//window; + struct XCBInfo + { + xcb_connection_t* connection = nullptr; + uint32_t window = 0; + }; + XCBInfo& info = *reinterpret_cast<XCBInfo*>(pNativeWndHandle); + surfaceCreateInfo.connection = info.connection; + surfaceCreateInfo.window = info.window; auto err = vkCreateXcbSurfaceKHR(m_VulkanInstance->GetVkInstance(), &surfaceCreateInfo, nullptr, &m_VkSurface); #endif @@ -439,7 +445,9 @@ void SwapChainVkImpl::Present(Uint32 SyncInterval) } pImmediateCtxVk->Flush(); - + // If present fails, default FB will be undbound by RecreateVulkanSwapchain(), so we need to check it now + bool IsDefaultFBBound = pImmediateCtxVk->IsDefaultFBBound(); + if (!m_IsMinimized) { VkPresentInfoKHR PresentInfo = {}; @@ -460,6 +468,16 @@ void SwapChainVkImpl::Present(Uint32 SyncInterval) pCmdQueueVk->Present(PresentInfo); } ); + + if (Result == VK_SUBOPTIMAL_KHR || Result == VK_ERROR_OUT_OF_DATE_KHR) + { + RecreateVulkanSwapchain(pImmediateCtxVk); + m_SemaphoreIndex = m_SwapChainDesc.BufferCount-1; // To start with 0 index when acquire next image + } + else + { + DEV_CHECK_ERR(Result == VK_SUCCESS, "Present failed"); + } } pImmediateCtxVk->FinishFrame(); @@ -473,7 +491,7 @@ void SwapChainVkImpl::Present(Uint32 SyncInterval) AcquireNextImage(pImmediateCtxVk); - if(pImmediateCtxVk->IsDefaultFBBound()) + if (IsDefaultFBBound) { // If default framebuffer is bound, we need to call SetRenderTargets() // to bind new back buffer RTV @@ -482,6 +500,31 @@ void SwapChainVkImpl::Present(Uint32 SyncInterval) } } +void SwapChainVkImpl::RecreateVulkanSwapchain(DeviceContextVkImpl* pImmediateCtxVk) +{ + if (pImmediateCtxVk->IsDefaultFBBound()) + pImmediateCtxVk->ResetRenderTargets(); + + // All references to the swap chain must be released before it can be resized + m_pBackBufferRTV.clear(); + m_SwapChainImagesInitialized.clear(); + m_pDepthBufferDSV.Release(); + + RenderDeviceVkImpl* pDeviceVk = m_pRenderDevice.RawPtr<RenderDeviceVkImpl>(); + // This will release references to Vk swap chain buffers hold by + // m_pBackBufferRTV[] + pDeviceVk->IdleGPU(); + + // We must wait unitl GPU is idled before destroying semaphores as they + // are destroyed immediately + m_ImageAcquiredSemaphores.clear(); + m_DrawCompleteSemaphores.clear(); + m_SemaphoreIndex = 0; + + CreateVulkanSwapChain(); + InitBuffersAndViews(); +} + void SwapChainVkImpl::Resize( Uint32 NewWidth, Uint32 NewHeight ) { if( TSwapChainBase::Resize(NewWidth, NewHeight) ) @@ -490,35 +533,17 @@ void SwapChainVkImpl::Resize( Uint32 NewWidth, Uint32 NewHeight ) VERIFY( pDeviceContext, "Immediate context has been released" ); if( pDeviceContext ) { - RenderDeviceVkImpl *pDeviceVk = m_pRenderDevice.RawPtr<RenderDeviceVkImpl>(); pDeviceContext->Flush(); try { - auto *pImmediateCtxVk = pDeviceContext.RawPtr<DeviceContextVkImpl>(); + auto* pImmediateCtxVk = pDeviceContext.RawPtr<DeviceContextVkImpl>(); + // RecreateVulkanSwapchain() unbinds default FB bool bIsDefaultFBBound = pImmediateCtxVk->IsDefaultFBBound(); - if(bIsDefaultFBBound) - pImmediateCtxVk->ResetRenderTargets(); - - // All references to the swap chain must be released before it can be resized - m_pBackBufferRTV.clear(); - m_SwapChainImagesInitialized.clear(); - m_pDepthBufferDSV.Release(); - - // This will release references to Vk swap chain buffers hold by - // m_pBackBufferRTV[] - pDeviceVk->IdleGPU(); - - // We must wait unitl GPU is idled before destroying semaphores as they - // are destroyed immediately - m_ImageAcquiredSemaphores.clear(); - m_DrawCompleteSemaphores.clear(); - m_SemaphoreIndex = 0; - - CreateVulkanSwapChain(); - InitBuffersAndViews(); + RecreateVulkanSwapchain(pImmediateCtxVk); + AcquireNextImage(pImmediateCtxVk); - + if( bIsDefaultFBBound ) { // Set default render target and viewport |
