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

View file

@ -580,6 +580,18 @@ bool VulkanHostDisplay::Render()
ResizeRenderWindow(0, 0);
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.
// In this case, just wait until the next frame to try again.