[Mesa-dev] [RFC v2 3/5] vulkan: Add support for in-fences for vkQueuePresent

Louis-Francis Ratté-Boulianne lfrb at collabora.com
Thu Sep 28 08:25:26 UTC 2017


Allow drivers to add a list of semaphores to wait on
when queuing a image to present.

Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
---
 src/amd/vulkan/radv_wsi.c           |  2 +-
 src/intel/vulkan/anv_wsi.c          |  2 ++
 src/vulkan/wsi/wsi_common.h         |  6 +++++
 src/vulkan/wsi/wsi_common_wayland.c |  2 ++
 src/vulkan/wsi/wsi_common_x11.c     | 50 +++++++++++++++++++++++++++++++++++--
 5 files changed, 59 insertions(+), 3 deletions(-)

diff --git a/src/amd/vulkan/radv_wsi.c b/src/amd/vulkan/radv_wsi.c
index 31448ae981..d73a5766d1 100644
--- a/src/amd/vulkan/radv_wsi.c
+++ b/src/amd/vulkan/radv_wsi.c
@@ -575,7 +575,7 @@ VkResult radv_QueuePresentKHR(
 		if (regions && regions->pRegions)
 			region = &regions->pRegions[i];
 
-		item_result = swapchain->queue_present(swapchain,
+		item_result = swapchain->queue_present(swapchain, NULL, 0,
 						  pPresentInfo->pImageIndices[i],
 						  region);
 		/* TODO: What if one of them returns OUT_OF_DATE? */
diff --git a/src/intel/vulkan/anv_wsi.c b/src/intel/vulkan/anv_wsi.c
index 978a66896f..2e05c3b07b 100644
--- a/src/intel/vulkan/anv_wsi.c
+++ b/src/intel/vulkan/anv_wsi.c
@@ -472,6 +472,8 @@ VkResult anv_QueuePresentKHR(
       anv_QueueSubmit(_queue, 0, NULL, swapchain->fences[0]);
 
       item_result = swapchain->queue_present(swapchain,
+                                             NULL,
+                                             0,
                                              pPresentInfo->pImageIndices[i],
                                              region);
       /* TODO: What if one of them returns OUT_OF_DATE? */
diff --git a/src/vulkan/wsi/wsi_common.h b/src/vulkan/wsi/wsi_common.h
index 99836054ca..e81c7be11a 100644
--- a/src/vulkan/wsi/wsi_common.h
+++ b/src/vulkan/wsi/wsi_common.h
@@ -57,6 +57,10 @@ struct wsi_image_fns {
    void (*free_wsi_image)(VkDevice device,
                           const VkAllocationCallbacks *pAllocator,
                           struct wsi_image_base *image);
+   VkResult (*get_semaphores_fd)(VkDevice device,
+                                 const VkSemaphore *semaphores,
+                                 uint32_t semaphore_count,
+                                 int *fd);
 };
 
 struct wsi_swapchain {
@@ -79,6 +83,8 @@ struct wsi_swapchain {
                                   uint64_t timeout, VkSemaphore semaphore,
                                   uint32_t *image_index);
    VkResult (*queue_present)(struct wsi_swapchain *swap_chain,
+                             const VkSemaphore *semaphores,
+                             uint32_t semaphore_count,
                              uint32_t image_index,
                              const VkPresentRegionKHR *damage);
    void (*get_image_and_linear)(struct wsi_swapchain *swapchain,
diff --git a/src/vulkan/wsi/wsi_common_wayland.c b/src/vulkan/wsi/wsi_common_wayland.c
index b4dd2d7ff0..6cafa8f178 100644
--- a/src/vulkan/wsi/wsi_common_wayland.c
+++ b/src/vulkan/wsi/wsi_common_wayland.c
@@ -720,6 +720,8 @@ static const struct wl_callback_listener frame_listener = {
 
 static VkResult
 wsi_wl_swapchain_queue_present(struct wsi_swapchain *wsi_chain,
+                               const VkSemaphore *semaphores,
+                               uint32_t semaphore_count,
                                uint32_t image_index,
                                const VkPresentRegionKHR *damage)
 {
diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c
index d9467092d2..1179eed9c7 100644
--- a/src/vulkan/wsi/wsi_common_x11.c
+++ b/src/vulkan/wsi/wsi_common_x11.c
@@ -654,6 +654,7 @@ struct x11_image {
    xcb_pixmap_t                              pixmap;
    bool                                      busy;
    struct xshmfence *                        shm_fence;
+   uint32_t                                  wait_fence;
    uint32_t                                  sync_fence;
 };
 
@@ -745,6 +746,14 @@ x11_handle_dri3_present_event(struct x11_swapchain *chain,
       for (unsigned i = 0; i < chain->base.image_count; i++) {
          if (chain->images[i].pixmap == idle->pixmap) {
             chain->images[i].busy = false;
+            if (chain->images[i].wait_fence) {
+               xcb_void_cookie_t cookie;
+
+               cookie = xcb_sync_destroy_fence(chain->conn, chain->images[i].wait_fence);
+               xcb_discard_reply(chain->conn, cookie.sequence);
+               xcb_flush(chain->conn);
+               chain->images[i].wait_fence = 0;
+            }
             if (chain->threaded)
                wsi_queue_push(&chain->acquire_queue, i);
             break;
@@ -907,13 +916,14 @@ x11_present_to_x11(struct x11_swapchain *chain, uint32_t image_index,
                          0,                                    /* x_off */
                          0,                                    /* y_off */
                          XCB_NONE,                             /* target_crtc */
-                         XCB_NONE,
+                         image->wait_fence,
                          image->sync_fence,
                          options,
                          target_msc,
                          divisor,
                          remainder, 0, NULL);
    xcb_discard_reply(chain->conn, cookie.sequence);
+
    image->busy = true;
 
    xcb_flush(chain->conn);
@@ -945,11 +955,39 @@ x11_acquire_next_image(struct wsi_swapchain *anv_chain,
 
 static VkResult
 x11_queue_present(struct wsi_swapchain *anv_chain,
+                  const VkSemaphore *semaphores,
+                  uint32_t semaphore_count,
                   uint32_t image_index,
                   const VkPresentRegionKHR *damage)
 {
    struct x11_swapchain *chain = (struct x11_swapchain *)anv_chain;
    VkResult result;
+   struct x11_image *image = &chain->images[image_index];
+
+#if XCB_DRI3_MAJOR_VERSION > 1 || XCB_DRI3_MINOR_VERSION >= 2
+   if (chain->has_dma_fence) {
+      int merged_fence_fd = -1;
+      VkResult ret;
+
+      ret = chain->base.image_fns->get_semaphores_fd(anv_chain->device,
+                                                     semaphores,
+                                                     semaphore_count,
+                                                     &merged_fence_fd);
+      if (ret != VK_SUCCESS) {
+         return ret;
+      }
+
+      if (merged_fence_fd > -1) {
+         image->wait_fence = xcb_generate_id(chain->conn);
+         xcb_dri3_fence_from_dma_fence_fd(chain->conn,
+                                          image->pixmap,
+                                          image->wait_fence,
+                                          merged_fence_fd);
+         xcb_flush(chain->conn);
+         close(merged_fence_fd);
+      }
+   }
+#endif
 
    if (chain->threaded) {
       wsi_queue_push(&chain->present_queue, image_index);
@@ -1118,6 +1156,9 @@ x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
    if (chain->has_present_v1_2 && chain->has_dri3_v1_2)
       wsi_x11_get_present_capabilities(chain);
 
+   image->wait_fence = 0;
+   image->busy = false;
+
    int fence_fd = xshmfence_alloc_shm();
    if (fence_fd < 0)
       goto fail_pixmap;
@@ -1133,7 +1174,6 @@ x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
                           false,
                           fence_fd);
 
-   image->busy = false;
    xshmfence_trigger(image->shm_fence);
 
    return VK_SUCCESS;
@@ -1161,6 +1201,12 @@ x11_image_finish(struct x11_swapchain *chain,
    xcb_discard_reply(chain->conn, cookie.sequence);
    xshmfence_unmap_shm(image->shm_fence);
 
+   if (image->wait_fence) {
+      cookie = xcb_sync_destroy_fence(chain->conn, image->wait_fence);
+      xcb_discard_reply(chain->conn, cookie.sequence);
+      image->wait_fence = 0;
+   }
+
    cookie = xcb_free_pixmap(chain->conn, image->pixmap);
    xcb_discard_reply(chain->conn, cookie.sequence);
 
-- 
2.13.0



More information about the mesa-dev mailing list