Signed-off-by: Daniel Stone <dani...@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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev