[gtk+] vulkan: Implement multiple render passes



commit d61a71590942ece5da40a21bd80d77751147e99e
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed Sep 27 20:56:01 2017 -0400

    vulkan: Implement multiple render passes
    
    Whenever we need a node as a texture, we now start a new render
    pass that renders the node into a new intermediate texture, and
    set up a semaphore to make the current render pass wait for it.
    
    As part of this reorganization, much of the setup and drawing
    code moved from gskvulkanrender.c to gskvulkanrenderpass.c.

 gsk/gskvulkanrender.c            |  204 ++++++++++++-------------------
 gsk/gskvulkanrenderer.c          |    1 +
 gsk/gskvulkanrenderpass.c        |  255 +++++++++++++++++++++++++++++++++-----
 gsk/gskvulkanrenderpassprivate.h |   25 ++--
 gsk/gskvulkanrenderprivate.h     |    9 ++
 5 files changed, 324 insertions(+), 170 deletions(-)
---
diff --git a/gsk/gskvulkanrender.c b/gsk/gskvulkanrender.c
index 5888866..06b593c 100644
--- a/gsk/gskvulkanrender.c
+++ b/gsk/gskvulkanrender.c
@@ -23,9 +23,6 @@
 #include "gskvulkantextpipelineprivate.h"
 #include "gskvulkanpushconstantsprivate.h"
 
-#define ORTHO_NEAR_PLANE        -10000
-#define ORTHO_FAR_PLANE          10000
-
 #define DESCRIPTOR_POOL_MAXSETS 128
 #define DESCRIPTOR_POOL_MAXSETS_INCREASE 128
 
@@ -34,7 +31,6 @@ struct _GskVulkanRender
   GskRenderer *renderer;
   GdkVulkanContext *vulkan;
 
-  graphene_matrix_t mvp;
   int scale_factor;
   VkRect2D viewport;
   cairo_region_t *clip;
@@ -46,7 +42,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;
@@ -57,7 +52,7 @@ struct _GskVulkanRender
 
   GskVulkanImage *target;
 
-  GSList *render_passes;
+  GList *render_passes;
   GSList *cleanup_images;
 };
 
@@ -67,7 +62,6 @@ gsk_vulkan_render_setup (GskVulkanRender       *self,
                          const graphene_rect_t *rect)
 {
   GdkWindow *window = gsk_renderer_get_window (self->renderer);
-  graphene_matrix_t modelview, projection;
 
   self->target = g_object_ref (target);
 
@@ -88,15 +82,6 @@ gsk_vulkan_render_setup (GskVulkanRender       *self,
       self->viewport.extent.height = gdk_window_get_height (window) * self->scale_factor;
       self->clip = gdk_drawing_context_get_clip (gsk_renderer_get_drawing_context (self->renderer));
     }
-
-  graphene_matrix_init_scale (&modelview, self->scale_factor, self->scale_factor, 1.0);
-  graphene_matrix_init_ortho (&projection,
-                              self->viewport.offset.x, self->viewport.offset.x + self->viewport.extent.width,
-                              self->viewport.offset.y, self->viewport.offset.y + 
self->viewport.extent.height,
-                              ORTHO_NEAR_PLANE,
-                              ORTHO_FAR_PLANE);
-
-  graphene_matrix_multiply (&modelview, &projection, &self->mvp);
 }
 
 GskVulkanRender *
@@ -243,7 +228,7 @@ gsk_vulkan_render_remove_framebuffer_from_image (gpointer  data,
   g_slice_free (HashFramebufferEntry, fb);
 }
 
-static VkFramebuffer
+VkFramebuffer
 gsk_vulkan_render_get_framebuffer (GskVulkanRender *self,
                                    GskVulkanImage  *image)
 {
@@ -285,70 +270,69 @@ void
 gsk_vulkan_render_add_node (GskVulkanRender *self,
                             GskRenderNode   *node)
 {
-  GskVulkanRenderPass *pass = gsk_vulkan_render_pass_new (self->vulkan);
-
-  self->render_passes = g_slist_prepend (self->render_passes, pass);
-
-  gsk_vulkan_render_pass_add (pass,
-                              self,
-                              &self->mvp,
-                              &GRAPHENE_RECT_INIT (
-                                  self->viewport.offset.x, self->viewport.offset.y,
-                                  self->viewport.extent.width, self->viewport.extent.height
-                              ),
-                              node);
+  GskVulkanRenderPass *pass;
+
+  pass = gsk_vulkan_render_pass_new (self->vulkan,
+                                     self->target,
+                                     self->scale_factor,
+                                     &GRAPHENE_RECT_INIT (
+                                         self->viewport.offset.x, self->viewport.offset.y,
+                                         self->viewport.extent.width, self->viewport.extent.height
+                                     ),
+                                     self->clip,
+                                     VK_NULL_HANDLE);
+
+  self->render_passes = g_list_prepend (self->render_passes, pass);
+
+  gsk_vulkan_render_pass_add (pass, self, node);
 }
 
 void
-gsk_vulkan_render_upload (GskVulkanRender *self)
+gsk_vulkan_render_add_node_for_texture (GskVulkanRender       *self,
+                                        GskRenderNode         *node,
+                                        const graphene_rect_t *bounds,
+                                        GskVulkanImage        *target,
+                                        VkSemaphore            semaphore)
 {
-  GSList *l;
+  GskVulkanRenderPass *pass;
+  cairo_region_t *clip;
 
-  for (l = self->render_passes; l; l = l->next)
-    {
-      gsk_vulkan_render_pass_upload (l->data, self, self->uploader);
-    }
+  clip = cairo_region_create_rectangle (&(cairo_rectangle_int_t) {
+                                         0, 0,
+                                         gsk_vulkan_image_get_width (target),
+                                         gsk_vulkan_image_get_height (target)
+                                     });
 
-  gsk_vulkan_uploader_upload (self->uploader);
-}
+  pass = gsk_vulkan_render_pass_new (self->vulkan,
+                                     target,
+                                     1,
+                                     bounds,
+                                     clip,
+                                     semaphore);
 
-static gsize
-gsk_vulkan_renderer_count_vertex_data (GskVulkanRender *self)
-{
-  gsize n_bytes;
-  GSList *l;
+  cairo_region_destroy (clip);
 
-  n_bytes = 0;
-  for (l = self->render_passes; l; l = l->next)
-    {
-      n_bytes += gsk_vulkan_render_pass_count_vertex_data (l->data);
-    }
+  self->render_passes = g_list_prepend (self->render_passes, pass);
 
-  return n_bytes;
+  gsk_vulkan_render_pass_add (pass, self, node);
 }
 
-static GskVulkanBuffer *
-gsk_vulkan_render_collect_vertex_data (GskVulkanRender *self)
+void
+gsk_vulkan_render_upload (GskVulkanRender *self)
 {
-  GskVulkanBuffer *buffer;
-  guchar *data;
-  GSList *l;
-  gsize offset, n_bytes;
-  
-  offset = 0;
-  n_bytes = gsk_vulkan_renderer_count_vertex_data (self);
-  buffer = gsk_vulkan_buffer_new (self->vulkan, n_bytes);
-  data = gsk_vulkan_buffer_map (buffer);
+  GList *l;
 
-  for (l = self->render_passes; l; l = l->next)
+  /* gsk_vulkan_render_pass_upload may call gsk_vulkan_render_add_node_for_texture,
+   * prepending new render passes to the list. Therefore, we walk the list from
+   * the end.
+   */
+  for (l = g_list_last (self->render_passes); l; l = l->prev)
     {
-      offset += gsk_vulkan_render_pass_collect_vertex_data (l->data, self, data, offset, n_bytes - offset);
-      g_assert (offset <= n_bytes);
+      GskVulkanRenderPass *pass = l->data;
+      gsk_vulkan_render_pass_upload (pass, self, self->uploader);
     }
 
-  gsk_vulkan_buffer_unmap (buffer);
-
-  return buffer;
+  gsk_vulkan_uploader_upload (self->uploader);
 }
 
 GskVulkanPipeline *
@@ -424,6 +408,8 @@ gsk_vulkan_render_reserve_descriptor_set (GskVulkanRender *self,
 {
   gpointer id_plus_one;
 
+  g_assert (source != NULL);
+
   id_plus_one = g_hash_table_lookup (self->descriptor_set_indexes, source);
   if (id_plus_one)
     return GPOINTER_TO_SIZE (id_plus_one) - 1;
@@ -441,14 +427,15 @@ gsk_vulkan_render_prepare_descriptor_sets (GskVulkanRender *self,
   GHashTableIter iter;
   gpointer key, value;
   VkDevice device;
-  GSList *l;
+  GList *l;
   guint i, needed_sets;
 
   device = gdk_vulkan_context_get_device (self->vulkan);
 
   for (l = self->render_passes; l; l = l->next)
     {
-      gsk_vulkan_render_pass_reserve_descriptor_sets (l->data, self);
+      GskVulkanRenderPass *pass = l->data;
+      gsk_vulkan_render_pass_reserve_descriptor_sets (pass, self);
     }
   
   needed_sets = g_hash_table_size (self->descriptor_set_indexes);
@@ -534,68 +521,35 @@ void
 gsk_vulkan_render_draw (GskVulkanRender   *self,
                         VkSampler          sampler)
 {
-  VkCommandBuffer command_buffer;
-  GSList *l;
-  guint i;
+  GList *l;
 
   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 (i = 0; i < cairo_region_num_rectangles (self->clip); i++)
+  for (l = self->render_passes; l; l = l->next)
     {
-      cairo_rectangle_int_t rect;
-
-      cairo_region_get_rectangle (self->clip, i, &rect);
-
-      vkCmdSetScissor (command_buffer,
-                       0,
-                       1,
-                       &(VkRect2D) {
-                           { rect.x * self->scale_factor, rect.y * self->scale_factor },
-                           { rect.width * self->scale_factor, rect.height * self->scale_factor }
-                       });
-
-      vkCmdBeginRenderPass (command_buffer,
-                            &(VkRenderPassBeginInfo) {
-                                .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
-                                .renderPass = self->render_pass,
-                                .framebuffer = gsk_vulkan_render_get_framebuffer (self, self->target),
-                                .renderArea = { 
-                                    { rect.x * self->scale_factor, rect.y * self->scale_factor },
-                                    { rect.width * self->scale_factor, rect.height * self->scale_factor }
-                                },
-                                .clearValueCount = 1,
-                                .pClearValues = (VkClearValue [1]) {
-                                    { .color = { .float32 = { 0.f, 0.f, 0.f, 0.f } } }
-                                }
-                            },
-                            VK_SUBPASS_CONTENTS_INLINE);
-
-      for (l = self->render_passes; l; l = l->next)
-        {
-          gsk_vulkan_render_pass_draw (l->data, self, self->vertex_buffer, 3, self->pipeline_layout, 
command_buffer);
-        }
-
-      vkCmdEndRenderPass (command_buffer);
+      GskVulkanRenderPass *pass = l->data;
+      VkCommandBuffer command_buffer;
+      gsize wait_semaphore_count;
+      gsize signal_semaphore_count;
+      VkSemaphore *wait_semaphores;
+      VkSemaphore *signal_semaphores;
+
+      wait_semaphore_count = gsk_vulkan_render_pass_get_wait_semaphores (pass, &wait_semaphores);
+      signal_semaphore_count = gsk_vulkan_render_pass_get_signal_semaphores (pass, &signal_semaphores);
+
+      command_buffer = gsk_vulkan_command_pool_get_buffer (self->command_pool);
+
+      gsk_vulkan_render_pass_draw (pass, self, 3, self->pipeline_layout, command_buffer);
+
+      gsk_vulkan_command_pool_submit_buffer (self->command_pool,
+                                             command_buffer,
+                                             wait_semaphore_count,
+                                             wait_semaphores,
+                                             signal_semaphore_count,
+                                             signal_semaphores,
+                                             l->next != NULL ? VK_NULL_HANDLE : self->fence);
     }
 
-  gsk_vulkan_command_pool_submit_buffer (self->command_pool, command_buffer, 0, NULL, 0, NULL, self->fence);
-
   if (GSK_RENDER_MODE_CHECK (SYNC))
     {
       GSK_VK_CHECK (vkWaitForFences, gdk_vulkan_context_get_device (self->vulkan),
@@ -634,14 +588,12 @@ 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,
                                        0);
 
-  g_slist_free_full (self->render_passes, (GDestroyNotify) gsk_vulkan_render_pass_free);
+  g_list_free_full (self->render_passes, (GDestroyNotify) gsk_vulkan_render_pass_free);
   self->render_passes = NULL;
   g_slist_free_full (self->cleanup_images, g_object_unref);
   self->cleanup_images = NULL;
diff --git a/gsk/gskvulkanrenderer.c b/gsk/gskvulkanrenderer.c
index 6666880..661128c 100644
--- a/gsk/gskvulkanrenderer.c
+++ b/gsk/gskvulkanrenderer.c
@@ -246,6 +246,7 @@ gsk_vulkan_renderer_render (GskRenderer   *renderer,
 
 #ifdef G_ENABLE_DEBUG
   profiler = gsk_renderer_get_profiler (renderer);
+  gsk_profiler_counter_set (profiler, self->profile_counters.fallback_pixels, 0);
   gsk_profiler_timer_begin (profiler, self->profile_timers.cpu_time);
 #endif
 
diff --git a/gsk/gskvulkanrenderpass.c b/gsk/gskvulkanrenderpass.c
index 022c08d..e82c4a2 100644
--- a/gsk/gskvulkanrenderpass.c
+++ b/gsk/gskvulkanrenderpass.c
@@ -27,6 +27,9 @@
 
 #include <cairo-ft.h>
 
+#define ORTHO_NEAR_PLANE        -10000
+#define ORTHO_FAR_PLANE          10000
+
 typedef union _GskVulkanOp GskVulkanOp;
 typedef struct _GskVulkanOpRender GskVulkanOpRender;
 typedef struct _GskVulkanOpText GskVulkanOpText;
@@ -107,17 +110,97 @@ struct _GskVulkanRenderPass
 
   GArray *render_ops;
 
+  GskVulkanImage *target;
+  int scale_factor;
+  graphene_rect_t viewport;
+  cairo_region_t *clip;
+  graphene_matrix_t mvp;
+
+  VkRenderPass render_pass;
+  VkSemaphore signal_semaphore;
+  GArray *wait_semaphores;
+  GskVulkanBuffer *vertex_data;
+
   GQuark fallback_pixels;
 };
 
 GskVulkanRenderPass *
-gsk_vulkan_render_pass_new (GdkVulkanContext *context)
+gsk_vulkan_render_pass_new (GdkVulkanContext  *context,
+                            GskVulkanImage    *target,
+                            int                scale_factor,
+                            graphene_rect_t   *viewport,
+                            cairo_region_t    *clip,
+                            VkSemaphore        signal_semaphore)
 {
   GskVulkanRenderPass *self;
+  graphene_matrix_t modelview, projection;
+  VkImageLayout final_layout;
 
   self = g_slice_new0 (GskVulkanRenderPass);
   self->vulkan = g_object_ref (context);
   self->render_ops = g_array_new (FALSE, FALSE, sizeof (GskVulkanOp));
+
+  self->target = g_object_ref (target);
+  self->scale_factor = scale_factor;
+  self->clip = cairo_region_copy (clip);
+  self->viewport = GRAPHENE_RECT_INIT (0, 0, viewport->size.width, viewport->size.height);
+
+  graphene_matrix_init_scale (&modelview, self->scale_factor, self->scale_factor, 1.0);
+  graphene_matrix_init_ortho (&projection,
+                              viewport->origin.x, viewport->origin.x + viewport->size.width,
+                              viewport->origin.y, viewport->origin.y + viewport->size.height,
+                              ORTHO_NEAR_PLANE,
+                              ORTHO_FAR_PLANE);
+  graphene_matrix_multiply (&modelview, &projection, &self->mvp);
+
+  if (signal_semaphore != VK_NULL_HANDLE) // this is a dependent pass
+    final_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+  else
+    final_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+  GSK_VK_CHECK (vkCreateRenderPass, gdk_vulkan_context_get_device (self->vulkan),
+                                    &(VkRenderPassCreateInfo) {
+                                        .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
+                                        .attachmentCount = 1,
+                                        .pAttachments = (VkAttachmentDescription[]) {
+                                           {
+                                              .format = gdk_vulkan_context_get_image_format (self->vulkan),
+                                              .samples = VK_SAMPLE_COUNT_1_BIT,
+                                              .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
+                                              .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
+                                              .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
+                                              .finalLayout = final_layout
+                                           }
+                                        },
+                                        .subpassCount = 1,
+                                        .pSubpasses = (VkSubpassDescription []) {
+                                           {
+                                              .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
+                                              .inputAttachmentCount = 0,
+                                              .colorAttachmentCount = 1,
+                                              .pColorAttachments = (VkAttachmentReference []) {
+                                                 {
+                                                    .attachment = 0,
+                                                     .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
+                                                  }
+                                               },
+                                               .pResolveAttachments = (VkAttachmentReference []) {
+                                                  {
+                                                     .attachment = VK_ATTACHMENT_UNUSED,
+                                                     .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
+                                                  }
+                                               },
+                                               .pDepthStencilAttachment = NULL,
+                                            }
+                                         },
+                                         .dependencyCount = 0
+                                      },
+                                      NULL,
+                                      &self->render_pass);
+
+  self->signal_semaphore = signal_semaphore;
+  self->wait_semaphores = g_array_new (FALSE, FALSE, sizeof (VkSemaphore));
+  self->vertex_data = NULL;
+
 #ifdef G_ENABLE_DEBUG
   self->fallback_pixels = g_quark_from_static_string ("fallback-pixels");
 #endif
@@ -130,6 +213,19 @@ gsk_vulkan_render_pass_free (GskVulkanRenderPass *self)
 {
   g_array_unref (self->render_ops);
   g_object_unref (self->vulkan);
+  g_object_unref (self->target);
+  cairo_region_destroy (self->clip);
+  vkDestroyRenderPass (gdk_vulkan_context_get_device (self->vulkan),
+                       self->render_pass,
+                       NULL);
+  if (self->vertex_data)
+    gsk_vulkan_buffer_free (self->vertex_data);
+  if (self->signal_semaphore != VK_NULL_HANDLE)
+    vkDestroySemaphore (gdk_vulkan_context_get_device (self->vulkan),
+                        self->signal_semaphore,
+                        NULL);
+  g_array_unref (self->wait_semaphores);
+
 
   g_slice_free (GskVulkanRenderPass, self);
 }
@@ -530,14 +626,12 @@ fallback:
 void
 gsk_vulkan_render_pass_add (GskVulkanRenderPass     *self,
                             GskVulkanRender         *render,
-                            const graphene_matrix_t *mvp,
-                            const graphene_rect_t   *viewport,
                             GskRenderNode           *node)
 {
   GskVulkanOp op = { 0, };
 
   op.type = GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS;
-  gsk_vulkan_push_constants_init (&op.constants.constants, mvp, viewport);
+  gsk_vulkan_push_constants_init (&op.constants.constants, &self->mvp, &self->viewport);
   g_array_append_val (self->render_ops, op);
 
   gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, node);
@@ -559,15 +653,39 @@ gsk_vulkan_render_pass_get_node_as_texture (GskVulkanRenderPass   *self,
       switch (gsk_render_node_get_node_type (node))
         {
         case GSK_TEXTURE_NODE:
-          return gsk_vulkan_renderer_ref_texture_image (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer 
(render)),
-                                                        gsk_texture_node_get_texture (node),
-                                                        uploader);
+          result = gsk_vulkan_renderer_ref_texture_image (GSK_VULKAN_RENDERER 
(gsk_vulkan_render_get_renderer (render)),
+                                                          gsk_texture_node_get_texture (node),
+                                                          uploader);
+          gsk_vulkan_render_add_cleanup_image (render, result);
+          return result;
+
         case GSK_CAIRO_NODE:
           surface = cairo_surface_reference (gsk_cairo_node_get_surface (node));
           goto got_surface;
 
-        default:
-          break;
+        default: ;
+          {
+            VkSemaphore semaphore;
+
+            result = gsk_vulkan_image_new_for_texture (self->vulkan,
+                                                       ceil (bounds->size.width),
+                                                       ceil (bounds->size.height));
+
+            vkCreateSemaphore (gdk_vulkan_context_get_device (self->vulkan),
+                               &(VkSemaphoreCreateInfo) {
+                                   VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
+                                   NULL,
+                                   0
+                               },
+                               NULL,
+                               &semaphore);
+
+            g_array_append_val (self->wait_semaphores, semaphore);
+            gsk_vulkan_render_add_node_for_texture (render, node, bounds, result, semaphore);
+            gsk_vulkan_render_add_cleanup_image (render, result);
+
+            return result;
+          }
         }
     }
 
@@ -756,7 +874,7 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass  *self,
           {
             GskRenderNode *child = gsk_color_matrix_node_get_child (op->render.node);
 
-            op->render.source = gsk_vulkan_render_pass_get_node_as_texture (self, 
+            op->render.source = gsk_vulkan_render_pass_get_node_as_texture (self,
                                                                             render,
                                                                             uploader,
                                                                             child,
@@ -813,7 +931,7 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass  *self,
     }
 }
 
-gsize
+static gsize
 gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self)
 {
   GskVulkanOp *op;
@@ -892,6 +1010,7 @@ gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self)
 
         default:
           g_assert_not_reached ();
+
         case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS:
           continue;
         }
@@ -900,7 +1019,7 @@ gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self)
   return n_bytes;
 }
 
-gsize
+static gsize
 gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
                                             GskVulkanRender     *render,
                                             guchar              *data,
@@ -1124,23 +1243,39 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
   return n_bytes;
 }
 
-GskVulkanBuffer *
+static 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);
+  if (self->vertex_data == NULL)
+    {
+      gsize n_bytes;
+      guchar *data;
+
+      n_bytes = gsk_vulkan_render_pass_count_vertex_data (self);
+      self->vertex_data = gsk_vulkan_buffer_new (self->vulkan, n_bytes);
+      data = gsk_vulkan_buffer_map (self->vertex_data);
+      gsk_vulkan_render_pass_collect_vertex_data (self, render, data, 0, n_bytes);
+      gsk_vulkan_buffer_unmap (self->vertex_data);
+    }
 
-  gsk_vulkan_render_pass_collect_vertex_data (self, render, data, 0, n_bytes);
+  return self->vertex_data;
+}
 
-  gsk_vulkan_buffer_unmap (buffer);
+gsize
+gsk_vulkan_render_pass_get_wait_semaphores (GskVulkanRenderPass  *self,
+                                            VkSemaphore         **semaphores)
+{
+  *semaphores = (VkSemaphore *)self->wait_semaphores->data;
+  return self->wait_semaphores->len;
+}
 
-  return buffer;
+gsize
+gsk_vulkan_render_pass_get_signal_semaphores (GskVulkanRenderPass  *self,
+                                              VkSemaphore         **semaphores)
+{
+  *semaphores = (VkSemaphore *)&self->signal_semaphore;
+  return self->signal_semaphore != VK_NULL_HANDLE ? 1 : 0;
 }
 
 void
@@ -1180,6 +1315,7 @@ gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self,
 
         default:
           g_assert_not_reached ();
+
         case GSK_VULKAN_OP_COLOR:
         case GSK_VULKAN_OP_LINEAR_GRADIENT:
         case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS:
@@ -1191,18 +1327,20 @@ gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self,
     }
 }
 
-void
-gsk_vulkan_render_pass_draw (GskVulkanRenderPass     *self,
-                             GskVulkanRender         *render,
-                             GskVulkanBuffer         *vertex_buffer,
-                             guint                    layout_count,
-                             VkPipelineLayout        *pipeline_layout,
-                             VkCommandBuffer          command_buffer)
+static void
+gsk_vulkan_render_pass_draw_rect (GskVulkanRenderPass     *self,
+                                  GskVulkanRender         *render,
+                                  guint                    layout_count,
+                                  VkPipelineLayout        *pipeline_layout,
+                                  VkCommandBuffer          command_buffer)
 {
   GskVulkanPipeline *current_pipeline = NULL;
   gsize current_draw_index = 0;
   GskVulkanOp *op;
   guint i, step;
+  GskVulkanBuffer *vertex_buffer;
+
+  vertex_buffer = gsk_vulkan_render_pass_get_vertex_data (self, render);
 
   for (i = 0; i < self->render_ops->len; i += step)
     {
@@ -1555,3 +1693,60 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass     *self,
         }
     }
 }
+
+void
+gsk_vulkan_render_pass_draw (GskVulkanRenderPass     *self,
+                             GskVulkanRender         *render,
+                             guint                    layout_count,
+                             VkPipelineLayout        *pipeline_layout,
+                             VkCommandBuffer          command_buffer)
+{
+  guint i;
+
+  vkCmdSetViewport (command_buffer,
+                    0,
+                    1,
+                    &(VkViewport) {
+                        .x = 0,
+                        .y = 0,
+                        .width = self->viewport.size.width,
+                        .height = self->viewport.size.height,
+                        .minDepth = 0,
+                        .maxDepth = 1
+                    });
+
+  for (i = 0; i < cairo_region_num_rectangles (self->clip); i++)
+    {
+      cairo_rectangle_int_t rect;
+
+      cairo_region_get_rectangle (self->clip, i, &rect);
+
+      vkCmdSetScissor (command_buffer,
+                       0,
+                       1,
+                       &(VkRect2D) {
+                          { rect.x * self->scale_factor, rect.y * self->scale_factor },
+                          { rect.width * self->scale_factor, rect.height * self->scale_factor }
+                       });
+
+      vkCmdBeginRenderPass (command_buffer,
+                            &(VkRenderPassBeginInfo) {
+                                .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
+                                .renderPass = self->render_pass,
+                                .framebuffer = gsk_vulkan_render_get_framebuffer (render, self->target),
+                                .renderArea = { 
+                                    { rect.x * self->scale_factor, rect.y * self->scale_factor },
+                                    { rect.width * self->scale_factor, rect.height * self->scale_factor }
+                                },
+                                .clearValueCount = 1,
+                                .pClearValues = (VkClearValue [1]) {
+                                    { .color = { .float32 = { 0.f, 0.f, 0.f, 0.f } } }
+                                }
+                            },
+                            VK_SUBPASS_CONTENTS_INLINE);
+
+      gsk_vulkan_render_pass_draw_rect (self, render, layout_count, pipeline_layout, command_buffer);
+
+      vkCmdEndRenderPass (command_buffer);
+    }
+}
diff --git a/gsk/gskvulkanrenderpassprivate.h b/gsk/gskvulkanrenderpassprivate.h
index 808ea88..3af9470 100644
--- a/gsk/gskvulkanrenderpassprivate.h
+++ b/gsk/gskvulkanrenderpassprivate.h
@@ -11,36 +11,33 @@
 G_BEGIN_DECLS
 
 
-GskVulkanRenderPass *   gsk_vulkan_render_pass_new                      (GdkVulkanContext       *context);
+GskVulkanRenderPass *   gsk_vulkan_render_pass_new                      (GdkVulkanContext       *context,
+                                                                         GskVulkanImage         *target,
+                                                                         int                     
scale_factor,
+                                                                         graphene_rect_t        *viewport,
+                                                                         cairo_region_t         *clip,
+                                                                         VkSemaphore             
signal_semaphore);
+
 void                    gsk_vulkan_render_pass_free                     (GskVulkanRenderPass    *self);
 
 void                    gsk_vulkan_render_pass_add                      (GskVulkanRenderPass    *self,
                                                                          GskVulkanRender        *render,
-                                                                         const graphene_matrix_t*mvp,
-                                                                         const graphene_rect_t  *viewport,
                                                                          GskRenderNode          *node);
 
 void                    gsk_vulkan_render_pass_upload                   (GskVulkanRenderPass    *self,
                                                                          GskVulkanRender        *render,
                                                                          GskVulkanUploader      *uploader);
-
-gsize                   gsk_vulkan_render_pass_count_vertex_data        (GskVulkanRenderPass    *self);
-gsize                   gsk_vulkan_render_pass_collect_vertex_data      (GskVulkanRenderPass    *self,
-                                                                         GskVulkanRender        *render,
-                                                                         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);
 void                    gsk_vulkan_render_pass_draw                     (GskVulkanRenderPass    *self,
                                                                          GskVulkanRender        *render,
-                                                                         GskVulkanBuffer        
*vertex_buffer,
                                                                          guint                   
layout_count,
                                                                          VkPipelineLayout       
*pipeline_layout,
                                                                          VkCommandBuffer         
command_buffer);
+gsize                   gsk_vulkan_render_pass_get_wait_semaphores      (GskVulkanRenderPass    *self,
+                                                                         VkSemaphore           **semaphores);
+gsize                   gsk_vulkan_render_pass_get_signal_semaphores    (GskVulkanRenderPass    *self,
+                                                                         VkSemaphore           **semaphores);
 
 G_END_DECLS
 
diff --git a/gsk/gskvulkanrenderprivate.h b/gsk/gskvulkanrenderprivate.h
index 4bd2484..ec553be 100644
--- a/gsk/gskvulkanrenderprivate.h
+++ b/gsk/gskvulkanrenderprivate.h
@@ -69,6 +69,13 @@ void                    gsk_vulkan_render_add_cleanup_image             (GskVulk
 void                    gsk_vulkan_render_add_node                      (GskVulkanRender        *self,
                                                                          GskRenderNode          *node);
 
+void                    gsk_vulkan_render_add_node_for_texture          (GskVulkanRender        *self,
+                                                                         GskRenderNode          *node,
+                                                                         const graphene_rect_t *bounds,
+                                                                         GskVulkanImage        *target,
+                                                                         VkSemaphore            semaphore);
+
+
 void                    gsk_vulkan_render_upload                        (GskVulkanRender        *self);
 
 GskVulkanPipeline *     gsk_vulkan_render_get_pipeline                  (GskVulkanRender        *self,
@@ -83,6 +90,8 @@ void                    gsk_vulkan_render_draw                          (GskVulk
 void                    gsk_vulkan_render_submit                        (GskVulkanRender        *self);
 
 GskTexture *            gsk_vulkan_render_download_target               (GskVulkanRender        *self);
+VkFramebuffer           gsk_vulkan_render_get_framebuffer               (GskVulkanRender        *self,
+                                                                         GskVulkanImage         *image);
 
 G_END_DECLS
 


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