[gtk+] vulkan: Add an api to update multiple image regions



commit 64322a2c417dfed54e4948bf252864455a90b63e
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu Sep 21 13:42:57 2017 -0400

    vulkan: Add an api to update multiple image regions
    
    Instead of doing multiple copy commands with a tiny buffer
    for each glyph, we can just batch them all together. This
    also avoids the issue of creating multiple barriers for the
    same image.

 gsk/gskvulkanimage.c        |   89 ++++++++++++++++++++++++++++++------------
 gsk/gskvulkanimageprivate.h |   14 +++++++
 2 files changed, 77 insertions(+), 26 deletions(-)
---
diff --git a/gsk/gskvulkanimage.c b/gsk/gskvulkanimage.c
index 3e36551..5ab2ae6 100644
--- a/gsk/gskvulkanimage.c
+++ b/gsk/gskvulkanimage.c
@@ -148,8 +148,12 @@ gsk_vulkan_uploader_upload (GskVulkanUploader *self)
 
       command_buffer = gsk_vulkan_command_pool_get_buffer (self->command_pool);
       vkCmdPipelineBarrier (command_buffer,
+#if 0
                             VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
                             VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+#endif
+                            VK_PIPELINE_STAGE_TRANSFER_BIT,
+                            VK_PIPELINE_STAGE_TRANSFER_BIT,
                             0,
                             0, NULL,
                             self->before_buffer_barriers->len, (VkBufferMemoryBarrier *) 
self->before_buffer_barriers->data,
@@ -164,8 +168,12 @@ gsk_vulkan_uploader_upload (GskVulkanUploader *self)
     {
       VkCommandBuffer command_buffer = gsk_vulkan_uploader_get_copy_buffer (self);
       vkCmdPipelineBarrier (command_buffer,
+#if 0
                             VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
                             VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+#endif
+                            VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
+                            VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
                             0,
                             0, NULL,
                             self->after_buffer_barriers->len, (VkBufferMemoryBarrier *) 
self->after_buffer_barriers->data,
@@ -664,22 +672,67 @@ gsk_vulkan_image_upload_region (GskVulkanImage    *self,
                                 gsize              x,
                                 gsize              y)
 {
+  gsk_vulkan_image_upload_regions (self, uploader, 1, (GskImageRegion[1]) {
+                                                       {
+                                                          .data = data,
+                                                          .width = width,
+                                                          .height = height,
+                                                          .stride = stride,
+                                                          .x = x,
+                                                          .y = y 
+                                                       } });
+}
+
+void
+gsk_vulkan_image_upload_regions (GskVulkanImage    *self,
+                                 GskVulkanUploader *uploader,
+                                 guint              num_regions,
+                                 GskImageRegion    *regions)
+{
   GskVulkanBuffer *staging;
   guchar *mem;
+  guchar *m;
+  gsize size;
+  gsize offset;
+  VkBufferImageCopy *bufferImageCopy;
+
+  size = 0;
+  for (int i = 0; i < num_regions; i++)
+    size += regions[i].width * regions[i].height * 4;
 
-  staging = gsk_vulkan_buffer_new_staging (uploader->vulkan, width * height * 4);
+  staging = gsk_vulkan_buffer_new_staging (uploader->vulkan, size);
   mem = gsk_vulkan_buffer_map (staging);
 
-  if (stride == width * 4)
-    {
-      memcpy (mem, data, stride * height);
-    }
-  else
+  bufferImageCopy = alloca (sizeof (VkBufferImageCopy) * num_regions);
+  memset (bufferImageCopy, 0, sizeof (VkBufferImageCopy) * num_regions);
+
+  offset = 0;
+  for (int i = 0; i < num_regions; i++)
     {
-      for (gsize i = 0; i < height; i++)
+      m = mem + offset;
+      if (regions[i].stride == regions[i].width * 4)
         {
-          memcpy (mem + i * width * 4, data + i * stride, width * 4);
+          memcpy (m, regions[i].data, regions[i].stride * regions[i].height);
         }
+      else
+        {
+          for (gsize r = 0; r < regions[i].height; i++)
+            memcpy (m + r * regions[i].width * 4, regions[i].data + r * regions[i].stride, regions[i].width 
* 4);
+        }
+
+      bufferImageCopy[i].bufferOffset = offset;
+      bufferImageCopy[i].imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+      bufferImageCopy[i].imageSubresource.mipLevel = 0;
+      bufferImageCopy[i].imageSubresource.baseArrayLayer = 0;
+      bufferImageCopy[i].imageSubresource.layerCount = 1;
+      bufferImageCopy[i].imageOffset.x = regions[i].x;
+      bufferImageCopy[i].imageOffset.y = regions[i].y;
+      bufferImageCopy[i].imageOffset.z = 0;
+      bufferImageCopy[i].imageExtent.width = regions[i].width;
+      bufferImageCopy[i].imageExtent.height = regions[i].height;
+      bufferImageCopy[i].imageExtent.depth = 1;
+
+      offset += regions[i].width * regions[i].height * 4;
     }
 
   gsk_vulkan_buffer_unmap (staging);
@@ -694,24 +747,8 @@ gsk_vulkan_image_upload_region (GskVulkanImage    *self,
                           gsk_vulkan_buffer_get_buffer (staging),
                           self->vk_image,
                           VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
-                          1,
-                          (VkBufferImageCopy[1]) {
-                               {
-                                   .bufferOffset = 0,
-                                   .imageSubresource = {
-                                       .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
-                                       .mipLevel = 0,
-                                       .baseArrayLayer = 0,
-                                       .layerCount = 1
-                                   },
-                                   .imageOffset = { x, y, 0 },
-                                   .imageExtent = {
-                                       .width = width,
-                                       .height = height,
-                                       .depth = 1
-                                   }
-                               }
-                          });
+                          num_regions,
+                          bufferImageCopy);
 
   gsk_vulkan_uploader_add_image_barrier (uploader,
                                          TRUE,
diff --git a/gsk/gskvulkanimageprivate.h b/gsk/gskvulkanimageprivate.h
index 5f2cdf7..3aa0263 100644
--- a/gsk/gskvulkanimageprivate.h
+++ b/gsk/gskvulkanimageprivate.h
@@ -39,6 +39,20 @@ void                    gsk_vulkan_image_upload_region                  (GskVulk
                                                                          gsize                   stride,
                                                                          gsize                   x,
                                                                          gsize                   y);
+
+typedef struct {
+  guchar *data;
+  gsize width;
+  gsize height;
+  gsize stride;
+  gsize x;
+  gsize y;
+} GskImageRegion;
+
+void                    gsk_vulkan_image_upload_regions                 (GskVulkanImage         *image,
+                                                                         GskVulkanUploader      *uploader,
+                                                                         guint                   num_regions,
+                                                                         GskImageRegion         *regions);
 GskVulkanImage *        gsk_vulkan_image_new_for_framebuffer            (GdkVulkanContext       *context,
                                                                          gsize                   width,
                                                                          gsize                   height);


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