[Mesa-dev] [PATCH] vulkan/wsi/wayland: Implement explicit fencing

Daniel Stone daniels at collabora.com
Tue Sep 19 23:51:55 UTC 2017


Signed-off-by: Daniel Stone <daniels at collabora.com>
---
 src/vulkan/Makefile.am              |  10 ++++
 src/vulkan/Makefile.sources         |   4 +-
 src/vulkan/wsi/wsi_common_wayland.c | 100 ++++++++++++++++++++++++++++++++++--
 3 files changed, 110 insertions(+), 4 deletions(-)

diff --git a/src/vulkan/Makefile.am b/src/vulkan/Makefile.am
index da692b6be5..93cc8b30bf 100644
--- a/src/vulkan/Makefile.am
+++ b/src/vulkan/Makefile.am
@@ -76,6 +76,16 @@ wsi/linux-dmabuf-unstable-v1-client-protocol.h : $(WL_DMABUF_XML)
 	$(MKDIR_GEN)
 	$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
 
+WL_SYNC_XML = $(WAYLAND_PROTOCOLS_DATADIR)/unstable/linux-explicit-synchronization/linux-explicit-synchronization-unstable-v1.xml
+
+wsi/linux-explicit-synchronization-unstable-v1-protocol.c : $(WL_SYNC_XML)
+	$(MKDIR_GEN)
+	$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
+
+wsi/linux-explicit-synchronization-unstable-v1-client-protocol.h : $(WL_SYNC_XML)
+	$(MKDIR_GEN)
+	$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
+
 if HAVE_PLATFORM_WAYLAND
 AM_CPPFLAGS += \
 	-I$(top_builddir)/src/vulkan/wsi \
diff --git a/src/vulkan/Makefile.sources b/src/vulkan/Makefile.sources
index 95685caab7..bea193f093 100644
--- a/src/vulkan/Makefile.sources
+++ b/src/vulkan/Makefile.sources
@@ -11,7 +11,9 @@ VULKAN_WSI_WAYLAND_GENERATED_FILES := \
 	wsi/wayland-drm-protocol.c \
 	wsi/wayland-drm-client-protocol.h \
 	wsi/linux-dmabuf-unstable-v1-protocol.c \
-	wsi/linux-dmabuf-unstable-v1-client-protocol.h
+	wsi/linux-dmabuf-unstable-v1-client-protocol.h \
+	wsi/linux-explicit-synchronization-unstable-v1-protocol.c \
+	wsi/linux-explicit-synchronization-unstable-v1-client-protocol.h
 
 VULKAN_WSI_X11_FILES := \
 	wsi/wsi_common_x11.c \
diff --git a/src/vulkan/wsi/wsi_common_wayland.c b/src/vulkan/wsi/wsi_common_wayland.c
index b4c65836d3..e295c13846 100644
--- a/src/vulkan/wsi/wsi_common_wayland.c
+++ b/src/vulkan/wsi/wsi_common_wayland.c
@@ -37,6 +37,7 @@
 #include "wsi_common_wayland.h"
 #include "wayland-drm-client-protocol.h"
 #include "linux-dmabuf-unstable-v1-client-protocol.h"
+#include "linux-explicit-synchronization-unstable-v1-client-protocol.h"
 
 #include <util/hash_table.h>
 #include <util/u_vector.h>
@@ -56,6 +57,7 @@ struct wsi_wl_display {
    struct wl_event_queue *                      queue;
    struct wl_drm *                              drm;
    struct zwp_linux_dmabuf_v1 *                 dmabuf;
+   struct zwp_linux_explicit_synchronization_v1 *explicit_sync;
 
    struct wsi_wayland *wsi_wl;
    /* Vector of VkFormats supported */
@@ -293,6 +295,10 @@ registry_handle_global(void *data, struct wl_registry *registry,
          wl_registry_bind(registry, name, &zwp_linux_dmabuf_v1_interface, 3);
       zwp_linux_dmabuf_v1_add_listener(display->dmabuf, &dmabuf_listener,
                                        display);
+   } else if (strcmp(interface, "zwp_linux_explicit_synchronization_v1") == 0) {
+      display->explicit_sync =
+         wl_registry_bind(registry, name,
+		          &zwp_linux_explicit_synchronization_v1_interface, 1);
    }
 }
 
@@ -586,6 +592,8 @@ struct wsi_wl_image {
    struct wsi_image_base                        base;
    struct wl_buffer *                           buffer;
    bool                                         busy;
+   struct zwp_buffer_release_v1 *               release;
+   int                                          release_fd;
 };
 
 struct wsi_wl_swapchain {
@@ -597,6 +605,7 @@ struct wsi_wl_swapchain {
    uint32_t                                     surface_version;
    struct wl_drm *                              drm_wrapper;
    struct wl_callback *                         frame;
+   struct zwp_surface_synchronization_v1 *      surface_sync;
 
    VkExtent2D                                   extent;
    VkFormat                                     vk_format;
@@ -634,6 +643,36 @@ wsi_wl_swapchain_get_images(struct wsi_swapchain *wsi_chain,
    return result;
 }
 
+static void buffer_release_fenced(void *data,
+                                  struct zwp_buffer_release_v1 *release,
+                                  int fence_fd)
+{
+   struct wsi_wl_image *image = data;
+
+   image->release_fd = fence_fd;
+
+   zwp_buffer_release_v1_destroy(release);
+   image->release = NULL;
+
+   image->busy = false;
+}
+
+static void buffer_release_immed(void *data,
+                                 struct zwp_buffer_release_v1 *release)
+{
+   struct wsi_wl_image *image = data;
+
+   zwp_buffer_release_v1_destroy(release);
+   image->release = NULL;
+
+   image->busy = false;
+}
+
+static const struct zwp_buffer_release_v1_listener release_listener = {
+   buffer_release_fenced,
+   buffer_release_immed,
+};
+
 static VkResult
 wsi_wl_swapchain_acquire_next_image(struct wsi_swapchain *wsi_chain,
                                     uint64_t timeout,
@@ -654,10 +693,21 @@ wsi_wl_swapchain_acquire_next_image(struct wsi_swapchain *wsi_chain,
    while (1) {
       for (uint32_t i = 0; i < chain->base.image_count; i++) {
          if (!chain->images[i].busy) {
+            int ret = VK_SUCCESS;
+
             /* We found a non-busy image */
             *image_index = i;
             chain->images[i].busy = true;
-            return VK_SUCCESS;
+
+	    if (chain->images[i].release_fd >= 0) {
+               ret =
+                  chain->base.image_fns->import_semaphore_fd(wsi_chain->device,
+                                                             semaphore,
+                                                             chain->images[i].release_fd);
+               chain->images[i].release_fd = -1;
+            }
+
+            return ret;
          }
       }
 
@@ -704,6 +754,31 @@ wsi_wl_swapchain_queue_present(struct wsi_swapchain *wsi_chain,
       }
    }
 
+   if (chain->surface_sync) {
+      struct wsi_wl_image *image = &chain->images[image_index];
+      int ret, merged_fence_fd;
+
+      ret = chain->base.image_fns->get_semaphores_fd(wsi_chain->device,
+                                                     semaphores,
+                                                     semaphore_count,
+                                                     &merged_fence_fd);
+      if (ret != VK_SUCCESS)
+         return VK_SUCCESS;
+
+      if (merged_fence_fd >= 0) {
+         zwp_surface_synchronization_v1_set_acquire_fence(chain->surface_sync,
+                                                          merged_fence_fd);
+         close(merged_fence_fd);
+      }
+
+      image->release =
+         zwp_surface_synchronization_v1_get_release(chain->surface_sync);
+      wl_proxy_set_queue((struct wl_proxy *) image->release, chain->queue);
+      zwp_buffer_release_v1_add_listener(image->release,
+                                         &release_listener,
+                                         &chain->images[image_index]);
+   }
+
    assert(image_index < chain->base.image_count);
    wl_surface_attach(chain->surface, chain->images[image_index].buffer, 0, 0);
 
@@ -740,7 +815,10 @@ buffer_handle_release(void *data, struct wl_buffer *buffer)
 
    assert(image->buffer == buffer);
 
-   image->busy = false;
+   /* If we're using explicit synchronization with the compositor, we wait for
+    * an explictly-fenced release event instead. */
+   if (!image->release)
+      image->busy = false;
 }
 
 static const struct wl_buffer_listener buffer_listener = {
@@ -851,10 +929,17 @@ wsi_wl_swapchain_destroy(struct wsi_swapchain *wsi_chain,
          chain->base.image_fns->free_wsi_image(chain->base.device, pAllocator,
                                                &chain->images[i].base);
       }
+
+      if (chain->images[i].release)
+         zwp_buffer_release_v1_destroy(chain->images[i].release);
+      if (chain->images[i].release_fd >= 0)
+         close(chain->images[i].release_fd);
    }
 
    if (chain->frame)
       wl_callback_destroy(chain->frame);
+   if (chain->surface_sync)
+      zwp_surface_synchronization_v1_destroy(chain->surface_sync);
    if (chain->surface)
       wl_proxy_wrapper_destroy(chain->surface);
    if (chain->drm_wrapper)
@@ -894,8 +979,11 @@ wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
    /* Mark a bunch of stuff as NULL.  This way we can just call
     * destroy_swapchain for cleanup.
     */
-   for (uint32_t i = 0; i < num_images; i++)
+   for (uint32_t i = 0; i < num_images; i++) {
       chain->images[i].buffer = NULL;
+      chain->images[i].release = NULL;
+      chain->images[i].release_fd = -1;
+   }
    chain->queue = NULL;
    chain->surface = NULL;
    chain->drm_wrapper = NULL;
@@ -944,6 +1032,12 @@ wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
    }
    wl_proxy_set_queue((struct wl_proxy *) chain->drm_wrapper, chain->queue);
 
+   if (chain->display->explicit_sync) {
+      chain->surface_sync =
+         zwp_linux_explicit_synchronization_v1_get_synchronization(chain->display->explicit_sync,
+                                                                   chain->surface);
+   }
+
    chain->fifo_ready = true;
 
    for (uint32_t i = 0; i < chain->base.image_count; i++) {
-- 
2.14.1



More information about the mesa-dev mailing list