[gtk+/wip/otte/vulkan: 20/28] vulkan: Create framebuffers from GskVulkanRender object



commit cb130e82151d4c4ee94139296f329d648561af61
Author: Benjamin Otte <otte redhat com>
Date:   Thu Dec 8 22:35:16 2016 +0100

    vulkan: Create framebuffers from GskVulkanRender object
    
    Also create them on-demand, as they need to be created per-image and
    per-framebuffer, so we don't want to create loads of them.

 gsk/gskvulkanrender.c        |   90 +++++++++++++++++++++++++++++++++++++++---
 gsk/gskvulkanrenderer.c      |   80 +++++--------------------------------
 gsk/gskvulkanrenderprivate.h |    8 ++--
 3 files changed, 98 insertions(+), 80 deletions(-)
---
diff --git a/gsk/gskvulkanrender.c b/gsk/gskvulkanrender.c
index fa51779..8498ee1 100644
--- a/gsk/gskvulkanrender.c
+++ b/gsk/gskvulkanrender.c
@@ -20,11 +20,15 @@ struct _GskVulkanRender
   VkExtent2D size;
   VkRect2D scissor;
 
+  GHashTable *framebuffers;
   VkCommandPool command_pool;
+  VkRenderPass render_pass;
   VkFence fence;
 
   VkCommandBuffer command_buffer;
 
+  GskVulkanImage *target;
+
   GSList *render_passes;
   GSList *cleanup_images;
 };
@@ -58,7 +62,8 @@ gsk_vulkan_render_compute_mvp (GskVulkanRender *self)
 
 GskVulkanRender *
 gsk_vulkan_render_new (GskRenderer      *renderer,
-                       GdkVulkanContext *context)
+                       GdkVulkanContext *context,
+                       VkRenderPass      pretend_you_didnt_see_me)
 {
   GskVulkanRender *self;
   VkDevice device;
@@ -67,6 +72,8 @@ gsk_vulkan_render_new (GskRenderer      *renderer,
 
   self->vulkan = context;
   self->renderer = renderer;
+  self->render_pass = pretend_you_didnt_see_me;
+  self->framebuffers = g_hash_table_new (g_direct_hash, g_direct_equal);
 
   device = gdk_vulkan_context_get_device (self->vulkan);
 
@@ -90,6 +97,58 @@ gsk_vulkan_render_new (GskRenderer      *renderer,
   return self;
 }
 
+typedef struct {
+  VkFramebuffer framebuffer;
+} HashFramebufferEntry;
+
+static void
+gsk_vulkan_render_remove_framebuffer_from_image (gpointer  data,
+                                                 GObject  *image)
+{
+  GskVulkanRender *self = data;
+  HashFramebufferEntry *fb;
+
+  fb = g_hash_table_lookup (self->framebuffers, image);
+  g_hash_table_remove (self->framebuffers, image);
+
+  vkDestroyFramebuffer (gdk_vulkan_context_get_device (self->vulkan),
+                        fb->framebuffer,
+                        NULL);
+
+  g_slice_free (HashFramebufferEntry, fb);
+}
+
+static VkFramebuffer
+gsk_vulkan_render_get_framebuffer (GskVulkanRender *self,
+                                   GskVulkanImage  *image)
+{
+  HashFramebufferEntry *fb;
+
+  fb = g_hash_table_lookup (self->framebuffers, image);
+  if (fb)
+    return fb->framebuffer;
+
+  fb = g_slice_new0 (HashFramebufferEntry);
+  GSK_VK_CHECK (vkCreateFramebuffer, gdk_vulkan_context_get_device (self->vulkan),
+                                     &(VkFramebufferCreateInfo) {
+                                         .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
+                                         .renderPass = self->render_pass,
+                                         .attachmentCount = 1,
+                                         .pAttachments = (VkImageView[1]) {
+                                             gsk_vulkan_image_get_image_view (image)
+                                         },
+                                         .width = gsk_vulkan_image_get_width (image),
+                                         .height = gsk_vulkan_image_get_height (image),
+                                         .layers = 1
+                                     },
+                                     NULL,
+                                     &fb->framebuffer);
+  g_hash_table_insert (self->framebuffers, image, fb);
+  g_object_weak_ref (G_OBJECT (image), gsk_vulkan_render_remove_framebuffer_from_image, self);
+
+  return fb->framebuffer;
+}
+
 void
 gsk_vulkan_render_add_cleanup_image (GskVulkanRender *self,
                                      GskVulkanImage  *image)
@@ -161,8 +220,6 @@ gsk_vulkan_render_collect_vertices (GskVulkanRender *self)
 void
 gsk_vulkan_render_draw (GskVulkanRender   *self,
                         GskVulkanPipeline *pipeline,
-                        VkRenderPass       render_pass,
-                        VkFramebuffer      framebuffer,
                         VkDescriptorSet    descriptor_set,
                         VkSampler          sampler)
 {
@@ -196,8 +253,8 @@ gsk_vulkan_render_draw (GskVulkanRender   *self,
   vkCmdBeginRenderPass (self->command_buffer,
                         &(VkRenderPassBeginInfo) {
                             .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
-                            .renderPass = render_pass,
-                            .framebuffer = framebuffer,
+                            .renderPass = self->render_pass,
+                            .framebuffer = gsk_vulkan_render_get_framebuffer (self, self->target),
                             .renderArea = { 
                                 { 0, 0 },
                                 { self->size.width, self->size.height }
@@ -305,17 +362,35 @@ gsk_vulkan_render_cleanup (GskVulkanRender *self)
   self->render_passes = NULL;
   g_slist_free_full (self->cleanup_images, g_object_unref);
   self->cleanup_images = NULL;
+
+  g_clear_object (&self->target);
 }
 
 void
 gsk_vulkan_render_free (GskVulkanRender *self)
 {
+  GHashTableIter iter;
+  gpointer key, value;
   VkDevice device;
   
   gsk_vulkan_render_cleanup (self);
 
   device = gdk_vulkan_context_get_device (self->vulkan);
 
+  g_hash_table_iter_init (&iter, self->framebuffers);
+  while (g_hash_table_iter_next (&iter, &key, &value))
+    {
+      HashFramebufferEntry *fb = value;
+
+      vkDestroyFramebuffer (gdk_vulkan_context_get_device (self->vulkan),
+                            fb->framebuffer,
+                            NULL);
+      g_slice_free (HashFramebufferEntry, fb);
+      g_object_weak_unref (G_OBJECT (key), gsk_vulkan_render_remove_framebuffer_from_image, self);
+      g_hash_table_iter_remove (&iter);
+    }
+  g_hash_table_unref (self->framebuffers);
+
   vkDestroyFence (device,
                   self->fence,
                   NULL);
@@ -333,12 +408,15 @@ gsk_vulkan_render_is_busy (GskVulkanRender *self)
 }
 
 void
-gsk_vulkan_render_reset (GskVulkanRender *self)
+gsk_vulkan_render_reset (GskVulkanRender *self,
+                         GskVulkanImage  *target)
 {
   VkDevice device;
 
   gsk_vulkan_render_cleanup (self);
 
+  self->target = g_object_ref (target);
+
   gsk_vulkan_render_compute_mvp (self);
 
   device = gdk_vulkan_context_get_device (self->vulkan);
diff --git a/gsk/gskvulkanrenderer.c b/gsk/gskvulkanrenderer.c
index fe7623b..e04537d 100644
--- a/gsk/gskvulkanrenderer.c
+++ b/gsk/gskvulkanrenderer.c
@@ -15,8 +15,6 @@
 
 #include <graphene.h>
 
-typedef struct _GskVulkanTarget GskVulkanTarget;
-
 #ifdef G_ENABLE_DEBUG
 typedef struct {
   GQuark cpu_time;
@@ -31,7 +29,7 @@ struct _GskVulkanRenderer
   GdkVulkanContext *vulkan;
 
   guint n_targets;
-  GskVulkanTarget **targets;
+  GskVulkanImage **targets;
 
   VkRenderPass render_pass;
 
@@ -56,63 +54,6 @@ struct _GskVulkanRendererClass
 
 G_DEFINE_TYPE (GskVulkanRenderer, gsk_vulkan_renderer, GSK_TYPE_RENDERER)
 
-struct _GskVulkanTarget {
-  GskVulkanImage *image;
-  VkFramebuffer framebuffer;
-}; 
-
-static GskVulkanTarget *
-gsk_vulkan_target_new_for_image (GskVulkanRenderer *self,
-                                 VkImage            image,
-                                 gsize              width,
-                                 gsize              height)
-{
-  GskVulkanTarget *target;
-  VkDevice device;
-
-  device = gdk_vulkan_context_get_device (self->vulkan);
-
-  target = g_slice_new0 (GskVulkanTarget);
-
-  target->image = gsk_vulkan_image_new_for_swapchain (self->vulkan,
-                                                      image,
-                                                      gdk_vulkan_context_get_image_format (self->vulkan),
-                                                      width, height);
-  GSK_VK_CHECK (vkCreateFramebuffer, device,
-                                     &(VkFramebufferCreateInfo) {
-                                         .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
-                                         .renderPass = self->render_pass,
-                                         .attachmentCount = 1,
-                                         .pAttachments = (VkImageView[1]) {
-                                             gsk_vulkan_image_get_image_view (target->image)
-                                         },
-                                         .width = width,
-                                         .height = height,
-                                         .layers = 1
-                                     },
-                                     NULL,
-                                     &target->framebuffer);
-
-  return target;
-}
-
-static void
-gsk_vulkan_target_free (GskVulkanRenderer *self,
-                        GskVulkanTarget   *target)
-{
-  VkDevice device;
-
-  device = gdk_vulkan_context_get_device (self->vulkan);
-
-  vkDestroyFramebuffer (device,
-                        target->framebuffer,
-                        NULL);
-
-  g_object_unref (target->image);
-
-  g_slice_free (GskVulkanTarget, target);
-}
-
 static void
 gsk_vulkan_renderer_free_targets (GskVulkanRenderer *self)
 {
@@ -120,7 +61,7 @@ gsk_vulkan_renderer_free_targets (GskVulkanRenderer *self)
 
   for (i = 0; i < self->n_targets; i++)
     {
-      gsk_vulkan_target_free (self, self->targets[i]);
+      g_object_unref (self->targets[i]);
     }
 
   g_clear_pointer (&self->targets, g_free);
@@ -139,7 +80,7 @@ gsk_vulkan_renderer_update_images_cb (GdkVulkanContext  *context,
   gsk_vulkan_renderer_free_targets (self);
 
   self->n_targets = gdk_vulkan_context_get_n_images (context);
-  self->targets = g_new (GskVulkanTarget *, self->n_targets);
+  self->targets = g_new (GskVulkanImage *, self->n_targets);
 
   window = gsk_renderer_get_window (GSK_RENDERER (self));
   scale_factor = gdk_window_get_scale_factor (window);
@@ -148,9 +89,10 @@ gsk_vulkan_renderer_update_images_cb (GdkVulkanContext  *context,
 
   for (i = 0; i < self->n_targets; i++)
     {
-      self->targets[i] = gsk_vulkan_target_new_for_image (self,
-                                                          gdk_vulkan_context_get_image (context, i),
-                                                          width, height);
+      self->targets[i] = gsk_vulkan_image_new_for_swapchain (self->vulkan,
+                                                             gdk_vulkan_context_get_image (context, i),
+                                                             gdk_vulkan_context_get_image_format 
(self->vulkan),
+                                                             width, height);
     }
 }
 
@@ -259,7 +201,7 @@ gsk_vulkan_renderer_realize (GskRenderer  *renderer,
   gsk_vulkan_renderer_update_images_cb (self->vulkan, self);
 
   /* We will need at least one render object, so create it early where we can still fail fine */
-  self->renders = g_slist_prepend (self->renders, gsk_vulkan_render_new (renderer, self->vulkan));
+  self->renders = g_slist_prepend (self->renders, gsk_vulkan_render_new (renderer, self->vulkan, 
self->render_pass));
 
   return TRUE;
 }
@@ -329,19 +271,17 @@ gsk_vulkan_renderer_render (GskRenderer   *renderer,
     }
   else
     {
-      render = gsk_vulkan_render_new (renderer, self->vulkan);
+      render = gsk_vulkan_render_new (renderer, self->vulkan, self->render_pass);
       self->renders = g_slist_prepend (self->renders, render);
     }
 
-  gsk_vulkan_render_reset (render);
+  gsk_vulkan_render_reset (render, self->targets[gdk_vulkan_context_get_draw_index (self->vulkan)]);
 
   gsk_vulkan_render_add_node (render, root);
 
   gsk_vulkan_render_upload (render);
 
   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_render_submit (render);
diff --git a/gsk/gskvulkanrenderprivate.h b/gsk/gskvulkanrenderprivate.h
index a86e5c8..a17de86 100644
--- a/gsk/gskvulkanrenderprivate.h
+++ b/gsk/gskvulkanrenderprivate.h
@@ -21,11 +21,13 @@ struct _GskVulkanVertex
 };
 
 GskVulkanRender *       gsk_vulkan_render_new                           (GskRenderer            *renderer,
-                                                                         GdkVulkanContext       *context);
+                                                                         GdkVulkanContext       *context,
+                                                                         VkRenderPass            
pretend_you_didnt_see_me);
 void                    gsk_vulkan_render_free                          (GskVulkanRender        *self);
 
 gboolean                gsk_vulkan_render_is_busy                       (GskVulkanRender        *self);
-void                    gsk_vulkan_render_reset                         (GskVulkanRender        *self);
+void                    gsk_vulkan_render_reset                         (GskVulkanRender        *self,
+                                                                         GskVulkanImage         *target);
 
 GskRenderer *           gsk_vulkan_render_get_renderer                  (GskVulkanRender        *self);
 
@@ -39,8 +41,6 @@ void                    gsk_vulkan_render_upload                        (GskVulk
 
 void                    gsk_vulkan_render_draw                          (GskVulkanRender        *self,
                                                                          GskVulkanPipeline      *pipeline,
-                                                                         VkRenderPass            render_pass,
-                                                                         VkFramebuffer           framebuffer,
                                                                          VkDescriptorSet         
descriptor_set,
                                                                          VkSampler               sampler);
 


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