[gtk+/wip/otte/vulkan: 9/28] vulkan: Add GskVulkanRenderPass



commit 8a4e4079271d213a0a5827765f3e73bec78261fc
Author: Benjamin Otte <otte redhat com>
Date:   Thu Dec 8 13:26:36 2016 +0100

    vulkan: Add GskVulkanRenderPass
    
    And move the actual rendering code there.
    
    A RenderPass is a collection of operations on the same target that
    get executed one after another. It roughly targets VkRenderPass or
    rather the subpasses of a VkRenderPass.
    
    For now, only the infrastructure is there. No real stuff is happening.

 gsk/Makefile.am                  |    2 +
 gsk/gskvulkanrender.c            |  200 ++++++++++++++++++++++++++++++++
 gsk/gskvulkanrenderer.c          |  202 ++-------------------------------
 gsk/gskvulkanrenderpass.c        |  233 ++++++++++++++++++++++++++++++++++++++
 gsk/gskvulkanrenderpassprivate.h |   37 ++++++
 gsk/gskvulkanrenderprivate.h     |   42 +++++++-
 6 files changed, 520 insertions(+), 196 deletions(-)
---
diff --git a/gsk/Makefile.am b/gsk/Makefile.am
index bde8dbe..32f37d3 100644
--- a/gsk/Makefile.am
+++ b/gsk/Makefile.am
@@ -30,6 +30,7 @@ gsk_private_vulan_source_h = \
        gskvulkanpipelineprivate.h \
        gskvulkanrenderprivate.h \
        gskvulkanrendererprivate.h \
+       gskvulkanrenderpassprivate.h \
        gskvulkanshaderprivate.h
 gsk_private_vulkan_source_c = \
        gskvulkanbuffer.c \
@@ -38,6 +39,7 @@ gsk_private_vulkan_source_c = \
        gskvulkanpipeline.c \
        gskvulkanrender.c \
        gskvulkanrenderer.c \
+       gskvulkanrenderpass.c \
        gskvulkanshader.c
 endif
 
diff --git a/gsk/gskvulkanrender.c b/gsk/gskvulkanrender.c
index 3dff0bf..c57e701 100644
--- a/gsk/gskvulkanrender.c
+++ b/gsk/gskvulkanrender.c
@@ -2,16 +2,56 @@
 
 #include "gskvulkanrenderprivate.h"
 
+#include "gskrendererprivate.h"
+#include "gskvulkanbufferprivate.h"
 #include "gskvulkanpipelineprivate.h"
+#include "gskvulkanrenderpassprivate.h"
+
+#define ORTHO_NEAR_PLANE        -10000
+#define ORTHO_FAR_PLANE          10000
+
+static void
+gsk_vulkan_render_compute_mvp (GskVulkanRender *self)
+{
+  GdkWindow *window = gsk_renderer_get_window (self->renderer);
+  graphene_matrix_t modelview, projection;
+  cairo_rectangle_int_t extents;
+
+  cairo_region_get_extents (gdk_drawing_context_get_clip (gsk_renderer_get_drawing_context (self->renderer)),
+                            &extents);
+
+  self->scale_factor = gsk_renderer_get_scale_factor (self->renderer);
+  self->size.width = gdk_window_get_width (window) * self->scale_factor;
+  self->size.height = gdk_window_get_height (window) * self->scale_factor;
+  self->scissor.offset.x = extents.x * self->scale_factor;
+  self->scissor.offset.y = extents.y * self->scale_factor;
+  self->scissor.extent.width = extents.width * self->scale_factor;
+  self->scissor.extent.height = extents.height * self->scale_factor;
+
+  graphene_matrix_init_scale (&modelview, self->scale_factor, self->scale_factor, 1.0);
+  graphene_matrix_init_ortho (&projection,
+                              0, self->size.width,
+                              0, self->size.height,
+                              ORTHO_NEAR_PLANE,
+                              ORTHO_FAR_PLANE);
+  graphene_matrix_multiply (&modelview, &projection, &self->mvp);
+}
 
 void
 gsk_vulkan_render_init (GskVulkanRender    *self,
+                        GskRenderer        *renderer,
                         GdkVulkanContext   *context,
                         VkCommandPool       command_pool)
 {
   self->vulkan = context;
+  self->renderer = renderer;
   self->command_pool = command_pool;
 
+  self->render_passes = NULL;
+  self->cleanup_images = NULL;
+
+  gsk_vulkan_render_compute_mvp (self);
+
   GSK_VK_CHECK (vkAllocateCommandBuffers, gdk_vulkan_context_get_device (self->vulkan),
                                           &(VkCommandBufferAllocateInfo) {
                                               .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
@@ -29,6 +69,163 @@ gsk_vulkan_render_init (GskVulkanRender    *self,
 }
 
 void
+gsk_vulkan_render_add_cleanup_image (GskVulkanRender *self,
+                                     GskVulkanImage  *image)
+{
+  self->cleanup_images = g_slist_prepend (self->cleanup_images, image);
+}
+
+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_node (pass, self, node);
+}
+
+void
+gsk_vulkan_render_upload (GskVulkanRender *self)
+{
+  GSList *l;
+
+  for (l = self->render_passes; l; l = l->next)
+    {
+      gsk_vulkan_render_pass_upload (l->data, self);
+    }
+}
+
+static gsize
+gsk_vulkan_renderer_count_vertices (GskVulkanRender *self)
+{
+  gsize count;
+  GSList *l;
+
+  count = 0;
+  for (l = self->render_passes; l; l = l->next)
+    {
+      count += gsk_vulkan_render_pass_count_vertices (l->data);
+    }
+
+  return count;
+}
+
+static GskVulkanBuffer *
+gsk_vulkan_render_collect_vertices (GskVulkanRender *self)
+{
+  GskVulkanBuffer *buffer;
+  GskVulkanVertex *vertices;
+  GSList *l;
+  gsize offset, count;
+  
+  offset = 0;
+  count = gsk_vulkan_renderer_count_vertices (self);
+  buffer = gsk_vulkan_buffer_new (self->vulkan, sizeof (GskVulkanVertex) * count);
+  vertices = (GskVulkanVertex *) gsk_vulkan_buffer_map (buffer);
+
+  for (l = self->render_passes; l; l = l->next)
+    {
+      offset += gsk_vulkan_render_pass_collect_vertices (l->data, vertices, offset, count - offset);
+      g_assert (offset <= count);
+    }
+
+  gsk_vulkan_buffer_unmap (buffer);
+
+  return buffer;
+}
+
+void
+gsk_vulkan_render_draw (GskVulkanRender   *self,
+                        GskVulkanPipeline *pipeline,
+                        VkRenderPass       render_pass,
+                        VkFramebuffer      framebuffer,
+                        VkDescriptorSet    descriptor_set,
+                        VkSampler          sampler)
+{
+  GskVulkanBuffer *buffer;
+  GSList *l;
+
+  buffer = gsk_vulkan_render_collect_vertices (self);
+
+  for (l = self->render_passes; l; l = l->next)
+    {
+      gsk_vulkan_render_pass_update_descriptor_sets (l->data, descriptor_set, sampler);
+    }
+
+  vkCmdSetViewport (self->command_buffer,
+                    0,
+                    1,
+                    &(VkViewport) {
+                      .x = 0,
+                      .y = 0,
+                      .width = self->size.width,
+                      .height = self->size.height,
+                      .minDepth = 0,
+                      .maxDepth = 1
+                    });
+
+  vkCmdSetScissor (self->command_buffer,
+                   0,
+                   1,
+                   &self->scissor);
+
+  vkCmdBeginRenderPass (self->command_buffer,
+                        &(VkRenderPassBeginInfo) {
+                            .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
+                            .renderPass = render_pass,
+                            .framebuffer = framebuffer,
+                            .renderArea = { 
+                                { 0, 0 },
+                                { self->size.width, self->size.height }
+                            },
+                            .clearValueCount = 1,
+                            .pClearValues = (VkClearValue [1]) {
+                                { .color = { .float32 = { 0.f, 0.f, 0.f, 0.f } } }
+                            }
+                        },
+                        VK_SUBPASS_CONTENTS_INLINE);
+
+  vkCmdBindPipeline (self->command_buffer,
+                     VK_PIPELINE_BIND_POINT_GRAPHICS,
+                     gsk_vulkan_pipeline_get_pipeline (pipeline));
+
+  vkCmdBindDescriptorSets (self->command_buffer,
+                           VK_PIPELINE_BIND_POINT_GRAPHICS,
+                           gsk_vulkan_pipeline_get_pipeline_layout (pipeline),
+                           0,
+                           1,
+                           &descriptor_set,
+                           0,
+                           NULL);
+
+  vkCmdBindVertexBuffers (self->command_buffer,
+                          0,
+                          1,
+                          (VkBuffer[1]) {
+                              gsk_vulkan_buffer_get_buffer (buffer)
+                          },
+                          (VkDeviceSize[1]) { 0 });
+
+  vkCmdPushConstants (self->command_buffer,
+                      gsk_vulkan_pipeline_get_pipeline_layout (pipeline),
+                      VK_SHADER_STAGE_VERTEX_BIT,
+                      0,
+                      sizeof (graphene_matrix_t),
+                      &self->mvp);
+
+  for (l = self->render_passes; l; l = l->next)
+    {
+      gsk_vulkan_render_pass_draw (l->data, self);
+    }
+
+  vkCmdEndRenderPass (self->command_buffer);
+
+  gsk_vulkan_buffer_free (buffer);
+}
+
+void
 gsk_vulkan_render_submit (GskVulkanRender *self,
                           VkFence          fence)
 {
@@ -66,4 +263,7 @@ gsk_vulkan_render_finish (GskVulkanRender *self)
   GSK_VK_CHECK (vkResetCommandPool, gdk_vulkan_context_get_device (self->vulkan),
                                     self->command_pool,
                                     0);
+
+  g_slist_free_full (self->render_passes, (GDestroyNotify) gsk_vulkan_render_pass_free);
+  g_slist_free_full (self->cleanup_images, (GDestroyNotify) gsk_vulkan_image_free);
 }
diff --git a/gsk/gskvulkanrenderer.c b/gsk/gskvulkanrenderer.c
index 9856f3f..8bf422e 100644
--- a/gsk/gskvulkanrenderer.c
+++ b/gsk/gskvulkanrenderer.c
@@ -332,201 +332,12 @@ gsk_vulkan_renderer_unrealize (GskRenderer *renderer)
   g_clear_object (&self->vulkan);
 }
 
-static GskVulkanImage *
-gsk_vulkan_renderer_prepare_render (GskVulkanRenderer *self,
-                                    VkCommandBuffer    command_buffer,
-                                    GskRenderNode     *root)
-{
-  GdkWindow *window;
-  GskRenderer *fallback;
-  GskVulkanImage *image;
-  cairo_surface_t *surface;
-  cairo_t *cr;
-
-  window = gsk_renderer_get_window (GSK_RENDERER (self));
-  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
-                                        gdk_window_get_width (window),
-                                        gdk_window_get_height (window));
-  cr = cairo_create (surface);
-  fallback = gsk_renderer_create_fallback (GSK_RENDERER (self),
-                                           &GRAPHENE_RECT_INIT(
-                                               0, 0,
-                                               gdk_window_get_width (window),
-                                               gdk_window_get_height (window)
-                                           ),
-                                           cr);
-
-  gsk_renderer_render (fallback, root, NULL);
-  g_object_unref (fallback);
-  
-  cairo_destroy (cr);
-
-  image = gsk_vulkan_image_new_from_data (self->vulkan,
-                                          command_buffer,
-                                          cairo_image_surface_get_data (surface),
-                                          cairo_image_surface_get_width (surface),
-                                          cairo_image_surface_get_height (surface),
-                                          cairo_image_surface_get_stride (surface));
-  cairo_surface_destroy (surface);
-
-  return image;
-}
-
-static void
-gsk_vulkan_renderer_do_render_commands (GskVulkanRenderer *self,
-                                        VkCommandBuffer    command_buffer)
-{
-  GskVulkanBuffer *buffer;
-  GdkWindow *window = gsk_renderer_get_window (GSK_RENDERER (self));
-  int width = gdk_window_get_width (window);
-  int height = gdk_window_get_height (window);
-  float pts[] = {
-    0.0,   0.0,     0.0, 0.0,
-    width, 0.0,     1.0, 0.0,
-    0.0,   height,  0.0, 1.0,
-
-    0.0,   height,  0.0, 1.0,
-    width, 0.0,     1.0, 0.0,
-    width, height,  1.0, 1.0
-  };
-  guchar *data;
-
-  buffer = gsk_vulkan_buffer_new (self->vulkan, sizeof (pts));
-
-  data = gsk_vulkan_buffer_map (buffer);
-  memcpy (data, pts, sizeof (pts));
-  gsk_vulkan_buffer_unmap (buffer);
-
-  vkCmdBindPipeline (command_buffer,
-                     VK_PIPELINE_BIND_POINT_GRAPHICS,
-                     gsk_vulkan_pipeline_get_pipeline (self->pipeline));
-
-  vkCmdBindDescriptorSets (command_buffer,
-                           VK_PIPELINE_BIND_POINT_GRAPHICS,
-                           gsk_vulkan_pipeline_get_pipeline_layout (self->pipeline),
-                           0,
-                           1,
-                           &self->descriptor_set,
-                           0,
-                           NULL);
-
-  vkCmdBindVertexBuffers (command_buffer,
-                          0,
-                          1,
-                          (VkBuffer[1]) {
-                              gsk_vulkan_buffer_get_buffer (buffer)
-                          },
-                          (VkDeviceSize[1]) { 0 });
-
-  vkCmdDraw (command_buffer,
-             6, 1,
-             0, 0);
-
-  gsk_vulkan_buffer_free (buffer);
-}
-
-#define ORTHO_NEAR_PLANE        -10000
-#define ORTHO_FAR_PLANE          10000
-
-static void
-gsk_vulkan_renderer_do_render_pass (GskVulkanRenderer *self,
-                                    VkCommandBuffer    command_buffer,
-                                    GskVulkanImage    *image)
-{
-  GdkRectangle extents;
-  GdkWindow *window;
-  int scale_factor, unscaled_width, unscaled_height;
-  graphene_matrix_t modelview, projection, mvp;
-
-  window = gsk_renderer_get_window (GSK_RENDERER (self));
-  cairo_region_get_extents (gdk_drawing_context_get_clip (gsk_renderer_get_drawing_context (GSK_RENDERER 
(self))),
-                            &extents);
-  scale_factor = gsk_renderer_get_scale_factor (GSK_RENDERER (self));
-  unscaled_width = gdk_window_get_width (window) * scale_factor;
-  unscaled_height = gdk_window_get_height (window) * scale_factor;
-
-  vkUpdateDescriptorSets (gdk_vulkan_context_get_device (self->vulkan),
-                          1,
-                          (VkWriteDescriptorSet[1]) {
-                              {
-                                  .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
-                                  .dstSet = self->descriptor_set,
-                                  .dstBinding = 0,
-                                  .dstArrayElement = 0,
-                                  .descriptorCount = 1,
-                                  .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
-                                  .pImageInfo = &(VkDescriptorImageInfo) {
-                                      .sampler = self->sampler,
-                                      .imageView = gsk_vulkan_image_get_image_view (image),
-                                      .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
-                                  }
-                              }
-                          },
-                          0, NULL);
-
-  vkCmdBeginRenderPass (command_buffer,
-                        &(VkRenderPassBeginInfo) {
-                            .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
-                            .renderPass = self->render_pass,
-                            .framebuffer = self->targets[gdk_vulkan_context_get_draw_index 
(self->vulkan)]->framebuffer,
-                            .renderArea = { 
-                                { 0, 0 },
-                                { unscaled_width, unscaled_height }
-                            },
-                            .clearValueCount = 1,
-                            .pClearValues = (VkClearValue [1]) {
-                                { .color = { .float32 = { 0.f, 0.f, 0.f, 0.f } } }
-                            }
-                        },
-                        VK_SUBPASS_CONTENTS_INLINE);
-
-  vkCmdSetViewport (command_buffer,
-                    0,
-                    1,
-                    &(VkViewport) {
-                      .x = 0,
-                      .y = 0,
-                      .width = unscaled_width,
-                      .height = unscaled_height,
-                      .minDepth = 0,
-                      .maxDepth = 1
-                    });
-
-  vkCmdSetScissor (command_buffer,
-                   0,
-                   1,
-                   &(VkRect2D) {
-                       { extents.x * scale_factor, extents.y * scale_factor },
-                       { extents.width * scale_factor, extents.height * scale_factor }
-                   });
-
-  graphene_matrix_init_scale (&modelview, scale_factor, scale_factor, 1.0);
-  graphene_matrix_init_ortho (&projection,
-                              0, unscaled_width,
-                              0, unscaled_height,
-                              ORTHO_NEAR_PLANE,
-                              ORTHO_FAR_PLANE);
-  graphene_matrix_multiply (&modelview, &projection, &mvp);
-
-  vkCmdPushConstants (command_buffer,
-                      gsk_vulkan_pipeline_get_pipeline_layout (self->pipeline),
-                      VK_SHADER_STAGE_VERTEX_BIT,
-                      0,
-                      sizeof (graphene_matrix_t),
-                      &mvp);
-
-  gsk_vulkan_renderer_do_render_commands (self, command_buffer);
-
-  vkCmdEndRenderPass (command_buffer);
-}
-
 static void
 gsk_vulkan_renderer_render (GskRenderer   *renderer,
                             GskRenderNode *root)
 {
   GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer);
   GskVulkanRender render;
-  GskVulkanImage *image;
 #ifdef G_ENABLE_DEBUG
   GskProfiler *profiler;
   gint64 cpu_time;
@@ -537,15 +348,18 @@ gsk_vulkan_renderer_render (GskRenderer   *renderer,
   gsk_profiler_timer_begin (profiler, self->profile_timers.cpu_time);
 #endif
 
-  gsk_vulkan_render_init (&render, self->vulkan, self->command_pool);
+  gsk_vulkan_render_init (&render, renderer, self->vulkan, self->command_pool);
 
-  image = gsk_vulkan_renderer_prepare_render (self, render.command_buffer, root);
+  gsk_vulkan_render_add_node (&render, root);
 
-  gsk_vulkan_renderer_do_render_pass (self, render.command_buffer, image);
+  gsk_vulkan_render_upload (&render);
 
-  gsk_vulkan_render_submit (&render, self->command_pool_fence);
+  gsk_vulkan_render_draw (&render, self->pipeline,
+                          self->render_pass,
+                          self->targets[gdk_vulkan_context_get_draw_index (self->vulkan)]->framebuffer,
+                          self->descriptor_set, self->sampler);
 
-  gsk_vulkan_image_free (image);
+  gsk_vulkan_render_submit (&render, self->command_pool_fence);
 
   gsk_vulkan_render_finish (&render);
 
diff --git a/gsk/gskvulkanrenderpass.c b/gsk/gskvulkanrenderpass.c
new file mode 100644
index 0000000..373bc6c
--- /dev/null
+++ b/gsk/gskvulkanrenderpass.c
@@ -0,0 +1,233 @@
+#include "config.h"
+
+#include "gskvulkanrenderpassprivate.h"
+
+#include "gskvulkanimageprivate.h"
+#include "gskrendernodeprivate.h"
+#include "gskrenderer.h"
+
+typedef struct _GskVulkanRenderOp GskVulkanRenderOp;
+
+typedef enum {
+  GSK_VULKAN_OP_FALLBACK
+} GskVulkanOpType;
+
+struct _GskVulkanRenderOp
+{
+  GskVulkanOpType      type;
+  GskRenderNode       *node; /* node that's the source of this op */
+  GskVulkanRenderPass *pass; /* render pass required to set up node */
+  GskVulkanImage      *source; /* source image to render */
+  gsize                vertex_offset; /* offset into vertex buffer */
+  gsize                vertex_count; /* number of vertices */
+};
+
+struct _GskVulkanRenderPass
+{
+  GdkVulkanContext *vulkan;
+
+  GArray *render_ops;
+};
+
+GskVulkanRenderPass *
+gsk_vulkan_render_pass_new (GdkVulkanContext *context)
+{
+  GskVulkanRenderPass *self;
+
+  self = g_slice_new0 (GskVulkanRenderPass);
+  self->vulkan = g_object_ref (context);
+  self->render_ops = g_array_new (FALSE, FALSE, sizeof (GskVulkanRenderOp));
+
+  return self;
+}
+
+void
+gsk_vulkan_render_pass_free (GskVulkanRenderPass *self)
+{
+  g_array_unref (self->render_ops);
+  g_object_unref (self->vulkan);
+
+  g_slice_free (GskVulkanRenderPass, self);
+}
+
+void
+gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
+                                 GskVulkanRender     *render,
+                                 GskRenderNode       *node)
+{
+  GskVulkanRenderOp op = {
+    .type = GSK_VULKAN_OP_FALLBACK,
+    .node = node
+  };
+
+  g_array_append_val (self->render_ops, op);
+}
+
+static void
+gsk_vulkan_render_pass_upload_fallback (GskVulkanRenderOp *op,
+                                        GskVulkanRender   *render)
+{
+  graphene_rect_t bounds;
+  GskRenderer *fallback;
+  cairo_surface_t *surface;
+  cairo_t *cr;
+
+  gsk_render_node_get_bounds (op->node, &bounds);
+
+  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+                                        ceil (bounds.size.width),
+                                        ceil (bounds.size.height));
+  cr = cairo_create (surface);
+  cairo_translate (cr, bounds.origin.x, bounds.origin.y);
+
+  fallback = gsk_renderer_create_fallback (render->renderer,
+                                           &bounds,
+                                           cr);
+  gsk_renderer_render (fallback, op->node, NULL);
+  g_object_unref (fallback);
+  
+  cairo_destroy (cr);
+
+  op->source = gsk_vulkan_image_new_from_data (render->vulkan,
+                                               render->command_buffer,
+                                               cairo_image_surface_get_data (surface),
+                                               cairo_image_surface_get_width (surface),
+                                               cairo_image_surface_get_height (surface),
+                                               cairo_image_surface_get_stride (surface));
+
+  cairo_surface_destroy (surface);
+
+  gsk_vulkan_render_add_cleanup_image (render, op->source);
+}
+
+void
+gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
+                               GskVulkanRender     *render)
+{
+  GskVulkanRenderOp *op;
+  guint i;
+
+  for (i = 0; i < self->render_ops->len; i++)
+    {
+      op = &g_array_index (self->render_ops, GskVulkanRenderOp, i);
+
+      switch (op->type)
+        {
+        case GSK_VULKAN_OP_FALLBACK:
+          gsk_vulkan_render_pass_upload_fallback (op, render);
+          break;
+
+        default:
+          g_assert_not_reached ();
+          break;
+        }
+    }
+}
+
+gsize
+gsk_vulkan_render_pass_count_vertices (GskVulkanRenderPass *self)
+{
+  return self->render_ops->len * 6;
+}
+
+static gsize
+gsk_vulkan_render_op_collect_vertices (GskVulkanRenderOp *op,
+                                       GskVulkanVertex   *vertices)
+{
+  graphene_rect_t bounds;
+
+  gsk_render_node_get_bounds (op->node, &bounds);
+
+  vertices[0] = (GskVulkanVertex) { bounds.origin.x,                     bounds.origin.y,                    
  0.0, 0.0 };
+  vertices[1] = (GskVulkanVertex) { bounds.origin.x + bounds.size.width, bounds.origin.y,                    
  1.0, 0.0 };
+  vertices[2] = (GskVulkanVertex) { bounds.origin.x,                     bounds.origin.y + 
bounds.size.height, 0.0, 1.0 };
+  vertices[3] = (GskVulkanVertex) { bounds.origin.x,                     bounds.origin.y + 
bounds.size.height, 0.0, 1.0 };
+  vertices[4] = (GskVulkanVertex) { bounds.origin.x + bounds.size.width, bounds.origin.y,                    
  1.0, 0.0 };
+  vertices[5] = (GskVulkanVertex) { bounds.origin.x + bounds.size.width, bounds.origin.y + 
bounds.size.height, 1.0, 1.0 };
+
+  return 6;
+}
+
+gsize
+gsk_vulkan_render_pass_collect_vertices (GskVulkanRenderPass *self,
+                                         GskVulkanVertex     *vertices,
+                                         gsize                offset,
+                                         gsize                total)
+{
+  GskVulkanRenderOp *op;
+  gsize n;
+  guint i;
+
+  n = 0;
+  for (i = 0; i < self->render_ops->len; i++)
+    {
+      op = &g_array_index (self->render_ops, GskVulkanRenderOp, i);
+
+      switch (op->type)
+        {
+        case GSK_VULKAN_OP_FALLBACK:
+          op->vertex_offset = offset + n;
+          op->vertex_count = gsk_vulkan_render_op_collect_vertices (op, vertices + n + offset);
+          break;
+
+        default:
+          g_assert_not_reached ();
+          break;
+        }
+
+      n += op->vertex_count;
+      g_assert (n + offset <= total);
+    }
+
+  return n;
+}
+
+void
+gsk_vulkan_render_pass_update_descriptor_sets (GskVulkanRenderPass *self,
+                                               VkDescriptorSet      descriptor_set,
+                                               VkSampler            sampler)
+{
+  GskVulkanRenderOp *op;
+  guint i;
+
+  for (i = 0; i < self->render_ops->len; i++)
+    {
+      op = &g_array_index (self->render_ops, GskVulkanRenderOp, i);
+
+      vkUpdateDescriptorSets (gdk_vulkan_context_get_device (self->vulkan),
+                              1,
+                              (VkWriteDescriptorSet[1]) {
+                                  {
+                                      .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+                                      .dstSet = descriptor_set,
+                                      .dstBinding = 0,
+                                      .dstArrayElement = 0,
+                                      .descriptorCount = 1,
+                                      .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+                                      .pImageInfo = &(VkDescriptorImageInfo) {
+                                          .sampler = sampler,
+                                          .imageView = gsk_vulkan_image_get_image_view (op->source),
+                                          .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
+                                      }
+                                  }
+                              },
+                              0, NULL);
+    }
+}
+
+void
+gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self,
+                             GskVulkanRender     *render)
+{
+  GskVulkanRenderOp *op;
+  guint i;
+
+  for (i = 0; i < self->render_ops->len; i++)
+    {
+      op = &g_array_index (self->render_ops, GskVulkanRenderOp, i);
+
+      vkCmdDraw (render->command_buffer,
+                 op->vertex_count, 1,
+                 op->vertex_offset, 0);
+    }
+}
diff --git a/gsk/gskvulkanrenderpassprivate.h b/gsk/gskvulkanrenderpassprivate.h
new file mode 100644
index 0000000..eb22761
--- /dev/null
+++ b/gsk/gskvulkanrenderpassprivate.h
@@ -0,0 +1,37 @@
+#ifndef __GSK_VULKAN_RENDER_PASS_PRIVATE_H__
+#define __GSK_VULKAN_RENDER_PASS_PRIVATE_H__
+
+#include <gdk/gdk.h>
+#include <gsk/gskrendernode.h>
+
+#include "gsk/gskvulkanrenderprivate.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GskVulkanRenderPass GskVulkanRenderPass;
+
+GskVulkanRenderPass *   gsk_vulkan_render_pass_new                      (GdkVulkanContext       *context);
+void                    gsk_vulkan_render_pass_free                     (GskVulkanRenderPass    *self);
+
+void                    gsk_vulkan_render_pass_add_node                 (GskVulkanRenderPass    *self,
+                                                                         GskVulkanRender        *render,
+                                                                         GskRenderNode          *node);
+
+void                    gsk_vulkan_render_pass_upload                   (GskVulkanRenderPass    *self,
+                                                                         GskVulkanRender        *render);
+
+gsize                   gsk_vulkan_render_pass_count_vertices           (GskVulkanRenderPass    *self);
+gsize                   gsk_vulkan_render_pass_collect_vertices         (GskVulkanRenderPass    *self,
+                                                                         GskVulkanVertex        *vertices,
+                                                                         gsize                   offset,
+                                                                         gsize                   total);
+
+void                    gsk_vulkan_render_pass_update_descriptor_sets   (GskVulkanRenderPass    *self,
+                                                                         VkDescriptorSet         
descriptor_set,
+                                                                         VkSampler               sampler);
+void                    gsk_vulkan_render_pass_draw                     (GskVulkanRenderPass    *self,
+                                                                         GskVulkanRender        *render);
+
+G_END_DECLS
+
+#endif /* __GSK_VULKAN_RENDER_PASS_PRIVATE_H__ */
diff --git a/gsk/gskvulkanrenderprivate.h b/gsk/gskvulkanrenderprivate.h
index c1f3202..53f67de 100644
--- a/gsk/gskvulkanrenderprivate.h
+++ b/gsk/gskvulkanrenderprivate.h
@@ -2,28 +2,66 @@
 #define __GSK_VULKAN_RENDER_PRIVATE_H__
 
 #include <gdk/gdk.h>
+#include <gsk/gskrendernode.h>
+
+#include "gsk/gskvulkanimageprivate.h"
+#include "gsk/gskvulkanpipelineprivate.h"
 
 G_BEGIN_DECLS
 
 typedef struct _GskVulkanRender GskVulkanRender;
+typedef struct _GskVulkanVertex GskVulkanVertex;
 
 struct _GskVulkanRender
 {
+  GskRenderer *renderer;
   GdkVulkanContext *vulkan;
 
+  graphene_matrix_t mvp;
+  int scale_factor;
+  VkExtent2D size;
+  VkRect2D scissor;
+
+
   VkCommandPool command_pool;
   VkCommandBuffer command_buffer;
+
+  GSList *render_passes;
+  GSList *cleanup_images;
+};
+
+struct _GskVulkanVertex
+{
+  float x;
+  float y;
+  float tex_x;
+  float tex_y;
 };
 
 void                    gsk_vulkan_render_init                          (GskVulkanRender        *self,
+                                                                         GskRenderer            *renderer,
                                                                          GdkVulkanContext       *context,
                                                                          VkCommandPool           
command_pool);
+void                    gsk_vulkan_render_finish                        (GskVulkanRender        *self);
+
+void                    gsk_vulkan_render_add_cleanup_image             (GskVulkanRender        *self,
+                                                                         GskVulkanImage         *image);
+
+void                    gsk_vulkan_render_add_node                      (GskVulkanRender        *self,
+                                                                         GskRenderNode          *node);
+
+void                    gsk_vulkan_render_upload                        (GskVulkanRender        *self);
+
+void                    gsk_vulkan_render_draw                          (GskVulkanRender        *self,
+                                                                         GskVulkanPipeline      *pipeline,
+                                                                         VkRenderPass            render_pass,
+                                                                         VkFramebuffer           framebuffer,
+                                                                         VkDescriptorSet         
descriptor_set,
+                                                                         VkSampler               sampler);
 
 void                    gsk_vulkan_render_submit                        (GskVulkanRender        *self,
                                                                          VkFence                 fence);
 
-void                    gsk_vulkan_render_finish                        (GskVulkanRender        *self);
-
 G_END_DECLS
 
 #endif /* __GSK_VULKAN_RENDER_PRIVATE_H__ */


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