Mesa (main): d3d12: Handle depth readback on drivers that require full-resource copies for depth

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Dec 3 23:25:26 UTC 2021


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

Author: Jesse Natalie <jenatali at microsoft.com>
Date:   Fri Dec  3 10:45:20 2021 -0800

d3d12: Handle depth readback on drivers that require full-resource copies for depth

Reviewed-by: Bill Kristiansen <billkris at microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14051>

---

 src/gallium/drivers/d3d12/d3d12_resource.cpp | 129 +++++++++++++++++++++------
 src/gallium/drivers/d3d12/d3d12_resource.h   |   2 +
 2 files changed, 102 insertions(+), 29 deletions(-)

diff --git a/src/gallium/drivers/d3d12/d3d12_resource.cpp b/src/gallium/drivers/d3d12/d3d12_resource.cpp
index aa9283b0f78..d5e36e9f145 100644
--- a/src/gallium/drivers/d3d12/d3d12_resource.cpp
+++ b/src/gallium/drivers/d3d12/d3d12_resource.cpp
@@ -545,7 +545,8 @@ fill_buffer_location(struct d3d12_context *ctx,
    D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint;
    uint64_t offset = 0;
    auto descr = d3d12_resource_underlying(res, &offset)->GetDesc();
-   ID3D12Device* dev = d3d12_screen(ctx->base.screen)->dev;
+   struct d3d12_screen *screen = d3d12_screen(ctx->base.screen);
+   ID3D12Device* dev = screen->dev;
 
    unsigned sub_resid = get_subresource_id(res, resid, z, trans->base.b.level);
    dev->GetCopyableFootprints(&descr, sub_resid, 1, 0, &footprint, nullptr, nullptr, nullptr);
@@ -555,12 +556,19 @@ fill_buffer_location(struct d3d12_context *ctx,
    buf_loc.PlacedFootprint = footprint;
    buf_loc.PlacedFootprint.Offset += offset;
 
-   buf_loc.PlacedFootprint.Footprint.Width = ALIGN(trans->base.b.box.width,
-                                                   util_format_get_blockwidth(res->base.b.format));
-   buf_loc.PlacedFootprint.Footprint.Height = ALIGN(trans->base.b.box.height,
-                                                    util_format_get_blockheight(res->base.b.format));
-   buf_loc.PlacedFootprint.Footprint.Depth = ALIGN(depth,
-                                                   util_format_get_blockdepth(res->base.b.format));
+   if (util_format_has_depth(util_format_description(res->base.b.format)) &&
+       screen->opts2.ProgrammableSamplePositionsTier == D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED) {
+      buf_loc.PlacedFootprint.Footprint.Width = res->base.b.width0;
+      buf_loc.PlacedFootprint.Footprint.Height = res->base.b.height0;
+      buf_loc.PlacedFootprint.Footprint.Depth = res->base.b.depth0;
+   } else {
+      buf_loc.PlacedFootprint.Footprint.Width = ALIGN(trans->base.b.box.width,
+                                                      util_format_get_blockwidth(res->base.b.format));
+      buf_loc.PlacedFootprint.Footprint.Height = ALIGN(trans->base.b.box.height,
+                                                       util_format_get_blockheight(res->base.b.format));
+      buf_loc.PlacedFootprint.Footprint.Depth = ALIGN(depth,
+                                                      util_format_get_blockdepth(res->base.b.format));
+   }
 
    buf_loc.PlacedFootprint.Footprint.RowPitch = trans->base.b.stride;
 
@@ -608,6 +616,7 @@ transfer_buf_to_image_part(struct d3d12_context *ctx,
                    util_format_name(res->base.b.format));
    }
 
+   struct d3d12_screen *screen = d3d12_screen(res->base.b.screen);
    struct copy_info copy_info;
    copy_info.src = staging_res;
    copy_info.src_loc = fill_buffer_location(ctx, res, staging_res, trans, depth, resid, z);
@@ -615,8 +624,14 @@ transfer_buf_to_image_part(struct d3d12_context *ctx,
    copy_info.src_box = nullptr;
    copy_info.dst = res;
    copy_info.dst_loc = fill_texture_location(res, trans, resid, z);
-   copy_info.dst_x = trans->base.b.box.x;
-   copy_info.dst_y = trans->base.b.box.y;
+   if (util_format_has_depth(util_format_description(res->base.b.format)) &&
+       screen->opts2.ProgrammableSamplePositionsTier == D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED) {
+      copy_info.dst_x = 0;
+      copy_info.dst_y = 0;
+   } else {
+      copy_info.dst_x = trans->base.b.box.x;
+      copy_info.dst_y = trans->base.b.box.y;
+   }
    copy_info.dst_z = res->base.b.target == PIPE_TEXTURE_CUBE ? 0 : dest_z;
    copy_info.src_box = nullptr;
 
@@ -657,6 +672,7 @@ transfer_image_part_to_buf(struct d3d12_context *ctx,
    struct pipe_box *box = &trans->base.b.box;
    D3D12_BOX src_box = {};
 
+   struct d3d12_screen *screen = d3d12_screen(res->base.b.screen);
    struct copy_info copy_info;
    copy_info.src_box = nullptr;
    copy_info.src = res;
@@ -667,9 +683,13 @@ transfer_image_part_to_buf(struct d3d12_context *ctx,
    copy_info.dst_loc.PlacedFootprint.Offset = (z  - start_layer) * trans->base.b.layer_stride;
    copy_info.dst_x = copy_info.dst_y = copy_info.dst_z = 0;
 
-   if (!util_texrange_covers_whole_level(&res->base.b, trans->base.b.level,
-                                         box->x, box->y, start_box_z,
-                                         box->width, box->height, depth)) {
+   bool whole_resource = util_texrange_covers_whole_level(&res->base.b, trans->base.b.level,
+                                                          box->x, box->y, start_box_z,
+                                                          box->width, box->height, depth);
+   if (util_format_has_depth(util_format_description(res->base.b.format)) &&
+       screen->opts2.ProgrammableSamplePositionsTier == D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED)
+      whole_resource = true;
+   if (!whole_resource) {
       src_box.left = box->x;
       src_box.right = box->x + box->width;
       src_box.top = box->y;
@@ -875,15 +895,31 @@ private:
  * buffers, read back both resources and interleave the data.
  */
 static void
-prepare_zs_layer_strides(struct d3d12_resource *res,
+prepare_zs_layer_strides(struct d3d12_screen *screen,
+                         struct d3d12_resource *res,
                          const struct pipe_box *box,
                          struct d3d12_transfer *trans)
 {
-   trans->base.b.stride = align(util_format_get_stride(res->base.b.format, box->width),
-                              D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
+   bool copy_whole_resource = screen->opts2.ProgrammableSamplePositionsTier == D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED;
+   int width = copy_whole_resource ? res->base.b.width0 : box->width;
+   int height = copy_whole_resource ? res->base.b.height0 : box->height;
+
+   trans->base.b.stride = align(util_format_get_stride(res->base.b.format, width),
+                                D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
    trans->base.b.layer_stride = util_format_get_2d_size(res->base.b.format,
-                                                      trans->base.b.stride,
-                                                      box->height);
+                                                        trans->base.b.stride,
+                                                        height);
+
+   if (copy_whole_resource) {
+      trans->zs_cpu_copy_stride = align(util_format_get_stride(res->base.b.format, box->width),
+                                        D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
+      trans->zs_cpu_copy_layer_stride = util_format_get_2d_size(res->base.b.format,
+                                                                trans->base.b.stride,
+                                                                box->height);
+   } else {
+      trans->zs_cpu_copy_stride = trans->base.b.stride;
+      trans->zs_cpu_copy_layer_stride = trans->base.b.layer_stride;
+   }
 }
 
 static void *
@@ -892,8 +928,9 @@ read_zs_surface(struct d3d12_context *ctx, struct d3d12_resource *res,
                 struct d3d12_transfer *trans)
 {
    pipe_screen *pscreen = ctx->base.screen;
+   struct d3d12_screen *screen = d3d12_screen(pscreen);
 
-   prepare_zs_layer_strides(res, box, trans);
+   prepare_zs_layer_strides(screen, res, box, trans);
 
    struct pipe_resource tmpl;
    memset(&tmpl, 0, sizeof tmpl);
@@ -929,7 +966,7 @@ read_zs_surface(struct d3d12_context *ctx, struct d3d12_resource *res,
 
    d3d12_flush_cmdlist_and_wait(ctx);
 
-   void *depth_ptr = depth_buffer.map();
+   uint8_t *depth_ptr = (uint8_t *)depth_buffer.map();
    if (!depth_ptr) {
       debug_printf("Mapping staging depth buffer failed\n");
       return NULL;
@@ -941,7 +978,7 @@ read_zs_surface(struct d3d12_context *ctx, struct d3d12_resource *res,
       return NULL;
    }
 
-   uint8_t *buf = (uint8_t *)malloc(trans->base.b.layer_stride);
+   uint8_t *buf = (uint8_t *)malloc(trans->zs_cpu_copy_layer_stride);
    if (!buf)
       return NULL;
 
@@ -949,16 +986,24 @@ read_zs_surface(struct d3d12_context *ctx, struct d3d12_resource *res,
 
    switch (res->base.b.format) {
    case PIPE_FORMAT_Z24_UNORM_S8_UINT:
-      util_format_z24_unorm_s8_uint_pack_separate(buf, trans->base.b.stride,
+      if (screen->opts2.ProgrammableSamplePositionsTier == D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED) {
+         depth_ptr += trans->base.b.box.y * trans->base.b.stride + trans->base.b.box.x * 4;
+         stencil_ptr += trans->base.b.box.y * trans->base.b.stride + trans->base.b.box.x * 4;
+      }
+      util_format_z24_unorm_s8_uint_pack_separate(buf, trans->zs_cpu_copy_stride,
                                                   (uint32_t *)depth_ptr, trans->base.b.stride,
                                                   stencil_ptr, trans->base.b.stride,
                                                   trans->base.b.box.width, trans->base.b.box.height);
       break;
    case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
-      util_format_z32_float_s8x24_uint_pack_z_float(buf, trans->base.b.stride,
+      if (screen->opts2.ProgrammableSamplePositionsTier == D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED) {
+         depth_ptr += trans->base.b.box.y * trans->base.b.stride + trans->base.b.box.x * 4;
+         stencil_ptr += trans->base.b.box.y * trans->base.b.stride + trans->base.b.box.x;
+      }
+      util_format_z32_float_s8x24_uint_pack_z_float(buf, trans->zs_cpu_copy_stride,
                                                     (float *)depth_ptr, trans->base.b.stride,
                                                     trans->base.b.box.width, trans->base.b.box.height);
-      util_format_z32_float_s8x24_uint_pack_s_8uint(buf, trans->base.b.stride,
+      util_format_z32_float_s8x24_uint_pack_s_8uint(buf, trans->zs_cpu_copy_stride,
                                                     stencil_ptr, trans->base.b.stride,
                                                     trans->base.b.box.width, trans->base.b.box.height);
       break;
@@ -974,7 +1019,8 @@ prepare_write_zs_surface(struct d3d12_resource *res,
                          const struct pipe_box *box,
                          struct d3d12_transfer *trans)
 {
-   prepare_zs_layer_strides(res, box, trans);
+   struct d3d12_screen *screen = d3d12_screen(res->base.b.screen);
+   prepare_zs_layer_strides(screen, res, box, trans);
    uint32_t *buf = (uint32_t *)malloc(trans->base.b.layer_stride);
    if (!buf)
       return NULL;
@@ -987,6 +1033,7 @@ static void
 write_zs_surface(struct pipe_context *pctx, struct d3d12_resource *res,
                  struct d3d12_transfer *trans)
 {
+   struct d3d12_screen *screen = d3d12_screen(res->base.b.screen);
    struct pipe_resource tmpl;
    memset(&tmpl, 0, sizeof tmpl);
    tmpl.target = PIPE_BUFFER;
@@ -1011,7 +1058,7 @@ write_zs_surface(struct pipe_context *pctx, struct d3d12_resource *res,
       return;
    }
 
-   void *depth_ptr = depth_buffer.map();
+   uint8_t *depth_ptr = (uint8_t *)depth_buffer.map();
    if (!depth_ptr) {
       debug_printf("Mapping staging depth buffer failed\n");
       return;
@@ -1025,19 +1072,27 @@ write_zs_surface(struct pipe_context *pctx, struct d3d12_resource *res,
 
    switch (res->base.b.format) {
    case PIPE_FORMAT_Z24_UNORM_S8_UINT:
+      if (screen->opts2.ProgrammableSamplePositionsTier == D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED) {
+         depth_ptr += trans->base.b.box.y * trans->base.b.stride + trans->base.b.box.x * 4;
+         stencil_ptr += trans->base.b.box.y * trans->base.b.stride + trans->base.b.box.x * 4;
+      }
       util_format_z32_unorm_unpack_z_32unorm((uint32_t *)depth_ptr, trans->base.b.stride, (uint8_t*)trans->data,
-                                             trans->base.b.stride, trans->base.b.box.width,
+                                             trans->zs_cpu_copy_stride, trans->base.b.box.width,
                                              trans->base.b.box.height);
       util_format_z24_unorm_s8_uint_unpack_s_8uint(stencil_ptr, trans->base.b.stride, (uint8_t*)trans->data,
-                                                   trans->base.b.stride, trans->base.b.box.width,
+                                                   trans->zs_cpu_copy_stride, trans->base.b.box.width,
                                                    trans->base.b.box.height);
       break;
    case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
+      if (screen->opts2.ProgrammableSamplePositionsTier == D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED) {
+         depth_ptr += trans->base.b.box.y * trans->base.b.stride + trans->base.b.box.x * 4;
+         stencil_ptr += trans->base.b.box.y * trans->base.b.stride + trans->base.b.box.x;
+      }
       util_format_z32_float_s8x24_uint_unpack_z_float((float *)depth_ptr, trans->base.b.stride, (uint8_t*)trans->data,
-                                                      trans->base.b.stride, trans->base.b.box.width,
+                                                      trans->zs_cpu_copy_stride, trans->base.b.box.width,
                                                       trans->base.b.box.height);
       util_format_z32_float_s8x24_uint_unpack_s_8uint(stencil_ptr, trans->base.b.stride, (uint8_t*)trans->data,
-                                                      trans->base.b.stride, trans->base.b.box.width,
+                                                      trans->zs_cpu_copy_stride, trans->base.b.box.width,
                                                       trans->base.b.box.height);
       break;
    default:
@@ -1063,6 +1118,7 @@ d3d12_transfer_map(struct pipe_context *pctx,
 {
    struct d3d12_context *ctx = d3d12_context(pctx);
    struct d3d12_resource *res = d3d12_resource(pres);
+   struct d3d12_screen *screen = d3d12_screen(pres->screen);
 
    if (usage & PIPE_MAP_DIRECTLY || !res->bo)
       return NULL;
@@ -1121,6 +1177,21 @@ d3d12_transfer_map(struct pipe_context *pctx,
          ptrans->layer_stride = align(ptrans->layer_stride,
                                       D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);
 
+      if (util_format_has_depth(util_format_description(pres->format)) &&
+          screen->opts2.ProgrammableSamplePositionsTier == D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED) {
+         trans->zs_cpu_copy_stride = ptrans->stride;
+         trans->zs_cpu_copy_layer_stride = ptrans->layer_stride;
+         
+         ptrans->stride = align(util_format_get_stride(pres->format, pres->width0),
+                                D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
+         ptrans->layer_stride = util_format_get_2d_size(pres->format,
+                                                        ptrans->stride,
+                                                        pres->height0);
+
+         range.Begin = box->y * ptrans->stride +
+            box->x * util_format_get_blocksize(pres->format);
+      }
+
       unsigned staging_res_size = ptrans->layer_stride * box->depth;
       if (res->base.b.target == PIPE_BUFFER) {
          /* To properly support ARB_map_buffer_alignment, we need to return a pointer
diff --git a/src/gallium/drivers/d3d12/d3d12_resource.h b/src/gallium/drivers/d3d12/d3d12_resource.h
index 57f5a0f08b0..97586f880ed 100644
--- a/src/gallium/drivers/d3d12/d3d12_resource.h
+++ b/src/gallium/drivers/d3d12/d3d12_resource.h
@@ -54,6 +54,8 @@ struct d3d12_transfer {
    struct threaded_transfer base;
    struct pipe_resource *staging_res;
    void *data;
+   unsigned zs_cpu_copy_stride;
+   unsigned zs_cpu_copy_layer_stride;
 };
 
 static inline struct d3d12_resource *



More information about the mesa-commit mailing list