Mesa (main): dzn: Fix copies of block-based formats

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Jun 29 20:05:20 UTC 2022


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

Author: Boris Brezillon <boris.brezillon at collabora.com>
Date:   Tue Jun 28 12:00:50 2022 +0200

dzn: Fix copies of block-based formats

D3D12 wants Width, Height and Depth to be aligned on the block width,
height and depth size. But Vulkan allows the width, height or depth to
be unaligned at the image boundary if image.{width,height,depth} is
not aligned.

Let's explicitly align things in the copy paths.

Reviewed-by: Jesse Natalie <jenatali at microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17250>

---

 src/microsoft/vulkan/dzn_cmd_buffer.c | 114 +++++++++++++++++++---------------
 src/microsoft/vulkan/dzn_image.c      |  18 ++++++
 src/microsoft/vulkan/dzn_private.h    |   4 ++
 3 files changed, 86 insertions(+), 50 deletions(-)

diff --git a/src/microsoft/vulkan/dzn_cmd_buffer.c b/src/microsoft/vulkan/dzn_cmd_buffer.c
index 13c449f9892..59a115e4bef 100644
--- a/src/microsoft/vulkan/dzn_cmd_buffer.c
+++ b/src/microsoft/vulkan/dzn_cmd_buffer.c
@@ -1608,15 +1608,21 @@ dzn_cmd_buffer_copy_buf2img_region(struct dzn_cmd_buffer *cmdbuf,
    ID3D12Device2 *dev = device->dev;
    ID3D12GraphicsCommandList1 *cmdlist = cmdbuf->cmdlist;
 
-   const VkBufferImageCopy2 *region = &info->pRegions[r];
+   VkBufferImageCopy2 region = info->pRegions[r];
    enum pipe_format pfmt = vk_format_to_pipe_format(dst_image->vk.format);
    uint32_t blkh = util_format_get_blockheight(pfmt);
    uint32_t blkd = util_format_get_blockdepth(pfmt);
 
+   /* D3D12 wants block aligned offsets/extent, but vulkan allows the extent
+    * to not be block aligned if it's reaching the image boundary, offsets still
+    * have to be aligned. Align the image extent to make D3D12 happy.
+    */
+   dzn_image_align_extent(dst_image, &region.imageExtent);
+
    D3D12_TEXTURE_COPY_LOCATION dst_img_loc =
-      dzn_image_get_copy_loc(dst_image, &region->imageSubresource, aspect, l);
+      dzn_image_get_copy_loc(dst_image, &region.imageSubresource, aspect, l);
    D3D12_TEXTURE_COPY_LOCATION src_buf_loc =
-      dzn_buffer_get_copy_loc(src_buffer, dst_image->vk.format, region, aspect, l);
+      dzn_buffer_get_copy_loc(src_buffer, dst_image->vk.format, &region, aspect, l);
 
    if (dzn_buffer_supports_region_copy(&src_buf_loc)) {
       /* RowPitch and Offset are properly aligned, we can copy
@@ -1626,15 +1632,15 @@ dzn_cmd_buffer_copy_buf2img_region(struct dzn_cmd_buffer *cmdbuf,
          .left = 0,
          .top = 0,
          .front = 0,
-         .right = region->imageExtent.width,
-         .bottom = region->imageExtent.height,
-         .back = region->imageExtent.depth,
+         .right = region.imageExtent.width,
+         .bottom = region.imageExtent.height,
+         .back = region.imageExtent.depth,
       };
 
       ID3D12GraphicsCommandList1_CopyTextureRegion(cmdlist, &dst_img_loc,
-                                                   region->imageOffset.x,
-                                                   region->imageOffset.y,
-                                                   region->imageOffset.z,
+                                                   region.imageOffset.x,
+                                                   region.imageOffset.y,
+                                                   region.imageOffset.z,
                                                    &src_buf_loc, &src_box);
       return;
    }
@@ -1647,22 +1653,22 @@ dzn_cmd_buffer_copy_buf2img_region(struct dzn_cmd_buffer *cmdbuf,
       .back = blkd,
    };
 
-   for (uint32_t z = 0; z < region->imageExtent.depth; z += blkd) {
-      for (uint32_t y = 0; y < region->imageExtent.height; y += blkh) {
+   for (uint32_t z = 0; z < region.imageExtent.depth; z += blkd) {
+      for (uint32_t y = 0; y < region.imageExtent.height; y += blkh) {
          uint32_t src_x;
 
          D3D12_TEXTURE_COPY_LOCATION src_buf_line_loc =
             dzn_buffer_get_line_copy_loc(src_buffer, dst_image->vk.format,
-                                         region, &src_buf_loc,
+                                         &region, &src_buf_loc,
                                          y, z, &src_x);
 
          src_box.left = src_x;
-         src_box.right = src_x + region->imageExtent.width;
+         src_box.right = src_x + region.imageExtent.width;
          ID3D12GraphicsCommandList1_CopyTextureRegion(cmdlist,
                                                       &dst_img_loc,
-                                                      region->imageOffset.x,
-                                                      region->imageOffset.y + y,
-                                                      region->imageOffset.z + z,
+                                                      region.imageOffset.x,
+                                                      region.imageOffset.y + y,
+                                                      region.imageOffset.z + z,
                                                       &src_buf_line_loc,
                                                       &src_box);
       }
@@ -1683,27 +1689,33 @@ dzn_cmd_buffer_copy_img2buf_region(struct dzn_cmd_buffer *cmdbuf,
    ID3D12Device2 *dev = device->dev;
    ID3D12GraphicsCommandList1 *cmdlist = cmdbuf->cmdlist;
 
-   const VkBufferImageCopy2 *region = &info->pRegions[r];
+   VkBufferImageCopy2 region = info->pRegions[r];
    enum pipe_format pfmt = vk_format_to_pipe_format(src_image->vk.format);
    uint32_t blkh = util_format_get_blockheight(pfmt);
    uint32_t blkd = util_format_get_blockdepth(pfmt);
 
+   /* D3D12 wants block aligned offsets/extent, but vulkan allows the extent
+    * to not be block aligned if it's reaching the image boundary, offsets still
+    * have to be aligned. Align the image extent to make D3D12 happy.
+    */
+   dzn_image_align_extent(src_image, &region.imageExtent);
+
    D3D12_TEXTURE_COPY_LOCATION src_img_loc =
-      dzn_image_get_copy_loc(src_image, &region->imageSubresource, aspect, l);
+      dzn_image_get_copy_loc(src_image, &region.imageSubresource, aspect, l);
    D3D12_TEXTURE_COPY_LOCATION dst_buf_loc =
-      dzn_buffer_get_copy_loc(dst_buffer, src_image->vk.format, region, aspect, l);
+      dzn_buffer_get_copy_loc(dst_buffer, src_image->vk.format, &region, aspect, l);
 
    if (dzn_buffer_supports_region_copy(&dst_buf_loc)) {
       /* RowPitch and Offset are properly aligned on 256 bytes, we can copy
        * the whole thing in one call.
        */
       D3D12_BOX src_box = {
-         .left = (UINT)region->imageOffset.x,
-         .top = (UINT)region->imageOffset.y,
-         .front = (UINT)region->imageOffset.z,
-         .right = (UINT)(region->imageOffset.x + region->imageExtent.width),
-         .bottom = (UINT)(region->imageOffset.y + region->imageExtent.height),
-         .back = (UINT)(region->imageOffset.z + region->imageExtent.depth),
+         .left = (UINT)region.imageOffset.x,
+         .top = (UINT)region.imageOffset.y,
+         .front = (UINT)region.imageOffset.z,
+         .right = (UINT)(region.imageOffset.x + region.imageExtent.width),
+         .bottom = (UINT)(region.imageOffset.y + region.imageExtent.height),
+         .back = (UINT)(region.imageOffset.z + region.imageExtent.depth),
       };
 
       ID3D12GraphicsCommandList1_CopyTextureRegion(cmdlist, &dst_buf_loc,
@@ -1713,24 +1725,24 @@ dzn_cmd_buffer_copy_img2buf_region(struct dzn_cmd_buffer *cmdbuf,
    }
 
    D3D12_BOX src_box = {
-      .left = (UINT)region->imageOffset.x,
-      .right = (UINT)(region->imageOffset.x + region->imageExtent.width),
+      .left = (UINT)region.imageOffset.x,
+      .right = (UINT)(region.imageOffset.x + region.imageExtent.width),
    };
 
    /* Copy line-by-line if things are not properly aligned. */
-   for (uint32_t z = 0; z < region->imageExtent.depth; z += blkd) {
-      src_box.front = region->imageOffset.z + z;
+   for (uint32_t z = 0; z < region.imageExtent.depth; z += blkd) {
+      src_box.front = region.imageOffset.z + z;
       src_box.back = src_box.front + blkd;
 
-      for (uint32_t y = 0; y < region->imageExtent.height; y += blkh) {
+      for (uint32_t y = 0; y < region.imageExtent.height; y += blkh) {
          uint32_t dst_x;
 
          D3D12_TEXTURE_COPY_LOCATION dst_buf_line_loc =
             dzn_buffer_get_line_copy_loc(dst_buffer, src_image->vk.format,
-                                         region, &dst_buf_loc,
+                                         &region, &dst_buf_loc,
                                          y, z, &dst_x);
 
-         src_box.top = region->imageOffset.y + y;
+         src_box.top = region.imageOffset.y + y;
          src_box.bottom = src_box.top + blkh;
 
          ID3D12GraphicsCommandList1_CopyTextureRegion(cmdlist,
@@ -1758,9 +1770,11 @@ dzn_cmd_buffer_copy_img_chunk(struct dzn_cmd_buffer *cmdbuf,
    ID3D12Device2 *dev = device->dev;
    ID3D12GraphicsCommandList1 *cmdlist = cmdbuf->cmdlist;
 
-   const VkImageCopy2 *region = &info->pRegions[r];
-   const VkImageSubresourceLayers *src_subres = &region->srcSubresource;
-   const VkImageSubresourceLayers *dst_subres = &region->dstSubresource;
+   VkImageCopy2 region = info->pRegions[r];
+   dzn_image_align_extent(src, &region.extent);
+
+   const VkImageSubresourceLayers *src_subres = &region.srcSubresource;
+   const VkImageSubresourceLayers *dst_subres = &region.dstSubresource;
    VkFormat src_format =
       dzn_image_get_plane_format(src->vk.format, aspect);
    VkFormat dst_format =
@@ -1774,8 +1788,8 @@ dzn_cmd_buffer_copy_img_chunk(struct dzn_cmd_buffer *cmdbuf,
    uint32_t dst_blkw = util_format_get_blockwidth(dst_pfmt);
    uint32_t dst_blkh = util_format_get_blockheight(dst_pfmt);
    uint32_t dst_blkd = util_format_get_blockdepth(dst_pfmt);
-   uint32_t dst_z = region->dstOffset.z, src_z = region->srcOffset.z;
-   uint32_t depth = region->extent.depth;
+   uint32_t dst_z = region.dstOffset.z, src_z = region.srcOffset.z;
+   uint32_t depth = region.extent.depth;
    uint32_t dst_l = l, src_l = l;
 
    assert(src_subres->aspectMask == dst_subres->aspectMask);
@@ -1800,18 +1814,18 @@ dzn_cmd_buffer_copy_img_chunk(struct dzn_cmd_buffer *cmdbuf,
    D3D12_TEXTURE_COPY_LOCATION src_loc = dzn_image_get_copy_loc(src, src_subres, aspect, src_l);
 
    D3D12_BOX src_box = {
-      .left = (UINT)MAX2(region->srcOffset.x, 0),
-      .top = (UINT)MAX2(region->srcOffset.y, 0),
+      .left = (UINT)MAX2(region.srcOffset.x, 0),
+      .top = (UINT)MAX2(region.srcOffset.y, 0),
       .front = (UINT)MAX2(src_z, 0),
-      .right = (UINT)region->srcOffset.x + region->extent.width,
-      .bottom = (UINT)region->srcOffset.y + region->extent.height,
+      .right = (UINT)region.srcOffset.x + region.extent.width,
+      .bottom = (UINT)region.srcOffset.y + region.extent.height,
       .back = (UINT)src_z + depth,
    };
 
    if (!tmp_loc->pResource) {
       ID3D12GraphicsCommandList1_CopyTextureRegion(cmdlist, &dst_loc,
-                                                   region->dstOffset.x,
-                                                   region->dstOffset.y,
+                                                   region.dstOffset.x,
+                                                   region.dstOffset.y,
                                                    dst_z, &src_loc,
                                                    &src_box);
       return;
@@ -1819,8 +1833,8 @@ dzn_cmd_buffer_copy_img_chunk(struct dzn_cmd_buffer *cmdbuf,
 
    tmp_desc->Format =
       dzn_image_get_placed_footprint_format(src->vk.format, aspect);
-   tmp_desc->Width = region->extent.width;
-   tmp_desc->Height = region->extent.height;
+   tmp_desc->Width = region.extent.width;
+   tmp_desc->Height = region.extent.height;
 
    ID3D12Device1_GetCopyableFootprints(dev, tmp_desc,
                                        0, 1, 0,
@@ -1848,9 +1862,9 @@ dzn_cmd_buffer_copy_img_chunk(struct dzn_cmd_buffer *cmdbuf,
    tmp_desc->Format =
       dzn_image_get_placed_footprint_format(dst->vk.format, aspect);
    if (src_blkw != dst_blkw)
-      tmp_desc->Width = DIV_ROUND_UP(region->extent.width, src_blkw) * dst_blkw;
+      tmp_desc->Width = DIV_ROUND_UP(region.extent.width, src_blkw) * dst_blkw;
    if (src_blkh != dst_blkh)
-      tmp_desc->Height = DIV_ROUND_UP(region->extent.height, src_blkh) * dst_blkh;
+      tmp_desc->Height = DIV_ROUND_UP(region.extent.height, src_blkh) * dst_blkh;
 
    ID3D12Device1_GetCopyableFootprints(device->dev, tmp_desc,
                                        0, 1, 0,
@@ -1861,7 +1875,7 @@ dzn_cmd_buffer_copy_img_chunk(struct dzn_cmd_buffer *cmdbuf,
       tmp_loc->PlacedFootprint.Footprint.Depth =
          DIV_ROUND_UP(depth, src_blkd) * dst_blkd;
    } else {
-      tmp_loc->PlacedFootprint.Footprint.Depth = region->extent.depth;
+      tmp_loc->PlacedFootprint.Footprint.Depth = region.extent.depth;
    }
 
    D3D12_BOX tmp_box = {
@@ -1874,8 +1888,8 @@ dzn_cmd_buffer_copy_img_chunk(struct dzn_cmd_buffer *cmdbuf,
    };
 
    ID3D12GraphicsCommandList1_CopyTextureRegion(cmdlist, &dst_loc,
-                                                region->dstOffset.x,
-                                                region->dstOffset.y,
+                                                region.dstOffset.x,
+                                                region.dstOffset.y,
                                                 dst_z,
                                                 tmp_loc, &tmp_box);
 }
diff --git a/src/microsoft/vulkan/dzn_image.c b/src/microsoft/vulkan/dzn_image.c
index 7d8daddb129..b585f8ca086 100644
--- a/src/microsoft/vulkan/dzn_image.c
+++ b/src/microsoft/vulkan/dzn_image.c
@@ -28,6 +28,24 @@
 #include "vk_format.h"
 #include "vk_util.h"
 
+void
+dzn_image_align_extent(const struct dzn_image *image,
+                       VkExtent3D *extent)
+{
+   enum pipe_format pfmt = vk_format_to_pipe_format(image->vk.format);
+   uint32_t blkw = util_format_get_blockwidth(pfmt);
+   uint32_t blkh = util_format_get_blockheight(pfmt);
+   uint32_t blkd = util_format_get_blockdepth(pfmt);
+
+   assert(util_is_power_of_two_nonzero(blkw) &&
+          util_is_power_of_two_nonzero(blkh) &&
+          util_is_power_of_two_nonzero(blkh));
+
+   extent->width = ALIGN_POT(extent->width, blkw);
+   extent->height = ALIGN_POT(extent->height, blkh);
+   extent->depth = ALIGN_POT(extent->depth, blkd);
+}
+
 static void
 dzn_image_destroy(struct dzn_image *image,
                   const VkAllocationCallbacks *pAllocator)
diff --git a/src/microsoft/vulkan/dzn_private.h b/src/microsoft/vulkan/dzn_private.h
index af8841e02b3..bc875bc103d 100644
--- a/src/microsoft/vulkan/dzn_private.h
+++ b/src/microsoft/vulkan/dzn_private.h
@@ -882,6 +882,10 @@ struct dzn_image {
    VkDeviceSize mem_offset;
 };
 
+void
+dzn_image_align_extent(const struct dzn_image *image,
+                       VkExtent3D *extent);
+
 DXGI_FORMAT
 dzn_image_get_dxgi_format(VkFormat format,
                           VkImageUsageFlags usage,



More information about the mesa-commit mailing list