[gtk+/wip/matthiasc/renderpasses: 10/10] add semaphores



commit 156ecb90eaf058ed556a2e9a802d4ff3d3714d75
Author: Matthias Clasen <mclasen redhat com>
Date:   Tue Sep 26 23:41:25 2017 -0400

    add semaphores

 gsk/gskprivate.h                  |    3 +
 gsk/gskvulkancommandpool.c        |   32 +++++-----
 gsk/gskvulkancommandpoolprivate.h |    3 +
 gsk/gskvulkanimage.c              |   34 ++++++++--
 gsk/gskvulkanimageprivate.h       |    1 +
 gsk/gskvulkanrender.c             |  124 ++++++++++++++++++++++++++----------
 gsk/gskvulkanrenderpass.c         |   22 ++++++-
 gsk/gskvulkanrenderpassprivate.h  |    4 +-
 gsk/gskvulkanrenderprivate.h      |    5 +-
 9 files changed, 167 insertions(+), 61 deletions(-)
---
diff --git a/gsk/gskprivate.h b/gsk/gskprivate.h
index 8584be6..5d9f88c 100644
--- a/gsk/gskprivate.h
+++ b/gsk/gskprivate.h
@@ -10,6 +10,9 @@ void gsk_ensure_resources (void);
 
 int pango_glyph_string_num_glyphs (PangoGlyphString *glyphs);
 
+typedef struct _GskVulkanRender GskVulkanRender;
+typedef struct _GskVulkanRenderPass GskVulkanRenderPass;
+
 G_END_DECLS
 
 #endif /* __GSK_PRIVATE_H__ */
diff --git a/gsk/gskvulkancommandpool.c b/gsk/gskvulkancommandpool.c
index c2b9747..0125f64 100644
--- a/gsk/gskvulkancommandpool.c
+++ b/gsk/gskvulkancommandpool.c
@@ -75,33 +75,35 @@ gsk_vulkan_command_pool_get_buffer (GskVulkanCommandPool *self)
 void
 gsk_vulkan_command_pool_submit_buffer (GskVulkanCommandPool *self,
                                        VkCommandBuffer       command_buffer,
+                                       gsize                 wait_semaphore_count,
+                                       VkSemaphore          *wait_semaphores,
+                                       VkSemaphore           signal_semaphore,
                                        VkFence               fence)
 {
+  VkPipelineStageFlags *wait_semaphore_flags = NULL;
+
   GSK_VK_CHECK (vkEndCommandBuffer, command_buffer);
 
+  if (wait_semaphore_count > 0)
+    {
+      wait_semaphore_flags = alloca (sizeof (VkPipelineStageFlags) * wait_semaphore_count);
+      for (int i = 0; i < wait_semaphore_count; i++)
+        wait_semaphore_flags[i] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+    }
+
   GSK_VK_CHECK (vkQueueSubmit, gdk_vulkan_context_get_queue (self->vulkan),
                                1,
                                &(VkSubmitInfo) {
                                   .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
-/*
-                                  .waitSemaphoreCount = 1,
-                                  .pWaitSemaphores = (VkSemaphore[1]) {
-                                      gdk_vulkan_context_get_draw_semaphore (self->vulkan)
-                                  },
-*/
-                                  .pWaitDstStageMask = (VkPipelineStageFlags []) {
-                                      VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
-                                  },
+                                  .waitSemaphoreCount = wait_semaphore_count,
+                                  .pWaitSemaphores = wait_semaphores,
+                                  .pWaitDstStageMask = wait_semaphore_flags,
                                   .commandBufferCount = 1,
                                   .pCommandBuffers = (VkCommandBuffer[1]) {
                                       command_buffer
                                   },
-/*
-                                  .signalSemaphoreCount = 1,
-                                  .pSignalSemaphores = (VkSemaphore[1]) {
-                                      gdk_vulkan_context_get_draw_semaphore (self->vulkan)
-                                  }
-*/
+                                  .signalSemaphoreCount = signal_semaphore != VK_NULL_HANDLE ? 1 : 0,
+                                  .pSignalSemaphores = &signal_semaphore,
                                },
                                fence);
 }
diff --git a/gsk/gskvulkancommandpoolprivate.h b/gsk/gskvulkancommandpoolprivate.h
index 0373908..48fed35 100644
--- a/gsk/gskvulkancommandpoolprivate.h
+++ b/gsk/gskvulkancommandpoolprivate.h
@@ -15,6 +15,9 @@ void                    gsk_vulkan_command_pool_reset                   (GskVulk
 VkCommandBuffer         gsk_vulkan_command_pool_get_buffer              (GskVulkanCommandPool   *self);
 void                    gsk_vulkan_command_pool_submit_buffer           (GskVulkanCommandPool   *self,
                                                                          VkCommandBuffer         buffer,
+                                                                         gsize                   
wait_semaphore_count,
+                                                                         VkSemaphore            
*wait_semaphores,
+                                                                         VkSemaphore             
signal_semaphore,
                                                                          VkFence                 fence);
 
 G_END_DECLS
diff --git a/gsk/gskvulkanimage.c b/gsk/gskvulkanimage.c
index 5a286e1..aa6ca42 100644
--- a/gsk/gskvulkanimage.c
+++ b/gsk/gskvulkanimage.c
@@ -37,6 +37,7 @@ struct _GskVulkanImage
   VkImageView vk_image_view;
   VkImageLayout vk_image_layout;
   VkAccessFlags vk_access;
+  VkSemaphore vk_semaphore;
 
   GskVulkanMemory *memory;
 };
@@ -154,7 +155,7 @@ gsk_vulkan_uploader_upload (GskVulkanUploader *self)
                             0, NULL,
                             self->before_buffer_barriers->len, (VkBufferMemoryBarrier *) 
self->before_buffer_barriers->data,
                             self->before_image_barriers->len, (VkImageMemoryBarrier *) 
self->before_image_barriers->data);
-      gsk_vulkan_command_pool_submit_buffer (self->command_pool, command_buffer, VK_NULL_HANDLE);
+      gsk_vulkan_command_pool_submit_buffer (self->command_pool, command_buffer, 0, NULL, VK_NULL_HANDLE, 
VK_NULL_HANDLE);
       g_array_set_size (self->before_buffer_barriers, 0);
       g_array_set_size (self->before_image_barriers, 0);
     }
@@ -176,7 +177,7 @@ gsk_vulkan_uploader_upload (GskVulkanUploader *self)
 
   if (self->copy_buffer != VK_NULL_HANDLE)
     {
-      gsk_vulkan_command_pool_submit_buffer (self->command_pool, self->copy_buffer, VK_NULL_HANDLE);
+      gsk_vulkan_command_pool_submit_buffer (self->command_pool, self->copy_buffer, 0, NULL, VK_NULL_HANDLE, 
VK_NULL_HANDLE);
       self->copy_buffer = VK_NULL_HANDLE;
     }
 }
@@ -215,6 +216,7 @@ gsk_vulkan_image_new (GdkVulkanContext      *context,
   self->vk_usage = usage;
   self->vk_image_layout = layout;
   self->vk_access = access;
+  self->vk_semaphore = VK_NULL_HANDLE;
 
   GSK_VK_CHECK (vkCreateImage, gdk_vulkan_context_get_device (context),
                                 &(VkImageCreateInfo) {
@@ -622,9 +624,24 @@ gsk_vulkan_image_new_for_texture (GdkVulkanContext *context,
 
   gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_UNORM);
 
+  vkCreateSemaphore (gdk_vulkan_context_get_device (context),
+                     &(VkSemaphoreCreateInfo) {
+                       VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
+                       NULL,
+                       0
+                     },
+                     NULL,
+                     &self->vk_semaphore);
+
   return self;
 }
 
+VkSemaphore
+gsk_vulkan_image_get_semaphore (GskVulkanImage *self)
+{
+  return self->vk_semaphore;
+}
+
 GskTexture *
 gsk_vulkan_image_download (GskVulkanImage    *self,
                            GskVulkanUploader *uploader)
@@ -760,11 +777,14 @@ gsk_vulkan_image_finalize (GObject *object)
   GskVulkanImage *self = GSK_VULKAN_IMAGE (object);
 
   if (self->vk_image_view != VK_NULL_HANDLE)
-    {
-      vkDestroyImageView (gdk_vulkan_context_get_device (self->vulkan),
-                          self->vk_image_view,
-                          NULL);
-    }
+    vkDestroyImageView (gdk_vulkan_context_get_device (self->vulkan),
+                        self->vk_image_view,
+                         NULL);
+
+  if (self->vk_semaphore != VK_NULL_HANDLE)
+    vkDestroySemaphore (gdk_vulkan_context_get_device (self->vulkan),
+                        self->vk_semaphore,
+                        NULL);
 
   /* memory is NULL for for_swapchain() images, where we don't own
    * the VkImage */
diff --git a/gsk/gskvulkanimageprivate.h b/gsk/gskvulkanimageprivate.h
index f6223e9..8fc59fb 100644
--- a/gsk/gskvulkanimageprivate.h
+++ b/gsk/gskvulkanimageprivate.h
@@ -62,6 +62,7 @@ gsize                   gsk_vulkan_image_get_width                      (GskVulk
 gsize                   gsk_vulkan_image_get_height                     (GskVulkanImage         *self);
 VkImage                 gsk_vulkan_image_get_image                      (GskVulkanImage         *self);
 VkImageView             gsk_vulkan_image_get_image_view                 (GskVulkanImage         *self);
+VkSemaphore             gsk_vulkan_image_get_semaphore                  (GskVulkanImage         *self);
 
 G_END_DECLS
 
diff --git a/gsk/gskvulkanrender.c b/gsk/gskvulkanrender.c
index 9ff7b8a..e5c1919 100644
--- a/gsk/gskvulkanrender.c
+++ b/gsk/gskvulkanrender.c
@@ -46,7 +46,6 @@ struct _GskVulkanRender
   VkDescriptorSetLayout descriptor_set_layout;
   VkPipelineLayout pipeline_layout[3]; /* indexed by number of textures */
   GskVulkanUploader *uploader;
-  GskVulkanBuffer *vertex_buffer;
 
   GHashTable *descriptor_set_indexes;
   VkDescriptorPool descriptor_pool;
@@ -68,6 +67,9 @@ typedef struct {
   cairo_region_t *clip;
   int scale_factor;
   VkRenderPass render_pass;
+  GskVulkanBuffer *vertex_data;
+  VkSemaphore signal_semaphore;
+  GArray *wait_semaphores;
 } RenderPassData;
 
 static void
@@ -82,6 +84,16 @@ render_pass_data_free (gpointer v)
     vkDestroyRenderPass (gdk_vulkan_context_get_device (data->render->vulkan),
                          data->render_pass,
                          NULL);
+  if (data->vertex_data)
+    gsk_vulkan_buffer_free (data->vertex_data);
+  if (data->signal_semaphore != VK_NULL_HANDLE)
+    {
+      vkDestroySemaphore (gdk_vulkan_context_get_device (data->render->vulkan),
+                          data->signal_semaphore,
+                          NULL);
+    }
+  if (data->wait_semaphores)
+    g_array_unref (data->wait_semaphores);
   g_free (data);
 }
 
@@ -318,6 +330,8 @@ gsk_vulkan_render_add_node (GskVulkanRender *self,
   data->scale_factor = self->scale_factor;
   data->clip = cairo_region_copy (self->clip);
   data->render_pass = self->render_pass;
+  data->signal_semaphore = VK_NULL_HANDLE;
+  data->wait_semaphores = NULL;
 
   self->render_passes = g_list_prepend (self->render_passes, data);
 
@@ -331,12 +345,38 @@ gsk_vulkan_render_add_node (GskVulkanRender *self,
                               node);
 }
 
+static void
+add_wait_semaphore (GskVulkanRender     *self,
+                    GskVulkanRenderPass *pass,
+                    VkSemaphore          semaphore)
+{
+  GList *l;
+
+  if (semaphore == VK_NULL_HANDLE)
+    return;
+
+  for (l = self->render_passes; l; l = l->next)
+    {
+      RenderPassData *data = l->data;
+      if (data->pass == pass)
+        {
+          if (data->wait_semaphores == NULL)
+            data->wait_semaphores = g_array_new (FALSE, FALSE, sizeof (VkSemaphore));
+
+          g_array_append_val (data->wait_semaphores, semaphore);
+          return;
+        }
+    }
+}
+
 void
-gsk_vulkan_render_add_node_for_texture (GskVulkanRender *self,
-                                        GskRenderNode   *node,
-                                        GskVulkanImage  *target)
+gsk_vulkan_render_add_node_for_texture (GskVulkanRender     *self,
+                                        GskVulkanRenderPass *pass,
+                                        GskRenderNode       *node,
+                                        GskVulkanImage      *target)
 {
   RenderPassData *data;
+  VkSemaphore semaphore;
 
   data = g_new0 (RenderPassData, 1);
   data->pass = gsk_vulkan_render_pass_new (self->vulkan);
@@ -349,6 +389,13 @@ gsk_vulkan_render_add_node_for_texture (GskVulkanRender *self,
                                                 gsk_vulkan_image_get_height (target)
                                                 });
 
+  semaphore = gsk_vulkan_image_get_semaphore (target);
+  if (semaphore != VK_NULL_HANDLE)
+    {
+      data->signal_semaphore = semaphore;
+      add_wait_semaphore (self, pass, semaphore);
+    }
+
   GSK_VK_CHECK (vkCreateRenderPass, gdk_vulkan_context_get_device (self->vulkan),
                                     &(VkRenderPassCreateInfo) {
                                         .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
@@ -647,31 +694,33 @@ void
 gsk_vulkan_render_draw (GskVulkanRender   *self,
                         VkSampler          sampler)
 {
-  VkCommandBuffer command_buffer;
   GList *l;
-  guint i;
 
   gsk_vulkan_render_prepare_descriptor_sets (self, sampler);
 
-  command_buffer = gsk_vulkan_command_pool_get_buffer (self->command_pool);
-
-  self->vertex_buffer = gsk_vulkan_render_collect_vertex_data (self);
-
-  vkCmdSetViewport (command_buffer,
-                    0,
-                    1,
-                    &(VkViewport) {
-                      .x = 0,
-                      .y = 0,
-                      .width = self->viewport.extent.width,
-                      .height = self->viewport.extent.height,
-                      .minDepth = 0,
-                      .maxDepth = 1
-                    });
-
   for (l = self->render_passes; l; l = l->next)
     {
       RenderPassData *pass = l->data;
+      VkCommandBuffer command_buffer;
+      VkFence fence;
+      guint i;
+
+      pass->vertex_data = gsk_vulkan_render_pass_get_vertex_data (pass->pass, self);
+
+      command_buffer = gsk_vulkan_command_pool_get_buffer (self->command_pool);
+
+     vkCmdSetViewport (command_buffer,
+                       0,
+                       1,
+                       &(VkViewport) {
+                         .x = 0,
+                         .y = 0,
+                         .width = self->viewport.extent.width,
+                         .height = self->viewport.extent.height,
+                         .minDepth = 0,
+                         .maxDepth = 1
+                       });
+
       for (i = 0; i < cairo_region_num_rectangles (pass->clip); i++)
         {
           cairo_rectangle_int_t rect;
@@ -702,22 +751,29 @@ gsk_vulkan_render_draw (GskVulkanRender   *self,
                                 },
                                 VK_SUBPASS_CONTENTS_INLINE);
 
-          gsk_vulkan_render_pass_draw (pass->pass, self, self->vertex_buffer, 3, self->pipeline_layout, 
command_buffer);
-
+          gsk_vulkan_render_pass_draw (pass->pass, self, pass->vertex_data, 3, self->pipeline_layout, 
command_buffer);
           vkCmdEndRenderPass (command_buffer);
         }
-    }
 
-  gsk_vulkan_command_pool_submit_buffer (self->command_pool, command_buffer, self->fence);
+      if (l->next == NULL) // last batch
+        fence = self->fence;
+      else
+        fence = VK_NULL_HANDLE;
+
+      gsk_vulkan_command_pool_submit_buffer (self->command_pool,
+                                             command_buffer,
+                                             pass->wait_semaphores ? pass->wait_semaphores->len : 0,
+                                             pass->wait_semaphores ? pass->wait_semaphores->data : NULL,
+                                             pass->signal_semaphore,
+                                             fence);
+    }
 
   if (GSK_RENDER_MODE_CHECK (SYNC))
-    {
-      GSK_VK_CHECK (vkWaitForFences, gdk_vulkan_context_get_device (self->vulkan),
-                                     1,
-                                     &self->fence,
-                                     VK_TRUE,
-                                     INT64_MAX);
-    }
+    GSK_VK_CHECK (vkWaitForFences, gdk_vulkan_context_get_device (self->vulkan),
+                                   1,
+                                   &self->fence,
+                                   VK_TRUE,
+                                   INT64_MAX);
 }
 
 GskTexture *
@@ -748,8 +804,6 @@ gsk_vulkan_render_cleanup (GskVulkanRender *self)
 
   gsk_vulkan_command_pool_reset (self->command_pool);
 
-  g_clear_pointer (&self->vertex_buffer, gsk_vulkan_buffer_free);
-
   g_hash_table_remove_all (self->descriptor_set_indexes);
   GSK_VK_CHECK (vkResetDescriptorPool, device,
                                        self->descriptor_pool,
diff --git a/gsk/gskvulkanrenderpass.c b/gsk/gskvulkanrenderpass.c
index 6eae4a0..9d750a6 100644
--- a/gsk/gskvulkanrenderpass.c
+++ b/gsk/gskvulkanrenderpass.c
@@ -118,6 +118,7 @@ gsk_vulkan_render_pass_new (GdkVulkanContext *context)
   self = g_slice_new0 (GskVulkanRenderPass);
   self->vulkan = g_object_ref (context);
   self->render_ops = g_array_new (FALSE, FALSE, sizeof (GskVulkanOp));
+
 #ifdef G_ENABLE_DEBUG
   self->fallback_pixels = g_quark_from_static_string ("fallback-pixels");
 #endif
@@ -572,7 +573,7 @@ gsk_vulkan_render_pass_get_node_as_texture (GskVulkanRenderPass   *self,
                                                      ceil (bounds->size.width),
                                                      ceil (bounds->size.height));
           g_assert (result != NULL);
-          gsk_vulkan_render_add_node_for_texture (render, node, result);
+          gsk_vulkan_render_add_node_for_texture (render, self, node, result);
           g_assert (result != 0);
 
           return result;
@@ -1153,6 +1154,25 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
   return n_bytes;
 }
 
+GskVulkanBuffer *
+gsk_vulkan_render_pass_get_vertex_data (GskVulkanRenderPass *self,
+                                        GskVulkanRender     *render)
+{
+  gsize n_bytes;
+  GskVulkanBuffer *buffer;
+  guchar *data;
+
+  n_bytes = gsk_vulkan_render_pass_count_vertex_data (self);
+  buffer = gsk_vulkan_buffer_new (self->vulkan, n_bytes);
+  data = gsk_vulkan_buffer_map (buffer);
+
+  gsk_vulkan_render_pass_collect_vertex_data (self, render, data, 0, n_bytes);
+
+  gsk_vulkan_buffer_unmap (buffer);
+
+  return buffer;
+}
+
 void
 gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self,
                                                 GskVulkanRender     *render)
diff --git a/gsk/gskvulkanrenderpassprivate.h b/gsk/gskvulkanrenderpassprivate.h
index 56bc9ad..808ea88 100644
--- a/gsk/gskvulkanrenderpassprivate.h
+++ b/gsk/gskvulkanrenderpassprivate.h
@@ -6,10 +6,10 @@
 
 #include "gsk/gskvulkanbufferprivate.h"
 #include "gsk/gskvulkanrenderprivate.h"
+#include "gsk/gskprivate.h"
 
 G_BEGIN_DECLS
 
-typedef struct _GskVulkanRenderPass GskVulkanRenderPass;
 
 GskVulkanRenderPass *   gsk_vulkan_render_pass_new                      (GdkVulkanContext       *context);
 void                    gsk_vulkan_render_pass_free                     (GskVulkanRenderPass    *self);
@@ -30,6 +30,8 @@ gsize                   gsk_vulkan_render_pass_collect_vertex_data      (GskVulk
                                                                          guchar                 *data,
                                                                          gsize                   offset,
                                                                          gsize                   total);
+GskVulkanBuffer *       gsk_vulkan_render_pass_get_vertex_data          (GskVulkanRenderPass    *self,
+                                                                         GskVulkanRender        *render);
 
 void                    gsk_vulkan_render_pass_reserve_descriptor_sets  (GskVulkanRenderPass    *self,
                                                                          GskVulkanRender        *render);
diff --git a/gsk/gskvulkanrenderprivate.h b/gsk/gskvulkanrenderprivate.h
index 953e75c..9a4ea93 100644
--- a/gsk/gskvulkanrenderprivate.h
+++ b/gsk/gskvulkanrenderprivate.h
@@ -6,6 +6,8 @@
 
 #include "gsk/gskvulkanimageprivate.h"
 #include "gsk/gskvulkanpipelineprivate.h"
+#include "gsk/gskvulkanrenderpassprivate.h"
+#include "gsk/gskprivate.h"
 
 G_BEGIN_DECLS
 
@@ -50,8 +52,6 @@ typedef enum {
   GSK_VULKAN_N_PIPELINES
 } GskVulkanPipelineType;
 
-typedef struct _GskVulkanRender GskVulkanRender;
-
 GskVulkanRender *       gsk_vulkan_render_new                           (GskRenderer            *renderer,
                                                                          GdkVulkanContext       *context);
 void                    gsk_vulkan_render_free                          (GskVulkanRender        *self);
@@ -70,6 +70,7 @@ void                    gsk_vulkan_render_add_node                      (GskVulk
                                                                          GskRenderNode          *node);
 
 void                    gsk_vulkan_render_add_node_for_texture          (GskVulkanRender        *self,
+                                                                         GskVulkanRenderPass    *pass,
                                                                          GskRenderNode          *node,
                                                                          GskVulkanImage         *target);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]