From db9dbcbec0002ed87e825927983b841d1e90f163 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Wed, 15 Oct 2025 12:25:38 -0400 Subject: [PATCH] zink: defer swapchain updates for interval changes if acquired image is active in the case where an app triggers a swap interval change mid-frame, this handling previously triggered an immediate swapchain retire and then presented the new swapchain which had yet to be rendered to instead, defer swapchain updates to immediately after present when things are safe to ensure that the right image is always presented Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/14104 cc: mesa-stable Part-of: --- src/gallium/drivers/zink/zink_kopper.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/gallium/drivers/zink/zink_kopper.c b/src/gallium/drivers/zink/zink_kopper.c index b8c9330cd6f..7d563c55aae 100644 --- a/src/gallium/drivers/zink/zink_kopper.c +++ b/src/gallium/drivers/zink/zink_kopper.c @@ -931,6 +931,12 @@ zink_kopper_present_queue(struct zink_screen *screen, struct zink_resource *res, memset(&res->damage, 0, sizeof(res->damage)); cdt->swapchain->images[res->obj->dt_idx].acquired = NULL; res->obj->dt_idx = UINT32_MAX; + /* pick up pending present mode updates here */ + if (cdt->present_mode != cdt->swapchain->scci.presentMode) { + VkResult ret = update_swapchain(screen, cdt, cdt->caps.currentExtent.width, cdt->caps.currentExtent.height); + if (ret != VK_SUCCESS) + mesa_loge("zink: failed to set swap interval!"); + } } void @@ -1202,11 +1208,13 @@ zink_kopper_set_swap_interval(struct pipe_screen *pscreen, struct pipe_resource if (old_present_mode == cdt->present_mode) return; - VkResult ret = update_swapchain(screen, cdt, cdt->caps.currentExtent.width, cdt->caps.currentExtent.height); - if (ret == VK_SUCCESS) - return; cdt->present_mode = old_present_mode; - mesa_loge("zink: failed to set swap interval!"); + if (res->obj->dt_idx == UINT32_MAX) { + /* only update swapchain when there is no current acquire to avoid flickering */ + VkResult ret = update_swapchain(screen, cdt, cdt->caps.currentExtent.width, cdt->caps.currentExtent.height); + if (ret != VK_SUCCESS) + mesa_loge("zink: failed to set swap interval!"); + } } int