[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