From a7f44b626943642e0cc0d132dd80aa820a45749f Mon Sep 17 00:00:00 2001 From: Bas Nieuwenhuizen Date: Wed, 23 Feb 2022 02:27:46 +0100 Subject: [PATCH] vulkan/wsi/x11: Ensure we have the required number of images for acquire. For games that needs >1 at the same time the existing check wasn't enough. Cc: mesa-stable Reviewed-by: Hans-Kristian Arntzen Part-of: --- src/vulkan/wsi/wsi_common_x11.c | 39 +++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c index 099735dd9f3..1fc44ea79e7 100644 --- a/src/vulkan/wsi/wsi_common_x11.c +++ b/src/vulkan/wsi/wsi_common_x11.c @@ -612,7 +612,7 @@ x11_surface_get_support(VkIcdSurfaceBase *icd_surface, } static uint32_t -x11_get_min_image_count(struct wsi_device *wsi_device) +x11_get_min_image_count(const struct wsi_device *wsi_device) { if (wsi_device->x11.override_minImageCount) return wsi_device->x11.override_minImageCount; @@ -1431,6 +1431,17 @@ x11_needs_wait_for_fences(const struct wsi_device *wsi_device, } } +/** + * The number of images that are not owned by X11: + * (1) in the ownership of the app, or + * (2) app to take ownership through an acquire, or + * (3) in the present queue waiting for the FIFO thread to present to X11. + */ +static unsigned x11_driver_owned_images(const struct x11_swapchain *chain) +{ + return chain->base.image_count - chain->sent_image_count; +} + /** * Our queue manager. Albeit called x11_manage_fifo_queues only directly * manages the present-queue and does this in general in fifo and mailbox presentation @@ -1502,12 +1513,36 @@ x11_manage_fifo_queues(void *state) xcb_generic_event_t *event = NULL; xcb_connection_t *conn = chain->conn; + /* Assume this isn't a swapchain where we force 5 images, because those + * don't end up with an acquire queue at the moment. + */ + unsigned min_image_count = x11_get_min_image_count(chain->base.wsi); + + /* With drirc overrides some games have swapchain with less than + * minimum number of images. */ + min_image_count = MIN2(min_image_count, chain->base.image_count); + + /* We always need to ensure that the app can have this number of images + * acquired concurrently in between presents: + * "VUID-vkAcquireNextImageKHR-swapchain-01802 + * If the number of currently acquired images is greater than the difference + * between the number of images in swapchain and the value of + * VkSurfaceCapabilitiesKHR::minImageCount as returned by a call to + * vkGetPhysicalDeviceSurfaceCapabilities2KHR with the surface used to + * create swapchain, timeout must not be UINT64_MAX" + */ + unsigned forward_progress_guaranteed_acquired_images = + chain->base.image_count - min_image_count + 1; + /* Wait for our presentation to occur and ensure we have at least one * image that can be acquired by the client afterwards. This ensures we * can pull on the present-queue on the next loop. */ while (chain->images[image_index].present_queued || - chain->sent_image_count == chain->base.image_count) { + /* If we have images in the present queue the outer loop won't block and a break + * here would end up at this loop again, otherwise a break here satisfies + * VUID-vkAcquireNextImageKHR-swapchain-01802 */ + x11_driver_owned_images(chain) < forward_progress_guaranteed_acquired_images) { event = xcb_poll_for_special_event(conn, chain->special_event); if (event) {