diff --git a/gdk/gdkdisplayprivate.h b/gdk/gdkdisplayprivate.h index d02ccb3440..5a3e0e5fa4 100644 --- a/gdk/gdkdisplayprivate.h +++ b/gdk/gdkdisplayprivate.h @@ -47,6 +47,8 @@ typedef enum { GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING = 1 << 2, GDK_VULKAN_FEATURE_DYNAMIC_INDEXING = 1 << 3, GDK_VULKAN_FEATURE_NONUNIFORM_INDEXING = 1 << 4, + GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT = 1 << 5, + GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT = 1 << 6, } GdkVulkanFeatures; /* Tracks information about the device grab on this display */ diff --git a/gdk/gdkvulkancontext.c b/gdk/gdkvulkancontext.c index 7c435199ee..f7ad1a39cf 100644 --- a/gdk/gdkvulkancontext.c +++ b/gdk/gdkvulkancontext.c @@ -39,6 +39,8 @@ static const GdkDebugKey gsk_vulkan_feature_keys[] = { { "descriptor-indexing", GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING, "Force slow descriptor set layout codepath" }, { "dynamic-indexing", GDK_VULKAN_FEATURE_DYNAMIC_INDEXING, "Hardcode small number of buffer and texure arrays" }, { "nonuniform-indexing", GDK_VULKAN_FEATURE_NONUNIFORM_INDEXING, "Split draw calls to ensure uniform texture accesses" }, + { "semaphore-export", GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT, "Disable sync of exported dmabufs" }, + { "semaphore-import", GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT, "Disable sync of imported dmabufs" }, }; #endif @@ -562,8 +564,17 @@ physical_device_check_features (VkPhysicalDevice device, .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, .pNext = &ycbcr_features }; + VkExternalSemaphoreProperties semaphore_props = { + .sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES, + }; vkGetPhysicalDeviceFeatures2 (device, &features); + vkGetPhysicalDeviceExternalSemaphoreProperties (device, + &(VkPhysicalDeviceExternalSemaphoreInfo) { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO, + .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT, + }, + &semaphore_props); *out_features = 0; @@ -591,6 +602,15 @@ physical_device_check_features (VkPhysicalDevice device, physical_device_supports_extension (device, VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME)) *out_features |= GDK_VULKAN_FEATURE_DMABUF; + if (physical_device_supports_extension (device, VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME)) + { + if (semaphore_props.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) + *out_features |= GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT; + + if (semaphore_props.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT) + *out_features |= GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT; + } + return TRUE; } @@ -1450,6 +1470,8 @@ gdk_display_create_vulkan_device (GdkDisplay *display, g_ptr_array_add (device_extensions, (gpointer) VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME); g_ptr_array_add (device_extensions, (gpointer) VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME); } + if (features & (GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT | GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT)) + g_ptr_array_add (device_extensions, (gpointer) VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME); if (physical_device_supports_extension (devices[i], VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME)) g_ptr_array_add (device_extensions, (gpointer) VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME); diff --git a/gsk/gpu/gskgpublitop.c b/gsk/gpu/gskgpublitop.c index 1c7d0821f6..91952e7342 100644 --- a/gsk/gpu/gskgpublitop.c +++ b/gsk/gpu/gskgpublitop.c @@ -59,6 +59,7 @@ gsk_gpu_blit_op_vk_command (GskGpuOp *op, src_layout != VK_IMAGE_LAYOUT_GENERAL) { gsk_vulkan_image_transition (GSK_VULKAN_IMAGE (self->src_image), + state->semaphores, state->vk_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, @@ -72,6 +73,7 @@ gsk_gpu_blit_op_vk_command (GskGpuOp *op, dest_layout != VK_IMAGE_LAYOUT_GENERAL) { gsk_vulkan_image_transition (GSK_VULKAN_IMAGE (self->dest_image), + state->semaphores, state->vk_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, diff --git a/gsk/gpu/gskgpudownloadop.c b/gsk/gpu/gskgpudownloadop.c index bbb5a0a68e..4e95c21974 100644 --- a/gsk/gpu/gskgpudownloadop.c +++ b/gsk/gpu/gskgpudownloadop.c @@ -8,11 +8,17 @@ #include "gskgpuprintprivate.h" #ifdef GDK_RENDERING_VULKAN #include "gskvulkanbufferprivate.h" +#include "gskvulkanframeprivate.h" #include "gskvulkanimageprivate.h" #endif +#include "gdk/gdkdmabuftextureprivate.h" #include "gdk/gdkglcontextprivate.h" +#ifdef HAVE_DMABUF +#include +#endif + typedef struct _GskGpuDownloadOp GskGpuDownloadOp; typedef void (* GdkGpuDownloadOpCreateFunc) (GskGpuDownloadOp *); @@ -28,6 +34,9 @@ struct _GskGpuDownloadOp GdkTexture *texture; GskGpuBuffer *buffer; +#ifdef GDK_RENDERING_VULKAN + VkSemaphore vk_semaphore; +#endif }; static void @@ -59,6 +68,40 @@ gsk_gpu_download_op_print (GskGpuOp *op, } #ifdef GDK_RENDERING_VULKAN +/* The code needs to run here because vkGetSemaphoreFdKHR() may + * only be called after the semaphore has been submitted via + * vkQueueSubmit(). + */ +static void +gsk_gpu_download_op_vk_sync_semaphore (GskGpuDownloadOp *self) +{ + PFN_vkGetSemaphoreFdKHR func_vkGetSemaphoreFdKHR; + GdkDisplay *display; + int fd, sync_file_fd; + + /* Don't look at where I store my variables plz */ + display = gdk_dmabuf_texture_get_display (GDK_DMABUF_TEXTURE (self->texture)); + fd = gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (self->texture))->planes[0].fd; + func_vkGetSemaphoreFdKHR = (PFN_vkGetSemaphoreFdKHR) vkGetDeviceProcAddr (display->vk_device, "vkGetSemaphoreFdKHR"); + + /* vkGetSemaphoreFdKHR implicitly resets the semaphore. + * But who cares, we're about to delete it. */ + if (GSK_VK_CHECK (func_vkGetSemaphoreFdKHR, display->vk_device, + &(VkSemaphoreGetFdInfoKHR) { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR, + .semaphore = self->vk_semaphore, + .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT, + }, + &sync_file_fd) == VK_SUCCESS) + { + gdk_dmabuf_import_sync_file (fd, DMA_BUF_SYNC_WRITE, sync_file_fd); + + close (sync_file_fd); + } + + vkDestroySemaphore (display->vk_device, self->vk_semaphore, NULL); +} + static void gsk_gpu_download_op_vk_create (GskGpuDownloadOp *self) { @@ -93,7 +136,31 @@ gsk_gpu_download_op_vk_command (GskGpuOp *op, #ifdef HAVE_DMABUF self->texture = gsk_vulkan_image_to_dmabuf_texture (GSK_VULKAN_IMAGE (self->image)); if (self->texture) - return op->next; + { + GskVulkanDevice *device = GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame)); + VkDevice vk_device = gsk_vulkan_device_get_vk_device (device); + + gsk_gpu_device_cache_texture_image (GSK_GPU_DEVICE (device), self->texture, gsk_gpu_frame_get_timestamp (frame), self->image); + + if (gsk_vulkan_device_has_feature (device, GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT)) + { + GSK_VK_CHECK (vkCreateSemaphore, vk_device, + &(VkSemaphoreCreateInfo) { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + .pNext = &(VkExportSemaphoreCreateInfo) { + .sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO, + .handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT, + }, + }, + NULL, + &self->vk_semaphore); + gsk_vulkan_semaphores_add_signal (state->semaphores, self->vk_semaphore); + + self->create_func = gsk_gpu_download_op_vk_sync_semaphore; + } + + return op->next; + } #endif width = gsk_gpu_image_get_width (self->image); @@ -103,6 +170,7 @@ gsk_gpu_download_op_vk_command (GskGpuOp *op, height * stride); gsk_vulkan_image_transition (GSK_VULKAN_IMAGE (self->image), + state->semaphores, state->vk_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, diff --git a/gsk/gpu/gskgpumipmapop.c b/gsk/gpu/gskgpumipmapop.c index 374e6ae199..ccbace3577 100644 --- a/gsk/gpu/gskgpumipmapop.c +++ b/gsk/gpu/gskgpumipmapop.c @@ -58,6 +58,7 @@ gsk_gpu_mipmap_op_vk_command (GskGpuOp *op, /* optimize me: only transition mipmap layers 1..n, but not 0 */ gsk_vulkan_image_transition (image, + state->semaphores, state->vk_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, diff --git a/gsk/gpu/gskgpuopprivate.h b/gsk/gpu/gskgpuopprivate.h index cd8c083003..7cfc9f0675 100644 --- a/gsk/gpu/gskgpuopprivate.h +++ b/gsk/gpu/gskgpuopprivate.h @@ -39,6 +39,7 @@ struct _GskVulkanCommandState VkCommandBuffer vk_command_buffer; GskVulkanDescriptors *desc; + GskVulkanSemaphores *semaphores; }; #endif diff --git a/gsk/gpu/gskgpurenderpassop.c b/gsk/gpu/gskgpurenderpassop.c index ca30f9929f..188da496ef 100644 --- a/gsk/gpu/gskgpurenderpassop.c +++ b/gsk/gpu/gskgpurenderpassop.c @@ -88,11 +88,11 @@ gsk_gpu_render_pass_op_do_barriers (GskGpuRenderPassOp *self, state->desc = GSK_VULKAN_DESCRIPTORS (shader->desc); } desc = shader->desc; - gsk_vulkan_descriptors_transition (GSK_VULKAN_DESCRIPTORS (desc), state->vk_command_buffer); + gsk_vulkan_descriptors_transition (GSK_VULKAN_DESCRIPTORS (desc), state->semaphores, state->vk_command_buffer); } if (desc == NULL) - gsk_vulkan_descriptors_transition (state->desc, state->vk_command_buffer); + gsk_vulkan_descriptors_transition (state->desc, state->semaphores, state->vk_command_buffer); } static GskGpuOp * diff --git a/gsk/gpu/gskgputypesprivate.h b/gsk/gpu/gskgputypesprivate.h index 44a94f6041..569660a4f3 100644 --- a/gsk/gpu/gskgputypesprivate.h +++ b/gsk/gpu/gskgputypesprivate.h @@ -18,6 +18,7 @@ typedef struct _GskGpuOpClass GskGpuOpClass; typedef struct _GskGpuShaderOp GskGpuShaderOp; typedef struct _GskGpuShaderOpClass GskGpuShaderOpClass; typedef struct _GskVulkanDescriptors GskVulkanDescriptors; +typedef struct _GskVulkanSemaphores GskVulkanSemaphores; typedef enum { GSK_GPU_IMAGE_EXTERNAL = (1 << 0), diff --git a/gsk/gpu/gskgpuuploadop.c b/gsk/gpu/gskgpuuploadop.c index 7946aa165a..e4266960df 100644 --- a/gsk/gpu/gskgpuuploadop.c +++ b/gsk/gpu/gskgpuuploadop.c @@ -130,6 +130,7 @@ gsk_gpu_upload_op_vk_command_with_area (GskGpuOp *op, }, 0, NULL); gsk_vulkan_image_transition (image, + state->semaphores, state->vk_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, diff --git a/gsk/gpu/gskvulkandescriptors.c b/gsk/gpu/gskvulkandescriptors.c index f07b907717..edba0f83d6 100644 --- a/gsk/gpu/gskvulkandescriptors.c +++ b/gsk/gpu/gskvulkandescriptors.c @@ -26,6 +26,7 @@ gsk_vulkan_descriptors_get_pipeline_layout (GskVulkanDescriptors *self) void gsk_vulkan_descriptors_transition (GskVulkanDescriptors *self, + GskVulkanSemaphores *semaphores, VkCommandBuffer vk_command_buffer) { GskGpuDescriptors *desc = GSK_GPU_DESCRIPTORS (self); @@ -34,6 +35,7 @@ gsk_vulkan_descriptors_transition (GskVulkanDescriptors *self, for (i = 0; i < gsk_gpu_descriptors_get_n_images (desc); i++) { gsk_vulkan_image_transition (GSK_VULKAN_IMAGE (gsk_gpu_descriptors_get_image (desc, i)), + semaphores, vk_command_buffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, diff --git a/gsk/gpu/gskvulkandescriptorsprivate.h b/gsk/gpu/gskvulkandescriptorsprivate.h index 8434a0b22f..fb8aef1b3f 100644 --- a/gsk/gpu/gskvulkandescriptorsprivate.h +++ b/gsk/gpu/gskvulkandescriptorsprivate.h @@ -35,6 +35,7 @@ GType gsk_vulkan_descriptors_get_type GskVulkanPipelineLayout * gsk_vulkan_descriptors_get_pipeline_layout (GskVulkanDescriptors *self); void gsk_vulkan_descriptors_transition (GskVulkanDescriptors *self, + GskVulkanSemaphores *semaphores, VkCommandBuffer vk_command_buffer); void gsk_vulkan_descriptors_bind (GskVulkanDescriptors *self, GskVulkanDescriptors *previous, diff --git a/gsk/gpu/gskvulkanframe.c b/gsk/gpu/gskvulkanframe.c index bffd78e938..bbaaea8e77 100644 --- a/gsk/gpu/gskvulkanframe.c +++ b/gsk/gpu/gskvulkanframe.c @@ -20,6 +20,27 @@ #define GDK_ARRAY_NO_MEMSET 1 #include "gdk/gdkarrayimpl.c" +#define GDK_ARRAY_NAME gsk_semaphores +#define GDK_ARRAY_TYPE_NAME GskSemaphores +#define GDK_ARRAY_ELEMENT_TYPE VkSemaphore +#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 +#define GDK_ARRAY_PREALLOC 16 +#define GDK_ARRAY_NO_MEMSET 1 +#include "gdk/gdkarrayimpl.c" + +struct _GskVulkanSemaphores +{ + GskSemaphores wait_semaphores; + GskPipelineStages wait_stages; + GskSemaphores signal_semaphores; +}; + struct _GskVulkanFrame { GskGpuFrame parent_instance; @@ -265,6 +286,7 @@ gsk_vulkan_frame_submit (GskGpuFrame *frame, GskGpuOp *op) { GskVulkanFrame *self = GSK_VULKAN_FRAME (frame); + GskVulkanSemaphores semaphores; GskVulkanCommandState state; if (gsk_descriptors_get_size (&self->descriptors) == 0) @@ -287,10 +309,16 @@ gsk_vulkan_frame_submit (GskGpuFrame *frame, }, (VkDeviceSize[1]) { 0 }); + gsk_semaphores_init (&semaphores.wait_semaphores); + gsk_pipeline_stages_init (&semaphores.wait_stages); + gsk_semaphores_init (&semaphores.signal_semaphores); + state.vk_command_buffer = self->vk_command_buffer; state.vk_render_pass = VK_NULL_HANDLE; state.vk_format = VK_FORMAT_UNDEFINED; state.desc = GSK_VULKAN_DESCRIPTORS (gsk_descriptors_get (&self->descriptors, 0)); + state.semaphores = &semaphores; + gsk_vulkan_descriptors_bind (GSK_VULKAN_DESCRIPTORS (gsk_descriptors_get (&self->descriptors, 0)), NULL, state.vk_command_buffer); @@ -308,8 +336,17 @@ gsk_vulkan_frame_submit (GskGpuFrame *frame, .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .commandBufferCount = 1, .pCommandBuffers = &self->vk_command_buffer, + .pWaitSemaphores = gsk_semaphores_get_data (&semaphores.wait_semaphores), + .pWaitDstStageMask = gsk_pipeline_stages_get_data (&semaphores.wait_stages), + .waitSemaphoreCount = gsk_semaphores_get_size (&semaphores.wait_semaphores), + .pSignalSemaphores = gsk_semaphores_get_data (&semaphores.signal_semaphores), + .signalSemaphoreCount = gsk_semaphores_get_size (&semaphores.signal_semaphores), }, self->vk_fence); + + gsk_semaphores_clear (&semaphores.wait_semaphores); + gsk_pipeline_stages_clear (&semaphores.wait_stages); + gsk_semaphores_clear (&semaphores.signal_semaphores); } static void @@ -376,3 +413,19 @@ gsk_vulkan_frame_get_vk_fence (GskVulkanFrame *self) return self->vk_fence; } +void +gsk_vulkan_semaphores_add_wait (GskVulkanSemaphores *self, + VkSemaphore semaphore, + VkPipelineStageFlags stage) +{ + gsk_semaphores_append (&self->wait_semaphores, semaphore); + gsk_pipeline_stages_append (&self->wait_stages, stage); +} + +void +gsk_vulkan_semaphores_add_signal (GskVulkanSemaphores *self, + VkSemaphore semaphore) +{ + gsk_semaphores_append (&self->signal_semaphores, semaphore); +} + diff --git a/gsk/gpu/gskvulkanframeprivate.h b/gsk/gpu/gskvulkanframeprivate.h index 0fddb83d9d..8d3995241c 100644 --- a/gsk/gpu/gskvulkanframeprivate.h +++ b/gsk/gpu/gskvulkanframeprivate.h @@ -12,5 +12,10 @@ G_DECLARE_FINAL_TYPE (GskVulkanFrame, gsk_vulkan_frame, GSK, VULKAN_FRAME, GskGp VkFence gsk_vulkan_frame_get_vk_fence (GskVulkanFrame *self) G_GNUC_PURE; +void gsk_vulkan_semaphores_add_wait (GskVulkanSemaphores *self, + VkSemaphore semaphore, + VkPipelineStageFlags stage); +void gsk_vulkan_semaphores_add_signal (GskVulkanSemaphores *self, + VkSemaphore semaphore); G_END_DECLS diff --git a/gsk/gpu/gskvulkanimage.c b/gsk/gpu/gskvulkanimage.c index dcff48054e..d0cd531f4a 100644 --- a/gsk/gpu/gskvulkanimage.c +++ b/gsk/gpu/gskvulkanimage.c @@ -3,6 +3,7 @@ #include "gskvulkanimageprivate.h" #include "gskvulkanbufferprivate.h" +#include "gskvulkanframeprivate.h" #include "gskvulkanmemoryprivate.h" #include "gdk/gdkdisplayprivate.h" @@ -13,6 +14,9 @@ #include #include +#ifdef HAVE_DMABUF +#include +#endif struct _GskVulkanImage { @@ -28,6 +32,7 @@ struct _GskVulkanImage VkFramebuffer vk_framebuffer; VkImageView vk_framebuffer_image_view; VkSampler vk_sampler; + VkSemaphore vk_semaphore; VkPipelineStageFlags vk_pipeline_stage; VkImageLayout vk_image_layout; @@ -1221,6 +1226,32 @@ gsk_vulkan_image_new_for_dmabuf (GskVulkanDevice *device, }, &requirements); + if (gsk_vulkan_device_has_feature (device, GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT)) + { + int sync_file_fd = gdk_dmabuf_export_sync_file (fd, DMA_BUF_SYNC_READ); + if (sync_file_fd >= 0) + { + PFN_vkImportSemaphoreFdKHR func_vkImportSemaphoreFdKHR; + func_vkImportSemaphoreFdKHR = (PFN_vkImportSemaphoreFdKHR) vkGetDeviceProcAddr (vk_device, "vkImportSemaphoreFdKHR"); + + GSK_VK_CHECK (vkCreateSemaphore, vk_device, + &(VkSemaphoreCreateInfo) { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + }, + NULL, + &self->vk_semaphore); + + GSK_VK_CHECK (func_vkImportSemaphoreFdKHR, vk_device, + &(VkImportSemaphoreFdInfoKHR) { + .sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR, + .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT, + .flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT, + .semaphore = self->vk_semaphore, + .fd = sync_file_fd, + }); + } + } + gsk_vulkan_alloc (self->allocator, requirements.memoryRequirements.size, requirements.memoryRequirements.alignment, @@ -1440,6 +1471,8 @@ gsk_vulkan_image_to_dmabuf_texture (GskVulkanImage *self) return NULL; } + gsk_gpu_image_toggle_ref_texture (GSK_GPU_IMAGE (self), texture); + return texture; } #endif @@ -1481,6 +1514,9 @@ gsk_vulkan_image_finalize (GObject *object) if (self->vk_image_view != VK_NULL_HANDLE) vkDestroyImageView (device, self->vk_image_view, NULL); + if (self->vk_semaphore != VK_NULL_HANDLE) + vkDestroySemaphore (device, self->vk_semaphore, NULL); + /* memory is NULL for for_swapchain() images, where we don't own * the VkImage */ if (self->allocator) @@ -1610,6 +1646,7 @@ gsk_vulkan_image_set_vk_image_layout (GskVulkanImage *self, void gsk_vulkan_image_transition (GskVulkanImage *self, + GskVulkanSemaphores *semaphores, VkCommandBuffer command_buffer, VkPipelineStageFlags stage, VkImageLayout image_layout, @@ -1620,6 +1657,12 @@ gsk_vulkan_image_transition (GskVulkanImage *self, self->vk_access == access) return; + if (self->vk_pipeline_stage == VK_IMAGE_LAYOUT_UNDEFINED && + self->vk_semaphore) + { + gsk_vulkan_semaphores_add_wait (semaphores, self->vk_semaphore, stage); + } + vkCmdPipelineBarrier (command_buffer, self->vk_pipeline_stage, stage, diff --git a/gsk/gpu/gskvulkanimageprivate.h b/gsk/gpu/gskvulkanimageprivate.h index 899af834aa..54f2754326 100644 --- a/gsk/gpu/gskvulkanimageprivate.h +++ b/gsk/gpu/gskvulkanimageprivate.h @@ -52,6 +52,7 @@ void gsk_vulkan_image_set_vk_image_layout (GskVulk VkImageLayout image_layout, VkAccessFlags access); void gsk_vulkan_image_transition (GskVulkanImage *self, + GskVulkanSemaphores *semaphores, VkCommandBuffer command_buffer, VkPipelineStageFlags stage, VkImageLayout image_layout,