vk/meta: Use the biggest format possible for buffer copies
authorJason Ekstrand <jason.ekstrand@intel.com>
Wed, 20 May 2015 22:38:11 +0000 (15:38 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Wed, 20 May 2015 23:20:04 +0000 (16:20 -0700)
This should substantially improve throughput of buffer copies.

src/vulkan/meta.c

index f1524f9db2808e6f023616fc36fadfc4250181be..b1612c2dc2d5746182ee8814ffe18ed3d0f974f0 100644 (file)
@@ -627,6 +627,23 @@ meta_finish_blit(struct anv_cmd_buffer *cmd_buffer,
    anv_cmd_buffer_restore(cmd_buffer, saved_state);
 }
 
+static VkFormat
+vk_format_for_cpp(int cpp)
+{
+   switch (cpp) {
+   case 1: return VK_FORMAT_R8_UINT;
+   case 2: return VK_FORMAT_R8G8_UINT;
+   case 3: return VK_FORMAT_R8G8B8_UINT;
+   case 4: return VK_FORMAT_R8G8B8A8_UINT;
+   case 6: return VK_FORMAT_R16G16B16_UINT;
+   case 8: return VK_FORMAT_R16G16B16A16_UINT;
+   case 12: return VK_FORMAT_R32G32B32_UINT;
+   case 16: return VK_FORMAT_R32G32B32A32_UINT;
+   default:
+      unreachable("Invalid format cpp");
+   }
+}
+
 void anv_CmdCopyBuffer(
     VkCmdBuffer                                 cmdBuffer,
     VkBuffer                                    srcBuffer,
@@ -643,12 +660,37 @@ void anv_CmdCopyBuffer(
    meta_prepare_blit(cmd_buffer, &saved_state);
 
    for (unsigned r = 0; r < regionCount; r++) {
+      size_t src_offset = src_buffer->offset + pRegions[r].srcOffset;
+      size_t dest_offset = dest_buffer->offset + pRegions[r].destOffset;
+
+      /* First, we compute the biggest format that can be used with the
+       * given offsets and size.
+       */
+      int cpp = 16;
+
+      int fs = ffs(src_offset) - 1;
+      if (fs != -1)
+         cpp = MIN2(cpp, 1 << fs);
+      assert(src_offset % cpp == 0);
+
+      fs = ffs(dest_offset) - 1;
+      if (fs != -1)
+         cpp = MIN2(cpp, 1 << fs);
+      assert(dest_offset % cpp == 0);
+
+      fs = ffs(pRegions[r].copySize) - 1;
+      if (fs != -1)
+         cpp = MIN2(cpp, 1 << fs);
+      assert(pRegions[r].copySize % cpp == 0);
+
+      VkFormat copy_format = vk_format_for_cpp(cpp);
+
       VkImageCreateInfo image_info = {
          .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
          .imageType = VK_IMAGE_TYPE_2D,
-         .format = VK_FORMAT_R8_UNORM,
+         .format = copy_format,
          .extent = {
-            .width = pRegions[r].copySize,
+            .width = pRegions[r].copySize / cpp,
             .height = 1,
             .depth = 1,
          },
@@ -668,9 +710,9 @@ void anv_CmdCopyBuffer(
        * creating a dummy memory object etc. so there's really no point.
        */
       src_image->bo = src_buffer->bo;
-      src_image->offset = src_buffer->offset + pRegions[r].srcOffset;
+      src_image->offset = src_offset;
       dest_image->bo = dest_buffer->bo;
-      dest_image->offset = dest_buffer->offset + pRegions[r].destOffset;
+      dest_image->offset = dest_offset;
 
       struct anv_surface_view src_view;
       anv_image_view_init(&src_view, cmd_buffer->device,
@@ -678,7 +720,7 @@ void anv_CmdCopyBuffer(
             .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
             .image = (VkImage)src_image,
             .viewType = VK_IMAGE_VIEW_TYPE_2D,
-            .format = VK_FORMAT_R8_UNORM,
+            .format = copy_format,
             .channels = {
                VK_CHANNEL_SWIZZLE_R,
                VK_CHANNEL_SWIZZLE_G,
@@ -701,7 +743,7 @@ void anv_CmdCopyBuffer(
          &(VkColorAttachmentViewCreateInfo) {
             .sType = VK_STRUCTURE_TYPE_COLOR_ATTACHMENT_VIEW_CREATE_INFO,
             .image = (VkImage)dest_image,
-            .format = VK_FORMAT_R8_UNORM,
+            .format = copy_format,
             .mipLevel = 0,
             .baseArraySlice = 0,
             .arraySize = 1,
@@ -711,10 +753,10 @@ void anv_CmdCopyBuffer(
       meta_emit_blit(cmd_buffer,
                      &src_view,
                      (VkOffset3D) { 0, 0, 0 },
-                     (VkExtent3D) { pRegions[r].copySize, 1, 1 },
+                     (VkExtent3D) { pRegions[r].copySize / cpp, 1, 1 },
                      &dest_view,
                      (VkOffset3D) { 0, 0, 0 },
-                     (VkExtent3D) { pRegions[r].copySize, 1, 1 });
+                     (VkExtent3D) { pRegions[r].copySize / cpp, 1, 1 });
    }
 
    meta_finish_blit(cmd_buffer, &saved_state);