From 2f540283b352544f60cfadd226967bf818a33b59 Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Wed, 11 Mar 2026 22:21:19 +0800 Subject: [PATCH] vulkan/wsi/headless: properly cleanup swapchain init failure Currently the wsi_headless_surface_create_swapchain() function abuses the corresponding destroy function to perform cleanup operations when any failure happens during images creation. This practice sounds fragile and prevents further changes to the swapchain creation procedure. Implement a proper cleanup sequence to reverse all operations. As another cleanup codepath above already contains call of vk_free(), the call is changed to a goto targetting the corresponding label. Regression tested with `dEQP-VK.wsi.headless.swapchain.simulate_oom.*` on RADV. Signed-off-by: Icenowy Zheng Reviewed-by: Yiwei Zhang Part-of: --- src/vulkan/wsi/wsi_common_headless.c | 30 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/vulkan/wsi/wsi_common_headless.c b/src/vulkan/wsi/wsi_common_headless.c index 347b7c224c0..1e2f9886b0b 100644 --- a/src/vulkan/wsi/wsi_common_headless.c +++ b/src/vulkan/wsi/wsi_common_headless.c @@ -491,10 +491,8 @@ wsi_headless_surface_create_swapchain(VkIcdSurfaceBase *icd_surface, STACK_ARRAY_FINISH(mods); STACK_ARRAY_FINISH(mod_props); - if (result != VK_SUCCESS) { - vk_free(pAllocator, chain); - return result; - } + if (result != VK_SUCCESS) + goto fail_free_chain; chain->base.destroy = wsi_headless_swapchain_destroy; chain->base.get_wsi_image = wsi_headless_swapchain_get_wsi_image; @@ -504,25 +502,27 @@ wsi_headless_surface_create_swapchain(VkIcdSurfaceBase *icd_surface, chain->base.present_mode = wsi_swapchain_get_present_mode(wsi_device, pCreateInfo); chain->base.image_count = num_images; - for (uint32_t i = 0; i < chain->base.image_count; i++) { + uint32_t image = 0; + for (; image < chain->base.image_count; image++) { result = wsi_create_image(&chain->base, &chain->base.image_info, - &chain->images[i].base); - if (result != VK_SUCCESS) { - /* Record how many images need to be torn down */ - chain->base.image_count = i; - goto fail; - } + &chain->images[image].base); + if (result != VK_SUCCESS) + goto fail_destroy_images; - chain->images[i].busy_on_host = false; - chain->images[i].busy_on_device = false; + chain->images[image].busy_on_host = false; + chain->images[image].busy_on_device = false; } *swapchain_out = &chain->base; return VK_SUCCESS; -fail: - wsi_headless_swapchain_destroy(&chain->base, pAllocator); +fail_destroy_images: + for (uint32_t i = 0; i < image; i++) + wsi_destroy_image(&chain->base, &chain->images[i].base); + wsi_swapchain_finish(&chain->base); +fail_free_chain: + vk_free(pAllocator, chain); return result; }