anv: Use blorp for CopyImageToBuffer
authorJason Ekstrand <jason.ekstrand@intel.com>
Wed, 24 Aug 2016 03:19:57 +0000 (20:19 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Tue, 13 Sep 2016 19:40:12 +0000 (12:40 -0700)
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
Reviewed-by: Anuj Phogat <anuj.phogat@gmail.com>
Reviewed-by: Nanley Chery <nanley.g.chery@intel.com>
src/intel/vulkan/anv_blorp.c
src/intel/vulkan/anv_meta_copy.c

index 5d715fca26d334fffad91ad00f02011392a1ff2b..a838b55bfe04b3a91afd1708b3277a2958d26d09 100644 (file)
@@ -119,6 +119,38 @@ anv_device_finish_blorp(struct anv_device *device)
    anv_pipeline_cache_finish(&device->blorp_shader_cache);
 }
 
+static void
+get_blorp_surf_for_anv_buffer(struct anv_device *device,
+                              struct anv_buffer *buffer, uint64_t offset,
+                              uint32_t width, uint32_t height,
+                              uint32_t row_pitch, enum isl_format format,
+                              struct blorp_surf *blorp_surf,
+                              struct isl_surf *isl_surf)
+{
+   *blorp_surf = (struct blorp_surf) {
+      .surf = isl_surf,
+      .addr = {
+         .buffer = buffer->bo,
+         .offset = buffer->offset + offset,
+      },
+   };
+
+   isl_surf_init(&device->isl_dev, isl_surf,
+                 .dim = ISL_SURF_DIM_2D,
+                 .format = format,
+                 .width = width,
+                 .height = height,
+                 .depth = 1,
+                 .levels = 1,
+                 .array_len = 1,
+                 .samples = 1,
+                 .min_pitch = row_pitch,
+                 .usage = ISL_SURF_USAGE_TEXTURE_BIT |
+                          ISL_SURF_USAGE_RENDER_TARGET_BIT,
+                 .tiling_flags = ISL_TILING_LINEAR_BIT);
+   assert(isl_surf->row_pitch == row_pitch);
+}
+
 static void
 get_blorp_surf_for_anv_image(const struct anv_image *image,
                              VkImageAspectFlags aspect,
@@ -136,6 +168,108 @@ get_blorp_surf_for_anv_image(const struct anv_image *image,
    };
 }
 
+static void
+copy_buffer_to_image(struct anv_cmd_buffer *cmd_buffer,
+                     struct anv_buffer *anv_buffer,
+                     struct anv_image *anv_image,
+                     uint32_t regionCount,
+                     const VkBufferImageCopy* pRegions,
+                     bool buffer_to_image)
+{
+   struct blorp_batch batch;
+   blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer);
+
+   struct {
+      struct blorp_surf surf;
+      uint32_t level;
+      VkOffset3D offset;
+   } image, buffer, *src, *dst;
+
+   buffer.level = 0;
+   buffer.offset = (VkOffset3D) { 0, 0, 0 };
+
+   if (buffer_to_image) {
+      src = &buffer;
+      dst = &image;
+   } else {
+      src = &image;
+      dst = &buffer;
+   }
+
+   for (unsigned r = 0; r < regionCount; r++) {
+      const VkImageAspectFlags aspect = pRegions[r].imageSubresource.aspectMask;
+
+      get_blorp_surf_for_anv_image(anv_image, aspect, &image.surf);
+      image.offset =
+         anv_sanitize_image_offset(anv_image->type, pRegions[r].imageOffset);
+      image.level = pRegions[r].imageSubresource.mipLevel;
+
+      VkExtent3D extent =
+         anv_sanitize_image_extent(anv_image->type, pRegions[r].imageExtent);
+      if (anv_image->type != VK_IMAGE_TYPE_3D) {
+         image.offset.z = pRegions[r].imageSubresource.baseArrayLayer;
+         extent.depth = pRegions[r].imageSubresource.layerCount;
+      }
+
+      const enum isl_format buffer_format =
+         anv_get_isl_format(&cmd_buffer->device->info, anv_image->vk_format,
+                            aspect, VK_IMAGE_TILING_LINEAR);
+
+      const VkExtent3D bufferImageExtent = {
+         .width  = pRegions[r].bufferRowLength ?
+                   pRegions[r].bufferRowLength : extent.width,
+         .height = pRegions[r].bufferImageHeight ?
+                   pRegions[r].bufferImageHeight : extent.height,
+      };
+
+      const struct isl_format_layout *buffer_fmtl =
+         isl_format_get_layout(buffer_format);
+
+      const uint32_t buffer_row_pitch =
+         DIV_ROUND_UP(bufferImageExtent.width, buffer_fmtl->bw) *
+         (buffer_fmtl->bpb / 8);
+
+      const uint32_t buffer_layer_stride =
+         DIV_ROUND_UP(bufferImageExtent.height, buffer_fmtl->bh) *
+         buffer_row_pitch;
+
+      struct isl_surf buffer_isl_surf;
+      get_blorp_surf_for_anv_buffer(cmd_buffer->device,
+                                    anv_buffer, pRegions[r].bufferOffset,
+                                    extent.width, extent.height,
+                                    buffer_row_pitch, buffer_format,
+                                    &buffer.surf, &buffer_isl_surf);
+
+      for (unsigned z = 0; z < extent.depth; z++) {
+         blorp_copy(&batch, &src->surf, src->level, src->offset.z,
+                    &dst->surf, dst->level, dst->offset.z,
+                    src->offset.x, src->offset.y, dst->offset.x, dst->offset.y,
+                    extent.width, extent.height);
+
+         image.offset.z++;
+         buffer.surf.addr.offset += buffer_layer_stride;
+      }
+   }
+
+   blorp_batch_finish(&batch);
+}
+
+void anv_CmdCopyImageToBuffer(
+    VkCommandBuffer                             commandBuffer,
+    VkImage                                     srcImage,
+    VkImageLayout                               srcImageLayout,
+    VkBuffer                                    dstBuffer,
+    uint32_t                                    regionCount,
+    const VkBufferImageCopy*                    pRegions)
+{
+   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
+   ANV_FROM_HANDLE(anv_image, src_image, srcImage);
+   ANV_FROM_HANDLE(anv_buffer, dst_buffer, dstBuffer);
+
+   copy_buffer_to_image(cmd_buffer, dst_buffer, src_image,
+                        regionCount, pRegions, false);
+}
+
 static bool
 flip_coords(unsigned *src0, unsigned *src1, unsigned *dst0, unsigned *dst1)
 {
index 3f548e69867605216941702038af5f4629a7e673..a17dd639502da2d984ed11b30a4c283ed233c8c2 100644 (file)
@@ -232,22 +232,6 @@ void anv_CmdCopyBufferToImage(
                              regionCount, pRegions, true);
 }
 
-void anv_CmdCopyImageToBuffer(
-    VkCommandBuffer                             commandBuffer,
-    VkImage                                     srcImage,
-    VkImageLayout                               srcImageLayout,
-    VkBuffer                                    destBuffer,
-    uint32_t                                    regionCount,
-    const VkBufferImageCopy*                    pRegions)
-{
-   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
-   ANV_FROM_HANDLE(anv_image, src_image, srcImage);
-   ANV_FROM_HANDLE(anv_buffer, dst_buffer, destBuffer);
-
-   meta_copy_buffer_to_image(cmd_buffer, dst_buffer, src_image,
-                             regionCount, pRegions, false);
-}
-
 void anv_CmdCopyImage(
     VkCommandBuffer                             commandBuffer,
     VkImage                                     srcImage,