diff --git a/gdk/gdkdisplayprivate.h b/gdk/gdkdisplayprivate.h index 05f57731f5..bc4c861a52 100644 --- a/gdk/gdkdisplayprivate.h +++ b/gdk/gdkdisplayprivate.h @@ -49,10 +49,11 @@ typedef enum { GDK_VULKAN_FEATURE_DMABUF = 1 << 0, GDK_VULKAN_FEATURE_WIN32 = 1 << 1, GDK_VULKAN_FEATURE_YCBCR = 1 << 2, - GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT = 1 << 3, - GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT = 1 << 4, - GDK_VULKAN_FEATURE_INCREMENTAL_PRESENT = 1 << 5, - GDK_VULKAN_FEATURE_SWAPCHAIN_MAINTENANCE = 1 << 6, + GDK_VULKAN_FEATURE_TIMELINE_SEMAPHORE = 1 << 3, + GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT = 1 << 4, + GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT = 1 << 5, + GDK_VULKAN_FEATURE_INCREMENTAL_PRESENT = 1 << 6, + GDK_VULKAN_FEATURE_SWAPCHAIN_MAINTENANCE = 1 << 7, } GdkVulkanFeatures; #define GDK_VULKAN_N_FEATURES 6 diff --git a/gdk/gdkvulkancontext.c b/gdk/gdkvulkancontext.c index 6904b89438..abbcd0ffaf 100644 --- a/gdk/gdkvulkancontext.c +++ b/gdk/gdkvulkancontext.c @@ -39,6 +39,7 @@ const GdkDebugKey gdk_vulkan_feature_keys[] = { { "dmabuf", GDK_VULKAN_FEATURE_DMABUF, "Never import Dmabufs" }, { "win32", GDK_VULKAN_FEATURE_WIN32, "Never import Windows resources" }, { "ycbcr", GDK_VULKAN_FEATURE_YCBCR, "Do not support Ycbcr textures (also disables dmabufs)" }, + { "timeline-semaphore", GDK_VULKAN_FEATURE_TIMELINE_SEMAPHORE, "Disable timeline semaphore support (disables Windows sync)"}, { "semaphore-export", GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT, "Disable sync of exported dmabufs" }, { "semaphore-import", GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT, "Disable sync of imported dmabufs" }, { "incremental-present", GDK_VULKAN_FEATURE_INCREMENTAL_PRESENT, "Do not send damage regions" }, @@ -632,6 +633,9 @@ physical_device_check_features (VkPhysicalDevice device) physical_device_supports_extension (device, VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME)) features |= GDK_VULKAN_FEATURE_DMABUF; + if (physical_device_supports_extension (device, VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME)) + features |= GDK_VULKAN_FEATURE_TIMELINE_SEMAPHORE; + #ifdef GDK_WINDOWING_WIN32 if (physical_device_supports_extension (device, VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME)) features |= GDK_VULKAN_FEATURE_WIN32; @@ -1579,6 +1583,11 @@ gdk_display_create_vulkan_device (GdkDisplay *display, g_ptr_array_add (device_extensions, (gpointer) VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME); g_ptr_array_add (device_extensions, (gpointer) VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME); } + if (features & GDK_VULKAN_FEATURE_TIMELINE_SEMAPHORE) + { + g_ptr_array_add (device_extensions, (gpointer) VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME); + g_ptr_array_add (device_extensions, (gpointer) VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME); + } #ifdef GDK_WINDOWING_WIN32 if (features & GDK_VULKAN_FEATURE_WIN32) { @@ -1589,6 +1598,8 @@ gdk_display_create_vulkan_device (GdkDisplay *display, #endif if (features & (GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT | GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT)) { + if (!(features & GDK_VULKAN_FEATURE_TIMELINE_SEMAPHORE)) + g_ptr_array_add (device_extensions, (gpointer) VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME); g_ptr_array_add (device_extensions, (gpointer) VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME); } if (features & GDK_VULKAN_FEATURE_INCREMENTAL_PRESENT) diff --git a/gsk/gpu/gskvulkanframe.c b/gsk/gpu/gskvulkanframe.c index db65cd97d7..7ed09a2f2b 100644 --- a/gsk/gpu/gskvulkanframe.c +++ b/gsk/gpu/gskvulkanframe.c @@ -18,6 +18,13 @@ #define GDK_ARRAY_NO_MEMSET 1 #include "gdk/gdkarrayimpl.c" +#define GDK_ARRAY_NAME gsk_semaphore_values +#define GDK_ARRAY_TYPE_NAME GskSemaphoreValues +#define GDK_ARRAY_ELEMENT_TYPE uint64_t +#define GDK_ARRAY_PREALLOC 16 +#define GDK_ARRAY_NO_MEMSET 1 +#include "gdk/gdkarrayimpl.c" + #define GDK_ARRAY_NAME gsk_pipeline_stages #define GDK_ARRAY_TYPE_NAME GskPipelineStages #define GDK_ARRAY_ELEMENT_TYPE VkPipelineStageFlags @@ -28,6 +35,7 @@ struct _GskVulkanSemaphores { GskSemaphores wait_semaphores; + GskSemaphoreValues wait_semaphore_values; GskPipelineStages wait_stages; GskSemaphores signal_semaphores; }; @@ -260,9 +268,12 @@ gsk_vulkan_frame_submit (GskGpuFrame *frame, GskGpuOp *op) { GskVulkanFrame *self = GSK_VULKAN_FRAME (frame); + GskVulkanDevice *device; GskVulkanSemaphores semaphores; GskVulkanCommandState state = { 0, }; + device = GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame)); + GSK_VK_CHECK (vkBeginCommandBuffer, self->vk_command_buffer, &(VkCommandBufferBeginInfo) { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, @@ -279,6 +290,7 @@ gsk_vulkan_frame_submit (GskGpuFrame *frame, (VkDeviceSize[1]) { 0 }); gsk_semaphores_init (&semaphores.wait_semaphores); + gsk_semaphore_values_init (&semaphores.wait_semaphore_values); gsk_pipeline_stages_init (&semaphores.wait_stages); gsk_semaphores_init (&semaphores.signal_semaphores); @@ -286,6 +298,7 @@ gsk_vulkan_frame_submit (GskGpuFrame *frame, { gsk_vulkan_semaphores_add_wait (&semaphores, self->vk_acquire_semaphore, + 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); } @@ -302,7 +315,7 @@ gsk_vulkan_frame_submit (GskGpuFrame *frame, GSK_VK_CHECK (vkEndCommandBuffer, self->vk_command_buffer); - GSK_VK_CHECK (vkQueueSubmit, gsk_vulkan_device_get_vk_queue (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame))), + GSK_VK_CHECK (vkQueueSubmit, gsk_vulkan_device_get_vk_queue (device), 1, &(VkSubmitInfo) { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, @@ -313,10 +326,16 @@ gsk_vulkan_frame_submit (GskGpuFrame *frame, .waitSemaphoreCount = gsk_semaphores_get_size (&semaphores.wait_semaphores), .pSignalSemaphores = gsk_semaphores_get_data (&semaphores.signal_semaphores), .signalSemaphoreCount = gsk_semaphores_get_size (&semaphores.signal_semaphores), + .pNext = gsk_vulkan_device_has_feature (device, GDK_VULKAN_FEATURE_TIMELINE_SEMAPHORE) ? &(VkTimelineSemaphoreSubmitInfo) { + .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, + .waitSemaphoreValueCount = gsk_semaphore_values_get_size (&semaphores.wait_semaphore_values), + .pWaitSemaphoreValues = gsk_semaphore_values_get_data (&semaphores.wait_semaphore_values), + } : NULL, }, self->vk_fence); gsk_semaphores_clear (&semaphores.wait_semaphores); + gsk_semaphore_values_clear (&semaphores.wait_semaphore_values); gsk_pipeline_stages_clear (&semaphores.wait_stages); gsk_semaphores_clear (&semaphores.signal_semaphores); } @@ -384,9 +403,11 @@ gsk_vulkan_frame_get_vk_fence (GskVulkanFrame *self) void gsk_vulkan_semaphores_add_wait (GskVulkanSemaphores *self, VkSemaphore semaphore, + guint64 semaphore_wait, VkPipelineStageFlags stage) { gsk_semaphores_append (&self->wait_semaphores, semaphore); + gsk_semaphore_values_append (&self->wait_semaphore_values, semaphore_wait); gsk_pipeline_stages_append (&self->wait_stages, stage); } diff --git a/gsk/gpu/gskvulkanframeprivate.h b/gsk/gpu/gskvulkanframeprivate.h index 8d3995241c..9bb66714ff 100644 --- a/gsk/gpu/gskvulkanframeprivate.h +++ b/gsk/gpu/gskvulkanframeprivate.h @@ -14,6 +14,7 @@ VkFence gsk_vulkan_frame_get_vk_fence (GskVulk void gsk_vulkan_semaphores_add_wait (GskVulkanSemaphores *self, VkSemaphore semaphore, + uint64_t semaphore_wait, VkPipelineStageFlags stage); void gsk_vulkan_semaphores_add_signal (GskVulkanSemaphores *self, VkSemaphore semaphore); diff --git a/gsk/gpu/gskvulkanimage.c b/gsk/gpu/gskvulkanimage.c index f5ffb1a1c6..98178453c5 100644 --- a/gsk/gpu/gskvulkanimage.c +++ b/gsk/gpu/gskvulkanimage.c @@ -34,6 +34,7 @@ struct _GskVulkanImage VkImageView vk_framebuffer_image_view; GskVulkanYcbcr *ycbcr; VkSemaphore vk_semaphore; + uint64_t vk_semaphore_wait; struct { VkDescriptorSet vk_descriptor_set; gsize pool_id; @@ -1501,7 +1502,10 @@ gsk_vulkan_image_transition (GskVulkanImage *self, if (self->vk_pipeline_stage == VK_IMAGE_LAYOUT_GENERAL && self->vk_semaphore) { - gsk_vulkan_semaphores_add_wait (semaphores, self->vk_semaphore, stage); + gsk_vulkan_semaphores_add_wait (semaphores, + self->vk_semaphore, + self->vk_semaphore_wait, + stage); } vkCmdPipelineBarrier (command_buffer,