[gtk+/wip/otte/vulkan: 40/62] vulkan: Upload image data directly



commit 13b53656eacbc8d9fe24242b0295caed999e9587
Author: Benjamin Otte <otte redhat com>
Date:   Tue Dec 6 23:29:38 2016 +0100

    vulkan: Upload image data directly
    
    Instead of using a staging iamge, we require the final image to be
    linearly allocated and have host-visible memory.
    
    This improves performance quite a bit.
    
    The old code is still there and can be enabled with a simple change
    to a #define in gskvulkanimage.h

 gsk/gskvulkanimage.c        |  124 +++++++++++++++++++++++++++++++++----------
 gsk/gskvulkanimageprivate.h |    8 +++
 2 files changed, 104 insertions(+), 28 deletions(-)
---
diff --git a/gsk/gskvulkanimage.c b/gsk/gskvulkanimage.c
index c8777f7..edfb24a 100644
--- a/gsk/gskvulkanimage.c
+++ b/gsk/gskvulkanimage.c
@@ -65,27 +65,19 @@ gsk_vulkan_image_new (GdkVulkanContext      *context,
   return self;
 }
 
-static GskVulkanImage *
-gsk_vulkan_image_new_staging (GdkVulkanContext  *context,
-                              guchar            *data,
-                              gsize              width,
-                              gsize              height,
-                              gsize              stride)
+static void
+gsk_vulkan_image_upload_data (GskVulkanImage *self,
+                              guchar         *data,
+                              gsize           width,
+                              gsize           height,
+                              gsize           data_stride)
 {
   VkMemoryRequirements requirements;
-  GskVulkanImage *self;
-  guchar *mem;
   gsize mem_stride;
-
-  self = gsk_vulkan_image_new (context,
-                               width,
-                               height, 
-                               VK_IMAGE_TILING_LINEAR,
-                               VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
-                               VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
+  guchar *mem;
 
   mem_stride = width * 4;
-  vkGetImageMemoryRequirements (gdk_vulkan_context_get_device (context),
+  vkGetImageMemoryRequirements (gdk_vulkan_context_get_device (self->vulkan),
                                 self->vk_image,
                                 &requirements);
   if (mem_stride % requirements.alignment != 0)
@@ -93,21 +85,19 @@ gsk_vulkan_image_new_staging (GdkVulkanContext  *context,
 
   mem = gsk_vulkan_memory_map (self->memory);
 
-  if (stride == width * 4 && stride == mem_stride)
+  if (data_stride == width * 4 && data_stride == mem_stride)
     {
-      memcpy (mem, data, width * height * 4);
+      memcpy (mem, data, data_stride * height);
     }
   else
     {
       for (gsize i = 0; i < height; i++)
         {
-          memcpy (mem + i * mem_stride, data + i * stride, width * 4);
+          memcpy (mem + i * mem_stride, data + i * data_stride, width * 4);
         }
     }
 
   gsk_vulkan_memory_unmap (self->memory);
-
-  return self;
 }
 
 static void
@@ -138,16 +128,23 @@ gsk_vulkan_image_ensure_view (GskVulkanImage *self)
 }
 
 GskVulkanImage *
-gsk_vulkan_image_new_from_data (GdkVulkanContext  *context,
-                                VkCommandBuffer    command_buffer,
-                                guchar            *data,
-                                gsize              width,
-                                gsize              height,
-                                gsize              stride)
+gsk_vulkan_image_new_from_data_via_staging_image (GdkVulkanContext  *context,
+                                                  VkCommandBuffer    command_buffer,
+                                                  guchar            *data,
+                                                  gsize              width,
+                                                  gsize              height,
+                                                  gsize              stride)
 {
   GskVulkanImage *self, *staging;
 
-  staging = gsk_vulkan_image_new_staging (context, data, width, height, stride);
+  staging = gsk_vulkan_image_new (context,
+                                  width,
+                                  height, 
+                                  VK_IMAGE_TILING_LINEAR,
+                                  VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
+                                  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
+
+  gsk_vulkan_image_upload_data (staging, data, width, height, stride);
 
   self = gsk_vulkan_image_new (context,
                                width,
@@ -253,6 +250,7 @@ gsk_vulkan_image_new_from_data (GdkVulkanContext  *context,
                             }
                         });
 
+  /* XXX: Is this okay or do we need to keep the staging image around until the commands execute */
   gsk_vulkan_image_free (staging);
 
   gsk_vulkan_image_ensure_view (self);
@@ -260,6 +258,76 @@ gsk_vulkan_image_new_from_data (GdkVulkanContext  *context,
   return self;
 }
 
+GskVulkanImage *
+gsk_vulkan_image_new_from_data_directly (GdkVulkanContext  *context,
+                                         VkCommandBuffer    command_buffer,
+                                         guchar            *data,
+                                         gsize              width,
+                                         gsize              height,
+                                         gsize              stride)
+{
+  GskVulkanImage *self;
+
+  self = gsk_vulkan_image_new (context,
+                               width,
+                               height, 
+                               VK_IMAGE_TILING_LINEAR,
+                               VK_IMAGE_USAGE_SAMPLED_BIT,
+                               VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
+
+  gsk_vulkan_image_upload_data (self, data, width, height, stride);
+
+  vkCmdPipelineBarrier (command_buffer,
+                        VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+                        VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+                        0,
+                        0, NULL,
+                        0, NULL,
+                        1, (VkImageMemoryBarrier[1]) {
+                            {
+                                .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+                                .srcAccessMask = VK_ACCESS_HOST_WRITE_BIT,
+                                .dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
+                                .oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED,
+                                .newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+                                .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                                .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                                .image = self->vk_image,
+                                .subresourceRange = {
+                                    .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+                                    .baseMipLevel = 0,
+                                    .levelCount = 1,
+                                    .baseArrayLayer = 0,
+                                    .layerCount = 1
+                                }
+                            }
+                        });
+
+  gsk_vulkan_image_ensure_view (self);
+
+  return self;
+}
+
+GskVulkanImage *
+gsk_vulkan_image_new_from_data (GdkVulkanContext  *context,
+                                VkCommandBuffer    command_buffer,
+                                guchar            *data,
+                                gsize              width,
+                                gsize              height,
+                                gsize              stride)
+{
+  switch (GSK_VULKAN_UPLOAD_IMAGE_DEFAULT)
+    {
+    default:
+      g_assert_not_reached ();
+      /* fall through */
+    case GSK_VULKAN_UPLOAD_DIRECTLY:
+      return gsk_vulkan_image_new_from_data_directly (context, command_buffer, data, width, height, stride);
+    case GSK_VULKAN_UPLOAD_VIA_STAGING_IMAGE:
+      return gsk_vulkan_image_new_from_data_via_staging_image (context, command_buffer, data, width, height, 
stride);
+    }
+}
+
 void
 gsk_vulkan_image_free (GskVulkanImage *self)
 {
diff --git a/gsk/gskvulkanimageprivate.h b/gsk/gskvulkanimageprivate.h
index 57686ea..7c089c2 100644
--- a/gsk/gskvulkanimageprivate.h
+++ b/gsk/gskvulkanimageprivate.h
@@ -5,6 +5,14 @@
 
 G_BEGIN_DECLS
 
+/* Modify here for benchmarking */
+#define GSK_VULKAN_UPLOAD_IMAGE_DEFAULT GSK_VULKAN_UPLOAD_DIRECTLY
+
+typedef enum {
+  GSK_VULKAN_UPLOAD_DIRECTLY,
+  GSK_VULKAN_UPLOAD_VIA_STAGING_IMAGE
+} GstkVulkanImageUpload;
+
 typedef struct _GskVulkanImage GskVulkanImage;
 
 GskVulkanImage *        gsk_vulkan_image_new_from_data                  (GdkVulkanContext       *context,


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