anv: Use blorp for CopyImage
authorJason Ekstrand <jason.ekstrand@intel.com>
Sun, 28 Aug 2016 04:05:13 +0000 (21:05 -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 5fa6699e9feca8dcfc8803118cc35fbaadd6a242..23ebc429bf37977b29105904a828635c103c943d 100644 (file)
@@ -168,6 +168,73 @@ get_blorp_surf_for_anv_image(const struct anv_image *image,
    };
 }
 
+void anv_CmdCopyImage(
+    VkCommandBuffer                             commandBuffer,
+    VkImage                                     srcImage,
+    VkImageLayout                               srcImageLayout,
+    VkImage                                     dstImage,
+    VkImageLayout                               dstImageLayout,
+    uint32_t                                    regionCount,
+    const VkImageCopy*                          pRegions)
+{
+   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
+   ANV_FROM_HANDLE(anv_image, src_image, srcImage);
+   ANV_FROM_HANDLE(anv_image, dst_image, dstImage);
+
+   struct blorp_batch batch;
+   blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer);
+
+   for (unsigned r = 0; r < regionCount; r++) {
+      VkOffset3D srcOffset =
+         anv_sanitize_image_offset(src_image->type, pRegions[r].srcOffset);
+      VkOffset3D dstOffset =
+         anv_sanitize_image_offset(dst_image->type, pRegions[r].dstOffset);
+      VkExtent3D extent =
+         anv_sanitize_image_extent(src_image->type, pRegions[r].extent);
+
+      unsigned dst_base_layer, layer_count;
+      if (dst_image->type == VK_IMAGE_TYPE_3D) {
+         dst_base_layer = pRegions[r].dstOffset.z;
+         layer_count = pRegions[r].extent.depth;
+      } else {
+         dst_base_layer = pRegions[r].dstSubresource.baseArrayLayer;
+         layer_count = pRegions[r].dstSubresource.layerCount;
+      }
+
+      unsigned src_base_layer;
+      if (src_image->type == VK_IMAGE_TYPE_3D) {
+         src_base_layer = pRegions[r].srcOffset.z;
+      } else {
+         src_base_layer = pRegions[r].srcSubresource.baseArrayLayer;
+         assert(pRegions[r].srcSubresource.layerCount == layer_count);
+      }
+
+      assert(pRegions[r].srcSubresource.aspectMask ==
+             pRegions[r].dstSubresource.aspectMask);
+
+      uint32_t a;
+      for_each_bit(a, pRegions[r].dstSubresource.aspectMask) {
+         VkImageAspectFlagBits aspect = (1 << a);
+
+         struct blorp_surf src_surf, dst_surf;
+         get_blorp_surf_for_anv_image(src_image, aspect, &src_surf);
+         get_blorp_surf_for_anv_image(dst_image, aspect, &dst_surf);
+
+         for (unsigned i = 0; i < layer_count; i++) {
+            blorp_copy(&batch, &src_surf, pRegions[r].srcSubresource.mipLevel,
+                       src_base_layer + i,
+                       &dst_surf, pRegions[r].dstSubresource.mipLevel,
+                       dst_base_layer + i,
+                       srcOffset.x, srcOffset.y,
+                       dstOffset.x, dstOffset.y,
+                       extent.width, extent.height);
+         }
+      }
+   }
+
+   blorp_batch_finish(&batch);
+}
+
 static void
 copy_buffer_to_image(struct anv_cmd_buffer *cmd_buffer,
                      struct anv_buffer *anv_buffer,
index 5df04e6cea91d76978cd603fe23d844e787e8e99..b33273e1e385c916519a8fc790c65a8f13663790 100644 (file)
 
 #include "anv_meta.h"
 
-static VkExtent3D
-meta_image_block_size(const struct anv_image *image)
-{
-   if (image->aspects == VK_IMAGE_ASPECT_COLOR_BIT) {
-      const struct isl_format_layout *isl_layout =
-         isl_format_get_layout(image->color_surface.isl.format);
-      return (VkExtent3D) { isl_layout->bw, isl_layout->bh, isl_layout->bd };
-   } else {
-      return (VkExtent3D) { 1, 1, 1 };
-   }
-}
-
-/* Returns the user-provided VkBufferImageCopy::imageExtent in units of
- * elements rather than texels. One element equals one texel or one block
- * if Image is uncompressed or compressed, respectively.
- */
-static struct VkExtent3D
-meta_region_extent_el(const struct anv_image *image,
-                      const struct VkExtent3D *extent)
-{
-   const VkExtent3D block = meta_image_block_size(image);
-   return anv_sanitize_image_extent(image->type, (VkExtent3D) {
-      .width  = DIV_ROUND_UP(extent->width , block.width),
-      .height = DIV_ROUND_UP(extent->height, block.height),
-      .depth  = DIV_ROUND_UP(extent->depth , block.depth),
-   });
-}
-
-/* Returns the user-provided VkBufferImageCopy::imageOffset in units of
- * elements rather than texels. One element equals one texel or one block
- * if Image is uncompressed or compressed, respectively.
- */
-static struct VkOffset3D
-meta_region_offset_el(const struct anv_image *image,
-                      const struct VkOffset3D *offset)
-{
-   const VkExtent3D block = meta_image_block_size(image);
-   return anv_sanitize_image_offset(image->type, (VkOffset3D) {
-      .x = offset->x / block.width,
-      .y = offset->y / block.height,
-      .z = offset->z / block.depth,
-   });
-}
-
-static struct anv_meta_blit2d_surf
-blit_surf_for_image(const struct anv_image* image,
-                    const struct anv_surface *surf)
-{
-   return (struct anv_meta_blit2d_surf) {
-      .bo = image->bo,
-      .tiling = surf->isl.tiling,
-      .base_offset = image->offset + surf->offset,
-      .bs = isl_format_get_layout(surf->isl.format)->bpb / 8,
-      .pitch = isl_surf_get_row_pitch(&surf->isl),
-   };
-}
-
 static void
 do_buffer_copy(struct anv_cmd_buffer *cmd_buffer,
                struct anv_bo *src, uint64_t src_offset,
@@ -107,107 +50,6 @@ do_buffer_copy(struct anv_cmd_buffer *cmd_buffer,
    anv_meta_blit2d(cmd_buffer, &b_src, &b_dst, 1, &rect);
 }
 
-void anv_CmdCopyImage(
-    VkCommandBuffer                             commandBuffer,
-    VkImage                                     srcImage,
-    VkImageLayout                               srcImageLayout,
-    VkImage                                     destImage,
-    VkImageLayout                               destImageLayout,
-    uint32_t                                    regionCount,
-    const VkImageCopy*                          pRegions)
-{
-   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
-   ANV_FROM_HANDLE(anv_image, src_image, srcImage);
-   ANV_FROM_HANDLE(anv_image, dest_image, destImage);
-   struct anv_meta_saved_state saved_state;
-
-   /* From the Vulkan 1.0 spec:
-    *
-    *    vkCmdCopyImage can be used to copy image data between multisample
-    *    images, but both images must have the same number of samples.
-    */
-   assert(src_image->samples == dest_image->samples);
-
-   anv_meta_begin_blit2d(cmd_buffer, &saved_state);
-
-   for (unsigned r = 0; r < regionCount; r++) {
-      assert(pRegions[r].srcSubresource.aspectMask ==
-             pRegions[r].dstSubresource.aspectMask);
-
-      VkImageAspectFlags aspect = pRegions[r].srcSubresource.aspectMask;
-
-      /* Create blit surfaces */
-      const struct anv_surface *src_surf =
-         anv_image_get_surface_for_aspect_mask(src_image, aspect);
-      const struct anv_surface *dst_surf =
-         anv_image_get_surface_for_aspect_mask(dest_image, aspect);
-      struct anv_meta_blit2d_surf b_src =
-         blit_surf_for_image(src_image, src_surf);
-      struct anv_meta_blit2d_surf b_dst =
-         blit_surf_for_image(dest_image, dst_surf);
-
-      /**
-       * From the Vulkan 1.0.6 spec: 18.4 Copying Data Between Buffers and Images
-       *    imageExtent is the size in texels of the image to copy in width, height
-       *    and depth. 1D images use only x and width. 2D images use x, y, width
-       *    and height. 3D images use x, y, z, width, height and depth.
-       *
-       * Also, convert the offsets and extent from units of texels to units of
-       * blocks - which is the highest resolution accessible in this command.
-       */
-      const VkOffset3D dst_offset_el =
-         meta_region_offset_el(dest_image, &pRegions[r].dstOffset);
-      const VkOffset3D src_offset_el =
-         meta_region_offset_el(src_image, &pRegions[r].srcOffset);
-      const VkExtent3D img_extent_el =
-         meta_region_extent_el(src_image, &pRegions[r].extent);
-
-      /* Start creating blit rect */
-      struct anv_meta_blit2d_rect rect = {
-         .width = img_extent_el.width,
-         .height = img_extent_el.height,
-      };
-
-      /* Loop through each 3D or array slice */
-      unsigned num_slices_3d = img_extent_el.depth;
-      unsigned num_slices_array = pRegions[r].dstSubresource.layerCount;
-      unsigned slice_3d = 0;
-      unsigned slice_array = 0;
-      while (slice_3d < num_slices_3d && slice_array < num_slices_array) {
-
-         /* Finish creating blit rect */
-         isl_surf_get_image_offset_el(&dst_surf->isl,
-                                    pRegions[r].dstSubresource.mipLevel,
-                                    pRegions[r].dstSubresource.baseArrayLayer
-                                       + slice_array,
-                                    dst_offset_el.z + slice_3d,
-                                    &rect.dst_x,
-                                    &rect.dst_y);
-         isl_surf_get_image_offset_el(&src_surf->isl,
-                                    pRegions[r].srcSubresource.mipLevel,
-                                    pRegions[r].srcSubresource.baseArrayLayer
-                                       + slice_array,
-                                    src_offset_el.z + slice_3d,
-                                    &rect.src_x,
-                                    &rect.src_y);
-         rect.dst_x += dst_offset_el.x;
-         rect.dst_y += dst_offset_el.y;
-         rect.src_x += src_offset_el.x;
-         rect.src_y += src_offset_el.y;
-
-         /* Perform Blit */
-         anv_meta_blit2d(cmd_buffer, &b_src, &b_dst, 1, &rect);
-
-         if (dest_image->type == VK_IMAGE_TYPE_3D)
-            slice_3d++;
-         else
-            slice_array++;
-      }
-   }
-
-   anv_meta_end_blit2d(cmd_buffer, &saved_state);
-}
-
 void anv_CmdCopyBuffer(
     VkCommandBuffer                             commandBuffer,
     VkBuffer                                    srcBuffer,