}
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;
}
/**
+ * 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
* modes (there is no present-queue in immediate mode with the exception of Xwayland).
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) {