From 6ac8ac38f12c05e143e89c6c856978ba68b0a08a Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Fri, 8 Aug 2025 10:45:07 -0700 Subject: [PATCH] vulkan/wsi/headless: acquire the most likely idle image Previously the present marks the image free, and the next acquire would immediately acquire the just presented image back, which likely still has pending gpu work going on. To avoid introducing a present queue in headless, we simply tweak to acquire swapchain images in a loop to give the app the most likely idle image. Reviewed-by: Lionel Landwerlin Part-of: --- src/vulkan/wsi/wsi_common_headless.c | 29 +++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/vulkan/wsi/wsi_common_headless.c b/src/vulkan/wsi/wsi_common_headless.c index a3510cce5bd..e7ceb24034a 100644 --- a/src/vulkan/wsi/wsi_common_headless.c +++ b/src/vulkan/wsi/wsi_common_headless.c @@ -241,7 +241,18 @@ wsi_headless_surface_get_present_rectangles(VkIcdSurfaceBase *surface, struct wsi_headless_image { struct wsi_image base; - bool busy; + + /* whether the host side ownership is taken by the app or the display */ + bool busy_on_host; + + /* whether the image may still be worked on by the device + * + * The headless display does not involve a presentation queue to wait for + * the gpu out-fence. To let the app acquire the most likely idle image, we + * use a second boolean to steer the app to acquire all the swapchain images + * in a loop. + */ + bool busy_on_device; }; struct wsi_headless_swapchain { @@ -278,10 +289,17 @@ wsi_headless_swapchain_acquire_next_image(struct wsi_swapchain *wsi_chain, while (1) { /* Try to find a free image. */ for (uint32_t i = 0; i < chain->base.image_count; i++) { - if (!chain->images[i].busy) { + if (!chain->images[i].busy_on_host) { + if (chain->images[i].busy_on_device) { + /* simple trick to avoid the just presented image */ + chain->images[i].busy_on_device = false; + continue; + } + /* We found a non-busy image */ *image_index = i; - chain->images[i].busy = true; + chain->images[i].busy_on_host = true; + chain->images[i].busy_on_device = true; return VK_SUCCESS; } } @@ -305,7 +323,7 @@ wsi_headless_swapchain_queue_present(struct wsi_swapchain *wsi_chain, assert(image_index < chain->base.image_count); - chain->images[image_index].busy = false; + chain->images[image_index].busy_on_host = false; return VK_SUCCESS; } @@ -501,7 +519,8 @@ wsi_headless_surface_create_swapchain(VkIcdSurfaceBase *icd_surface, if (result != VK_SUCCESS) goto fail; - chain->images[i].busy = false; + chain->images[i].busy_on_host = false; + chain->images[i].busy_on_device = false; } *swapchain_out = &chain->base;