Mesa (master): anv: Canonicalize buffer formats for image/buffer copies

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Jan 20 16:22:34 UTC 2020


Module: Mesa
Branch: master
Commit: dd92179a72e5263b9db730d92a883e2536aa4474
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=dd92179a72e5263b9db730d92a883e2536aa4474

Author: Jason Ekstrand <jason at jlekstrand.net>
Date:   Fri Jan 17 17:46:31 2020 -0600

anv: Canonicalize buffer formats for image/buffer copies

Some formats, in particular YCbCr formats and ASTC have additional
restrictions.  We already whack ASTC formats to RGBA32_UINT because the
hardware doesn't allow LINEAR with ASTC.  However, we need to fix YCbCr
formats as well because they come with alignment restrictions that we
can't guarantee are satisfied.  We're using blorp_copy to do the copies
so we may as well just stomp formats for everything.

Fixes: b24b93d5843 "anv: enable VK_KHR_sampler_ycbcr_conversion"
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin at intel.com>
Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3460>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3460>

---

 src/intel/vulkan/anv_blorp.c | 62 ++++++++++++++++++++++++++++++--------------
 1 file changed, 42 insertions(+), 20 deletions(-)

diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c
index 5649b00f29f..71690eab037 100644
--- a/src/intel/vulkan/anv_blorp.c
+++ b/src/intel/vulkan/anv_blorp.c
@@ -410,6 +410,24 @@ void anv_CmdCopyImage(
    blorp_batch_finish(&batch);
 }
 
+static enum isl_format
+isl_format_for_size(unsigned size_B)
+{
+   /* Prefer 32-bit per component formats for CmdFillBuffer */
+   switch (size_B) {
+   case 1:  return ISL_FORMAT_R8_UINT;
+   case 2:  return ISL_FORMAT_R16_UINT;
+   case 3:  return ISL_FORMAT_R8G8B8_UINT;
+   case 4:  return ISL_FORMAT_R32_UINT;
+   case 6:  return ISL_FORMAT_R16G16B16_UINT;
+   case 8:  return ISL_FORMAT_R32G32_UINT;
+   case 12: return ISL_FORMAT_R32G32B32_UINT;
+   case 16: return ISL_FORMAT_R32G32B32A32_UINT;
+   default:
+      unreachable("Unknown format size");
+   }
+}
+
 static void
 copy_buffer_to_image(struct anv_cmd_buffer *cmd_buffer,
                      struct anv_buffer *anv_buffer,
@@ -457,12 +475,11 @@ copy_buffer_to_image(struct anv_cmd_buffer *cmd_buffer,
             anv_get_layerCount(anv_image, &pRegions[r].imageSubresource);
       }
 
-      const enum isl_format buffer_format =
+      const enum isl_format linear_format =
          anv_get_isl_format(&cmd_buffer->device->info, anv_image->vk_format,
                             aspect, VK_IMAGE_TILING_LINEAR);
-
-      const struct isl_format_layout *buffer_fmtl =
-         isl_format_get_layout(buffer_format);
+      const struct isl_format_layout *linear_fmtl =
+         isl_format_get_layout(linear_format);
 
       const uint32_t buffer_row_length =
          pRegions[r].bufferRowLength ?
@@ -473,17 +490,34 @@ copy_buffer_to_image(struct anv_cmd_buffer *cmd_buffer,
          pRegions[r].bufferImageHeight : extent.height;
 
       const uint32_t buffer_row_pitch =
-         DIV_ROUND_UP(buffer_row_length, buffer_fmtl->bw) *
-         (buffer_fmtl->bpb / 8);
+         DIV_ROUND_UP(buffer_row_length, linear_fmtl->bw) *
+         (linear_fmtl->bpb / 8);
 
       const uint32_t buffer_layer_stride =
-         DIV_ROUND_UP(buffer_image_height, buffer_fmtl->bh) *
+         DIV_ROUND_UP(buffer_image_height, linear_fmtl->bh) *
          buffer_row_pitch;
 
+      /* Some formats have additional restrictions which may cause ISL to
+       * fail to create a surface for us.  Some examples include:
+       *
+       *    1. ASTC formats are not allowed to be LINEAR and must be tiled
+       *    2. YCbCr formats have to have 2-pixel aligned strides
+       *
+       * To avoid these issues, we always bind the buffer as if it's a
+       * "normal" format like RGBA32_UINT.  Since we're using blorp_copy,
+       * the format doesn't matter as long as it has the right bpb.
+       */
+      const VkExtent2D buffer_extent = {
+         .width = DIV_ROUND_UP(extent.width, linear_fmtl->bw),
+         .height = DIV_ROUND_UP(extent.height, linear_fmtl->bh),
+      };
+      const enum isl_format buffer_format =
+         isl_format_for_size(linear_fmtl->bpb / 8);
+
       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_extent.width, buffer_extent.height,
                                     buffer_row_pitch, buffer_format,
                                     &buffer.surf, &buffer_isl_surf);
 
@@ -699,18 +733,6 @@ void anv_CmdBlitImage(
    blorp_batch_finish(&batch);
 }
 
-static enum isl_format
-isl_format_for_size(unsigned size_B)
-{
-   switch (size_B) {
-   case 4:  return ISL_FORMAT_R32_UINT;
-   case 8:  return ISL_FORMAT_R32G32_UINT;
-   case 16: return ISL_FORMAT_R32G32B32A32_UINT;
-   default:
-      unreachable("Not a power-of-two format size");
-   }
-}
-
 /**
  * Returns the greatest common divisor of a and b that is a power of two.
  */



More information about the mesa-commit mailing list