From 7a3c6b77ef48f92eccaff5d6b1fc2e4d73509a78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Do=C4=9Fukan=20Korkmazt=C3=BCrk?= Date: Mon, 29 Apr 2024 13:53:25 -0400 Subject: [PATCH] vulkan: Recreate swapchain when it is necessary or beneficial Currently, GTK does not check the result of vkAcquireNextImageKHR() and assumes that it always succeeds. As a result, the vkQueuePresentKHR() is unconditionally set to wait for the semaphore passed to vkAcquireNextImageKHR() earlier. However, if vkAcquireNextImageKHR() fails for some reason, the semaphore passed to it does not get signalled. This causes the presentation command to wait for the semaphore to be signalled indefinitely, which causes GTK to hang. This change adds error handling around vkAcquireNextImageKHR() to make GTK recreate the Vulkan swapchain when it is necessary or beneficial and helps avoiding situations that could cause indefinite waits. --- gdk/gdkvulkancontext.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/gdk/gdkvulkancontext.c b/gdk/gdkvulkancontext.c index 1842c6bf25..048fa57dc3 100644 --- a/gdk/gdkvulkancontext.c +++ b/gdk/gdkvulkancontext.c @@ -628,6 +628,7 @@ gdk_vulkan_context_begin_frame (GdkDrawContext *draw_context, { GdkVulkanContext *context = GDK_VULKAN_CONTEXT (draw_context); GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context); + VkResult acquire_result; guint i; if (depth != priv->current_format) @@ -649,12 +650,29 @@ gdk_vulkan_context_begin_frame (GdkDrawContext *draw_context, cairo_region_union (priv->regions[i], region); } - GDK_VK_CHECK (vkAcquireNextImageKHR, gdk_vulkan_context_get_device (context), - priv->swapchain, - UINT64_MAX, - priv->draw_semaphore, - VK_NULL_HANDLE, - &priv->draw_index); +acquire_next_image: + acquire_result = GDK_VK_CHECK (vkAcquireNextImageKHR, gdk_vulkan_context_get_device (context), + priv->swapchain, + UINT64_MAX, + priv->draw_semaphore, + VK_NULL_HANDLE, + &priv->draw_index); + if ((acquire_result == VK_ERROR_OUT_OF_DATE_KHR) || + (acquire_result == VK_SUBOPTIMAL_KHR)) + { + GError *error = NULL; + + GDK_DEBUG (VULKAN, "Recreating the swapchain"); + + if (!gdk_vulkan_context_check_swapchain (context, &error)) + { + g_warning ("%s", error->message); + g_error_free (error); + return; + } + + goto acquire_next_image; + } cairo_region_union (region, priv->regions[priv->draw_index]); }