VulkanHostDisplay: Handle surface loss gracefully

Also skips a full swap chain recreate on resize.
This commit is contained in:
Connor McLaughlin 2021-04-08 03:03:12 +10:00
parent 0342d0a26e
commit 19ca102b40
2 changed files with 22 additions and 7 deletions

View file

@ -723,13 +723,15 @@ void SwapChain::DestroySwapChain()
VkResult SwapChain::AcquireNextImage() VkResult SwapChain::AcquireNextImage()
{ {
if (!m_swap_chain)
return VK_ERROR_SURFACE_LOST_KHR;
return vkAcquireNextImageKHR(g_vulkan_context->GetDevice(), m_swap_chain, UINT64_MAX, m_image_available_semaphore, return vkAcquireNextImageKHR(g_vulkan_context->GetDevice(), m_swap_chain, UINT64_MAX, m_image_available_semaphore,
VK_NULL_HANDLE, &m_current_image); VK_NULL_HANDLE, &m_current_image);
} }
bool SwapChain::ResizeSwapChain(u32 new_width /* = 0 */, u32 new_height /* = 0 */) bool SwapChain::ResizeSwapChain(u32 new_width /* = 0 */, u32 new_height /* = 0 */)
{ {
DestroySemaphores();
DestroySwapChainImages(); DestroySwapChainImages();
if (new_width != 0 && new_height != 0) if (new_width != 0 && new_height != 0)
@ -738,7 +740,7 @@ bool SwapChain::ResizeSwapChain(u32 new_width /* = 0 */, u32 new_height /* = 0 *
m_window_info.surface_height = new_height; m_window_info.surface_height = new_height;
} }
if (!CreateSwapChain() || !SetupSwapChainImages() || !CreateSemaphores()) if (!CreateSwapChain() || !SetupSwapChainImages())
{ {
Panic("Failed to re-configure swap chain images, this is fatal (for now)"); Panic("Failed to re-configure swap chain images, this is fatal (for now)");
return false; return false;
@ -749,10 +751,9 @@ bool SwapChain::ResizeSwapChain(u32 new_width /* = 0 */, u32 new_height /* = 0 *
bool SwapChain::RecreateSwapChain() bool SwapChain::RecreateSwapChain()
{ {
DestroySemaphores();
DestroySwapChainImages(); DestroySwapChainImages();
DestroySwapChain();
if (!CreateSwapChain() || !SetupSwapChainImages() || !CreateSemaphores()) if (!CreateSwapChain() || !SetupSwapChainImages())
{ {
Panic("Failed to re-configure swap chain images, this is fatal (for now)"); Panic("Failed to re-configure swap chain images, this is fatal (for now)");
return false; return false;
@ -774,7 +775,6 @@ bool SwapChain::SetVSync(bool enabled)
bool SwapChain::RecreateSurface(const WindowInfo& new_wi) bool SwapChain::RecreateSurface(const WindowInfo& new_wi)
{ {
// Destroy the old swap chain, images, and surface. // Destroy the old swap chain, images, and surface.
DestroySemaphores();
DestroySwapChainImages(); DestroySwapChainImages();
DestroySwapChain(); DestroySwapChain();
DestroySurface(); DestroySurface();
@ -803,7 +803,7 @@ bool SwapChain::RecreateSurface(const WindowInfo& new_wi)
} }
// Finally re-create the swap chain // Finally re-create the swap chain
if (!CreateSwapChain() || !SetupSwapChainImages() || !CreateSemaphores()) if (!CreateSwapChain() || !SetupSwapChainImages())
return false; return false;
return true; return true;
@ -811,6 +811,9 @@ bool SwapChain::RecreateSurface(const WindowInfo& new_wi)
void SwapChain::DestroySurface() void SwapChain::DestroySurface()
{ {
if (m_surface == VK_NULL_HANDLE)
return;
DestroyVulkanSurface(g_vulkan_context->GetVulkanInstance(), &m_window_info, m_surface); DestroyVulkanSurface(g_vulkan_context->GetVulkanInstance(), &m_window_info, m_surface);
m_surface = VK_NULL_HANDLE; m_surface = VK_NULL_HANDLE;
} }

View file

@ -580,6 +580,18 @@ bool VulkanHostDisplay::Render()
ResizeRenderWindow(0, 0); ResizeRenderWindow(0, 0);
res = m_swap_chain->AcquireNextImage(); res = m_swap_chain->AcquireNextImage();
} }
else if (res == VK_ERROR_SURFACE_LOST_KHR)
{
Log_WarningPrint("Surface lost, attempting to recreate");
if (!m_swap_chain->RecreateSurface(m_window_info))
{
Log_ErrorPrint("Failed to recreate surface after loss");
g_vulkan_context->ExecuteCommandBuffer(false);
return false;
}
res = m_swap_chain->AcquireNextImage();
}
// This can happen when multiple resize events happen in quick succession. // This can happen when multiple resize events happen in quick succession.
// In this case, just wait until the next frame to try again. // In this case, just wait until the next frame to try again.