diff --git a/src/vulkan/wsi/wsi_common.c b/src/vulkan/wsi/wsi_common.c index cf83ca42da0..9590b70dfbd 100644 --- a/src/vulkan/wsi/wsi_common.c +++ b/src/vulkan/wsi/wsi_common.c @@ -1526,6 +1526,10 @@ wsi_common_queue_present(const struct wsi_device *wsi, image->acquired = false; image->present_serial = ++swapchain->present_serial; + /* If we updated the signal_dma_buf semaphore, extract its syncobj and + * attach it to the dma-buf before we present so that the present + * implicitly syncs on it. + */ if (!explicit_sync) { #ifdef HAVE_LIBDRM if (has_signal_dma_buf) { diff --git a/src/vulkan/wsi/wsi_common_display.c b/src/vulkan/wsi/wsi_common_display.c index 0f24e05586a..f1a425129bb 100644 --- a/src/vulkan/wsi/wsi_common_display.c +++ b/src/vulkan/wsi/wsi_common_display.c @@ -1743,6 +1743,11 @@ wsi_display_get_wsi_image(struct wsi_swapchain *drv_chain, return &chain->images[image_index].base; } +/** + * Marks the old image as idle after a pageflip event has indicated that we've + * flipped to the new image and are no longer scanning out from the previous + * image. + */ static void wsi_display_idle_old_displaying(struct wsi_display_image *active_image) { @@ -1762,6 +1767,10 @@ wsi_display_idle_old_displaying(struct wsi_display_image *active_image) static VkResult _wsi_display_queue_next(struct wsi_swapchain *drv_chain); +/** + * Wakes up any vkWaitForPresentKHR() waiters on the last present to this + * image. + */ static void wsi_display_present_complete(struct wsi_display_swapchain *swapchain, struct wsi_display_image *image) @@ -1803,6 +1812,8 @@ wsi_display_page_flip_handler2(int fd, wsi_display_present_complete(chain, image); wsi_display_idle_old_displaying(image); + + /* Send the next queued atomic commit now that one has completed. */ VkResult result = _wsi_display_queue_next(&(chain->base)); if (result != VK_SUCCESS) chain->status = result; diff --git a/src/vulkan/wsi/wsi_common_drm.c b/src/vulkan/wsi/wsi_common_drm.c index 663820ce092..d4013ed51a4 100644 --- a/src/vulkan/wsi/wsi_common_drm.c +++ b/src/vulkan/wsi/wsi_common_drm.c @@ -152,6 +152,13 @@ wsi_prepare_signal_dma_buf_from_semaphore(struct wsi_swapchain *chain, return result; } +/** + * Imports the dma_buf_semaphore's syncobj into the dmabuf so that display + * implicit sync waits on it. + * + * Note that this operation adds this sync point to the implicit fencing of the + * dma buf, rather than completely replacing it. + */ VkResult wsi_signal_dma_buf_from_semaphore(const struct wsi_swapchain *chain, const struct wsi_image *image) @@ -190,6 +197,9 @@ get_sync_file_sync_type(struct vk_device *device, return NULL; } +/* Extracts a syncobj from a dma-buf into a vk_sync, for the purpose of creating + * the AcquireNextImage fence/semaphores. + */ VkResult wsi_create_sync_for_dma_buf_wait(const struct wsi_swapchain *chain, const struct wsi_image *image, @@ -338,6 +348,10 @@ done: return result; } +/** + * Merges the explicit sync acquire/release timeline points for the image into + * vk_sync, for the purpose of creating the AcquireNextImage fence/semaphores. + */ VkResult wsi_create_sync_for_image_syncobj(const struct wsi_swapchain *chain, const struct wsi_image *image, diff --git a/src/vulkan/wsi/wsi_common_private.h b/src/vulkan/wsi/wsi_common_private.h index badfb3b9cad..d523202fcda 100644 --- a/src/vulkan/wsi/wsi_common_private.h +++ b/src/vulkan/wsi/wsi_common_private.h @@ -64,6 +64,7 @@ struct wsi_drm_image_params { struct wsi_base_image_params base; bool same_gpu; + /* See wsi_image_info.explicit_sync. */ bool explicit_sync; uint32_t num_modifier_lists; @@ -88,7 +89,20 @@ struct wsi_image_info { VkColorSpaceKHR color_space; enum wsi_image_type image_type; + + /** + * If set, the WSI backend and the WSI device support timeline-based explicit + * synchronization. The device check requires non-emulated timeline + * semaphores, so they can be exported as an opaque fd. + * + * The present will take in the explicit_sync[WSI_ES_ACQUIRE] timeline point + * and not present until that completes, and sets up the + * explicit_sync[WSI_ES_RELEASE] timeline point for when the image is done + * being used by the compositor (whether that's a GPU composite completing, + * or the scanned-out frame being flipped away from). + */ bool explicit_sync; + bool prime_use_linear_modifier; /* Not really part of VkImageCreateInfo but needed to figure out the @@ -119,7 +133,9 @@ struct wsi_image_info { enum wsi_explicit_sync_timelines { + /** Timeline point that must be passed before the display can start reading from the image */ WSI_ES_ACQUIRE, + /** Timeline point that indicates that the display is done reading from this image. */ WSI_ES_RELEASE, WSI_ES_COUNT, @@ -184,9 +200,23 @@ struct wsi_swapchain { VkAllocationCallbacks alloc; VkFence* fences; VkPresentModeKHR present_mode; + /** + * Timeline for presents completing according to VK_KHR_present_wait. The + * present should complete as close as possible (before or after!) to the + * first pixel being scanned out. + */ VkSemaphore present_id_timeline; int signal_dma_buf_from_semaphore; + /** + * Optional semaphore for implicit-sync swapchains. It will be signaled by + * the pre-present vkQueueSubmit, and its syncobj will get imported into the + * image's dma-buf before being presented. + * + * If not set (due to older kernels missing sync-file import/export), for + * implicit-sync swapchains, then you have to support + * create_sync_for_memory(). + */ VkSemaphore dma_buf_semaphore; struct wsi_image_info image_info;