summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/include/CommandQueueVkImpl.h4
-rw-r--r--Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h3
-rw-r--r--Graphics/GraphicsEngineVulkan/interface/CommandQueueVk.h2
-rw-r--r--Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp5
-rw-r--r--Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp79
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