anv/formats: Add an anv_get_format helper
[mesa.git] / src / intel / vulkan / anv_meta_copy.c
index 1a2bfd6cf01aea6dbdde4e75873710f593b74048..c509c8fa1c01efa6ffc0b2d23d3e240867da9cd3 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 VkFormat format,
+meta_region_extent_el(const struct anv_image *image,
                       const struct VkExtent3D *extent)
 {
-   const struct isl_format_layout *isl_layout =
-      anv_format_for_vk_format(format)->isl_layout;
-   return (VkExtent3D) {
-      .width  = DIV_ROUND_UP(extent->width , isl_layout->bw),
-      .height = DIV_ROUND_UP(extent->height, isl_layout->bh),
-      .depth  = DIV_ROUND_UP(extent->depth , isl_layout->bd),
-   };
+   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
@@ -48,12 +59,12 @@ static struct VkOffset3D
 meta_region_offset_el(const struct anv_image *image,
                       const struct VkOffset3D *offset)
 {
-   const struct isl_format_layout *isl_layout = image->format->isl_layout;
-   return (VkOffset3D) {
-      .x = offset->x / isl_layout->bw,
-      .y = offset->y / isl_layout->bh,
-      .z = offset->z / isl_layout->bd,
-   };
+   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
@@ -115,20 +126,33 @@ meta_copy_buffer_to_image(struct anv_cmd_buffer *cmd_buffer,
 
    for (unsigned r = 0; r < regionCount; r++) {
 
-      /* Start creating blit rect */
+      /**
+       * From the Vulkan 1.0.6 spec: 18.3 Copying Data Between Images
+       *    extent is the size in texels of the source 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 img_offset_el =
          meta_region_offset_el(image, &pRegions[r].imageOffset);
       const VkExtent3D bufferExtent = {
-         .width = pRegions[r].bufferRowLength,
-         .height = pRegions[r].bufferImageHeight,
+         .width  = pRegions[r].bufferRowLength ?
+                   pRegions[r].bufferRowLength : pRegions[r].imageExtent.width,
+         .height = pRegions[r].bufferImageHeight ?
+                   pRegions[r].bufferImageHeight : pRegions[r].imageExtent.height,
       };
       const VkExtent3D buf_extent_el =
-         meta_region_extent_el(image->vk_format, &bufferExtent);
+         meta_region_extent_el(image, &bufferExtent);
+
+      /* Start creating blit rect */
       const VkExtent3D img_extent_el =
-         meta_region_extent_el(image->vk_format, &pRegions[r].imageExtent);
+         meta_region_extent_el(image, &pRegions[r].imageExtent);
       struct anv_meta_blit2d_rect rect = {
-         .width = MAX2(buf_extent_el.width, img_extent_el.width),
-         .height = MAX2(buf_extent_el.height, img_extent_el.height),
+         .width = img_extent_el.width,
+         .height =  img_extent_el.height,
       };
 
       /* Create blit surfaces */
@@ -137,12 +161,14 @@ meta_copy_buffer_to_image(struct anv_cmd_buffer *cmd_buffer,
          &anv_image_get_surface_for_aspect_mask(image, aspect)->isl;
       struct anv_meta_blit2d_surf img_bsurf =
          blit_surf_for_image(image, img_isl_surf);
+      enum isl_format buf_format = anv_get_isl_format(image->vk_format, aspect,
+                                                      VK_IMAGE_TILING_LINEAR);
       struct anv_meta_blit2d_surf buf_bsurf = {
          .bo = buffer->bo,
          .tiling = ISL_TILING_LINEAR,
          .base_offset = buffer->offset + pRegions[r].bufferOffset,
-         .bs = forward ? image->format->isl_layout->bs : img_bsurf.bs,
-         .pitch = rect.width * buf_bsurf.bs,
+         .bs = isl_format_get_layout(buf_format)->bs,
+         .pitch = buf_extent_el.width * buf_bsurf.bs,
       };
 
       /* Set direction-dependent variables */
@@ -152,7 +178,7 @@ meta_copy_buffer_to_image(struct anv_cmd_buffer *cmd_buffer,
       uint32_t *y_offset = forward ? &rect.dst_y : &rect.src_y;
 
       /* Loop through each 3D or array slice */
-      unsigned num_slices_3d = pRegions[r].imageExtent.depth;
+      unsigned num_slices_3d = img_extent_el.depth;
       unsigned num_slices_array = pRegions[r].imageSubresource.layerCount;
       unsigned slice_3d = 0;
       unsigned slice_array = 0;
@@ -163,7 +189,7 @@ meta_copy_buffer_to_image(struct anv_cmd_buffer *cmd_buffer,
                                     pRegions[r].imageSubresource.mipLevel,
                                     pRegions[r].imageSubresource.baseArrayLayer
                                        + slice_array,
-                                    pRegions[r].imageOffset.z + slice_3d,
+                                    img_offset_el.z + slice_3d,
                                     x_offset,
                                     y_offset);
          *x_offset += img_offset_el.x;
@@ -177,7 +203,8 @@ meta_copy_buffer_to_image(struct anv_cmd_buffer *cmd_buffer,
           * increment the offset directly in the image effectively
           * re-binding it to different backing memory.
           */
-         buf_bsurf.base_offset += rect.width * rect.height * buf_bsurf.bs;
+         buf_bsurf.base_offset += buf_extent_el.width *
+                                  buf_extent_el.height * buf_bsurf.bs;
 
          if (image->type == VK_IMAGE_TYPE_3D)
             slice_3d++;
@@ -259,20 +286,30 @@ void anv_CmdCopyImage(
       struct anv_meta_blit2d_surf b_dst =
          blit_surf_for_image(dest_image, dst_isl_surf);
 
-      /* Start creating blit rect */
+      /**
+       * 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->vk_format, &pRegions[r].extent);
+         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 = pRegions[r].extent.depth;
+      unsigned num_slices_3d = img_extent_el.depth;
       unsigned num_slices_array = pRegions[r].dstSubresource.layerCount;
       unsigned slice_3d = 0;
       unsigned slice_array = 0;
@@ -283,14 +320,14 @@ void anv_CmdCopyImage(
                                     pRegions[r].dstSubresource.mipLevel,
                                     pRegions[r].dstSubresource.baseArrayLayer
                                        + slice_array,
-                                    pRegions[r].dstOffset.z + slice_3d,
+                                    dst_offset_el.z + slice_3d,
                                     &rect.dst_x,
                                     &rect.dst_y);
          isl_surf_get_image_offset_el(src_isl_surf,
                                     pRegions[r].srcSubresource.mipLevel,
                                     pRegions[r].srcSubresource.baseArrayLayer
                                        + slice_array,
-                                    pRegions[r].srcOffset.z + slice_3d,
+                                    src_offset_el.z + slice_3d,
                                     &rect.src_x,
                                     &rect.src_y);
          rect.dst_x += dst_offset_el.x;