[gtk+/wip/otte/vulkan: 22/28] vulkan: Redo descriptor set handling



commit 64b981a3f3236b8d82afe32ad686acd43a7ef37b
Author: Benjamin Otte <otte redhat com>
Date:   Fri Dec 9 02:55:47 2016 +0100

    vulkan: Redo descriptor set handling
    
    First, we collect all the info about descriptor sets into a hash table,
    then we use its size to determine the amount of sets and allocate those
    before we finally go ahead and use the hash table's contents to
    initialize the descriptor sets.
    
    And then we're ready to render.

 gsk/gskvulkanrender.c            |  141 ++++++++++++++++++++++++++++++--------
 gsk/gskvulkanrenderpass.c        |   46 +++++++------
 gsk/gskvulkanrenderpassprivate.h |    6 +-
 gsk/gskvulkanrenderprivate.h     |    4 +
 4 files changed, 145 insertions(+), 52 deletions(-)
---
diff --git a/gsk/gskvulkanrender.c b/gsk/gskvulkanrender.c
index f043b43..68f43ad 100644
--- a/gsk/gskvulkanrender.c
+++ b/gsk/gskvulkanrender.c
@@ -10,6 +10,9 @@
 #define ORTHO_NEAR_PLANE        -10000
 #define ORTHO_FAR_PLANE          10000
 
+#define DESCRIPTOR_POOL_MAXSETS 128
+#define DESCRIPTOR_POOL_MAXSETS_INCREASE 128
+
 struct _GskVulkanRender
 {
   GskRenderer *renderer;
@@ -24,8 +27,12 @@ struct _GskVulkanRender
   VkCommandPool command_pool;
   VkFence fence;
   VkRenderPass render_pass;
+
+  GHashTable *descriptor_set_indexes;
   VkDescriptorPool descriptor_pool;
-  VkDescriptorSet descriptor_set;  
+  uint32_t descriptor_pool_maxsets;
+  VkDescriptorSet *descriptor_sets;  
+  gsize n_descriptor_sets;
   GskVulkanPipeline *pipeline;
 
   VkCommandBuffer command_buffer;
@@ -75,6 +82,7 @@ gsk_vulkan_render_new (GskRenderer      *renderer,
   self->vulkan = context;
   self->renderer = renderer;
   self->framebuffers = g_hash_table_new (g_direct_hash, g_direct_equal);
+  self->descriptor_set_indexes = g_hash_table_new (g_direct_hash, g_direct_equal);
 
   device = gdk_vulkan_context_get_device (self->vulkan);
 
@@ -95,10 +103,11 @@ gsk_vulkan_render_new (GskRenderer      *renderer,
                                NULL,
                                &self->fence);
 
+  self->descriptor_pool_maxsets = DESCRIPTOR_POOL_MAXSETS;
   GSK_VK_CHECK (vkCreateDescriptorPool, device,
                                         &(VkDescriptorPoolCreateInfo) {
                                             .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
-                                            .maxSets = 1,
+                                            .maxSets = self->descriptor_pool_maxsets,
                                             .poolSizeCount = 1,
                                             .pPoolSizes = (VkDescriptorPoolSize[1]) {
                                                 {
@@ -154,17 +163,6 @@ gsk_vulkan_render_new (GskRenderer      *renderer,
 
   self->pipeline = gsk_vulkan_pipeline_new (self->vulkan, self->render_pass);
 
-  GSK_VK_CHECK (vkAllocateDescriptorSets, device,
-                                          &(VkDescriptorSetAllocateInfo) {
-                                              .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
-                                              .descriptorPool = self->descriptor_pool,
-                                              .descriptorSetCount = 1,
-                                              .pSetLayouts = (VkDescriptorSetLayout[1]) {
-                                                  gsk_vulkan_pipeline_get_descriptor_set_layout 
(self->pipeline)
-                                              }
-                                          },
-                                          &self->descriptor_set);
-
   return self;
 }
 
@@ -288,6 +286,101 @@ gsk_vulkan_render_collect_vertices (GskVulkanRender *self)
   return buffer;
 }
 
+VkDescriptorSet
+gsk_vulkan_render_get_descriptor_set (GskVulkanRender *self,
+                                      gsize            id)
+{
+  g_assert (id < self->n_descriptor_sets);
+
+  return self->descriptor_sets[id];
+}
+
+gsize
+gsk_vulkan_render_reserve_descriptor_set (GskVulkanRender *self,
+                                          GskVulkanImage  *source)
+{
+  gpointer id_plus_one;
+
+  id_plus_one = g_hash_table_lookup (self->descriptor_set_indexes, source);
+  if (id_plus_one)
+    return GPOINTER_TO_SIZE (id_plus_one) - 1;
+
+  id_plus_one = GSIZE_TO_POINTER (g_hash_table_size (self->descriptor_set_indexes) + 1);
+  g_hash_table_insert (self->descriptor_set_indexes, source, id_plus_one);
+  
+  return GPOINTER_TO_SIZE (id_plus_one) - 1;
+}
+
+static void
+gsk_vulkan_render_prepare_descriptor_sets (GskVulkanRender *self,
+                                           VkSampler        sampler)
+{
+  GHashTableIter iter;
+  gpointer key, value;
+  VkDevice device;
+  GSList *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);
+    }
+  
+  needed_sets = g_hash_table_size (self->descriptor_set_indexes);
+  if (needed_sets > self->n_descriptor_sets)
+    {
+      g_assert (needed_sets < self->descriptor_pool_maxsets);
+
+      GSK_VK_CHECK (vkResetDescriptorPool, device,
+                                           self->descriptor_pool,
+                                           0);
+      self->n_descriptor_sets = needed_sets;
+      self->descriptor_sets = g_renew (VkDescriptorSet, self->descriptor_sets, needed_sets);
+
+      VkDescriptorSetLayout layouts[needed_sets];
+      for (i = 0; i < needed_sets; i++)
+        {
+          layouts[i] = gsk_vulkan_pipeline_get_descriptor_set_layout (self->pipeline);
+        }
+      GSK_VK_CHECK (vkAllocateDescriptorSets, device,
+                                              &(VkDescriptorSetAllocateInfo) {
+                                                  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+                                                  .descriptorPool = self->descriptor_pool,
+                                                  .descriptorSetCount = needed_sets,
+                                                  .pSetLayouts = layouts
+                                              },
+                                              self->descriptor_sets);
+    }
+
+  g_hash_table_iter_init (&iter, self->descriptor_set_indexes);
+  while (g_hash_table_iter_next (&iter, &key, &value))
+    {
+      GskVulkanImage *image = key;
+      gsize id = GPOINTER_TO_SIZE (value) - 1;
+
+      vkUpdateDescriptorSets (device,
+                              1,
+                              (VkWriteDescriptorSet[1]) {
+                                  {
+                                      .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+                                      .dstSet = self->descriptor_sets[id],
+                                      .dstBinding = 0,
+                                      .dstArrayElement = 0,
+                                      .descriptorCount = 1,
+                                      .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+                                      .pImageInfo = &(VkDescriptorImageInfo) {
+                                          .sampler = sampler,
+                                          .imageView = gsk_vulkan_image_get_image_view (image),
+                                          .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
+                                      }
+                                  }
+                              },
+                              0, NULL);
+    }
+}
+
 void
 gsk_vulkan_render_draw (GskVulkanRender   *self,
                         VkSampler          sampler)
@@ -295,12 +388,9 @@ gsk_vulkan_render_draw (GskVulkanRender   *self,
   GskVulkanBuffer *buffer;
   GSList *l;
 
-  buffer = gsk_vulkan_render_collect_vertices (self);
+  gsk_vulkan_render_prepare_descriptor_sets (self, sampler);
 
-  for (l = self->render_passes; l; l = l->next)
-    {
-      gsk_vulkan_render_pass_update_descriptor_sets (l->data, self->descriptor_set, sampler);
-    }
+  buffer = gsk_vulkan_render_collect_vertices (self);
 
   vkCmdSetViewport (self->command_buffer,
                     0,
@@ -339,15 +429,6 @@ gsk_vulkan_render_draw (GskVulkanRender   *self,
                      VK_PIPELINE_BIND_POINT_GRAPHICS,
                      gsk_vulkan_pipeline_get_pipeline (self->pipeline));
 
-  vkCmdBindDescriptorSets (self->command_buffer,
-                           VK_PIPELINE_BIND_POINT_GRAPHICS,
-                           gsk_vulkan_pipeline_get_pipeline_layout (self->pipeline),
-                           0,
-                           1,
-                           &self->descriptor_set,
-                           0,
-                           NULL);
-
   vkCmdBindVertexBuffers (self->command_buffer,
                           0,
                           1,
@@ -365,7 +446,7 @@ gsk_vulkan_render_draw (GskVulkanRender   *self,
 
   for (l = self->render_passes; l; l = l->next)
     {
-      gsk_vulkan_render_pass_draw (l->data, self, self->command_buffer);
+      gsk_vulkan_render_pass_draw (l->data, self, self->pipeline, self->command_buffer);
     }
 
   vkCmdEndRenderPass (self->command_buffer);
@@ -427,6 +508,8 @@ gsk_vulkan_render_cleanup (GskVulkanRender *self)
                                     self->command_pool,
                                     0);
 
+  g_hash_table_remove_all (self->descriptor_set_indexes);
+
   g_slist_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);
@@ -469,6 +552,8 @@ gsk_vulkan_render_free (GskVulkanRender *self)
   vkDestroyDescriptorPool (device,
                            self->descriptor_pool,
                            NULL);
+  g_free (self->descriptor_sets);
+  g_hash_table_unref (self->descriptor_set_indexes);
 
   vkDestroyFence (device,
                   self->fence,
diff --git a/gsk/gskvulkanrenderpass.c b/gsk/gskvulkanrenderpass.c
index 731498b..60deacc 100644
--- a/gsk/gskvulkanrenderpass.c
+++ b/gsk/gskvulkanrenderpass.c
@@ -20,6 +20,7 @@ struct _GskVulkanRenderOp
   GskVulkanImage      *source; /* source image to render */
   gsize                vertex_offset; /* offset into vertex buffer */
   gsize                vertex_count; /* number of vertices */
+  gsize                descriptor_set_index; /* index into descriptor sets array for the right descriptor 
set to bind */
 };
 
 struct _GskVulkanRenderPass
@@ -186,9 +187,8 @@ gsk_vulkan_render_pass_collect_vertices (GskVulkanRenderPass *self,
 }
 
 void
-gsk_vulkan_render_pass_update_descriptor_sets (GskVulkanRenderPass *self,
-                                               VkDescriptorSet      descriptor_set,
-                                               VkSampler            sampler)
+gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self,
+                                                GskVulkanRender     *render)
 {
   GskVulkanRenderOp *op;
   guint i;
@@ -197,30 +197,23 @@ gsk_vulkan_render_pass_update_descriptor_sets (GskVulkanRenderPass *self,
     {
       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);
+      switch (op->type)
+        {
+        case GSK_VULKAN_OP_FALLBACK:
+          op->descriptor_set_index = gsk_vulkan_render_reserve_descriptor_set (render, op->source);
+          break;
+
+        default:
+          g_assert_not_reached ();
+          break;
+        }
     }
 }
 
 void
 gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self,
                              GskVulkanRender     *render,
+                             GskVulkanPipeline   *pipeline,
                              VkCommandBuffer      command_buffer)
 {
   GskVulkanRenderOp *op;
@@ -230,6 +223,17 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self,
     {
       op = &g_array_index (self->render_ops, GskVulkanRenderOp, i);
 
+      vkCmdBindDescriptorSets (command_buffer,
+                               VK_PIPELINE_BIND_POINT_GRAPHICS,
+                               gsk_vulkan_pipeline_get_pipeline_layout (pipeline),
+                               0,
+                               1,
+                               (VkDescriptorSet[1]) {
+                                   gsk_vulkan_render_get_descriptor_set (render, op->descriptor_set_index)
+                               },
+                               0,
+                               NULL);
+
       vkCmdDraw (command_buffer,
                  op->vertex_count, 1,
                  op->vertex_offset, 0);
diff --git a/gsk/gskvulkanrenderpassprivate.h b/gsk/gskvulkanrenderpassprivate.h
index 886e7c2..a5eae77 100644
--- a/gsk/gskvulkanrenderpassprivate.h
+++ b/gsk/gskvulkanrenderpassprivate.h
@@ -27,11 +27,11 @@ gsize                   gsk_vulkan_render_pass_collect_vertices         (GskVulk
                                                                          gsize                   offset,
                                                                          gsize                   total);
 
-void                    gsk_vulkan_render_pass_update_descriptor_sets   (GskVulkanRenderPass    *self,
-                                                                         VkDescriptorSet         
descriptor_set,
-                                                                         VkSampler               sampler);
+void                    gsk_vulkan_render_pass_reserve_descriptor_sets  (GskVulkanRenderPass    *self,
+                                                                         GskVulkanRender        *render);
 void                    gsk_vulkan_render_pass_draw                     (GskVulkanRenderPass    *self,
                                                                          GskVulkanRender        *render,
+                                                                         GskVulkanPipeline      *pipeline,
                                                                          VkCommandBuffer         
command_buffer);
 
 G_END_DECLS
diff --git a/gsk/gskvulkanrenderprivate.h b/gsk/gskvulkanrenderprivate.h
index 44c582f..1791245 100644
--- a/gsk/gskvulkanrenderprivate.h
+++ b/gsk/gskvulkanrenderprivate.h
@@ -38,6 +38,10 @@ void                    gsk_vulkan_render_add_node                      (GskVulk
 
 void                    gsk_vulkan_render_upload                        (GskVulkanRender        *self);
 
+VkDescriptorSet         gsk_vulkan_render_get_descriptor_set            (GskVulkanRender        *self,
+                                                                         gsize                   id);
+gsize                   gsk_vulkan_render_reserve_descriptor_set        (GskVulkanRender        *self,
+                                                                         GskVulkanImage         *source);
 void                    gsk_vulkan_render_draw                          (GskVulkanRender        *self,
                                                                          VkSampler               sampler);
 


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