Mesa (master): d3d12: Add a path for mapping of not-directly-mappable buffers

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Jan 5 23:03:11 UTC 2021


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

Author: Jesse Natalie <jenatali at microsoft.com>
Date:   Mon Dec 14 11:42:49 2020 -0800

d3d12: Add a path for mapping of not-directly-mappable buffers

Currently all buffers are allocated as mappable, but a future
commit will change that so that some buffers can be allocated
directly in non-CPU-accessible memory for improved performance.

Note that the returned pointer must be appropriately offset from
a 64-byte-aligned base pointer, so if offsets are used, the data
will be read/written to an offset region in the staging buffer.

Reviewed-by: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8095>

---

 src/gallium/drivers/d3d12/d3d12_resource.cpp | 72 ++++++++++++++++++++++++----
 1 file changed, 64 insertions(+), 8 deletions(-)

diff --git a/src/gallium/drivers/d3d12/d3d12_resource.cpp b/src/gallium/drivers/d3d12/d3d12_resource.cpp
index 852b395206d..7ec82ab438e 100644
--- a/src/gallium/drivers/d3d12/d3d12_resource.cpp
+++ b/src/gallium/drivers/d3d12/d3d12_resource.cpp
@@ -567,6 +567,36 @@ transfer_image_to_buf(struct d3d12_context *ctx,
    return true;
 }
 
+static void
+transfer_buf_to_buf(struct d3d12_context *ctx,
+                    struct d3d12_resource *src,
+                    struct d3d12_resource *dst,
+                    uint64_t src_offset,
+                    uint64_t dst_offset,
+                    uint64_t width)
+{
+   auto batch = d3d12_current_batch(ctx);
+
+   d3d12_batch_reference_resource(batch, src);
+   d3d12_batch_reference_resource(batch, dst);
+
+   uint64_t src_offset_suballoc = 0;
+   uint64_t dst_offset_suballoc = 0;
+   auto src_d3d12 = d3d12_resource_underlying(src, &src_offset_suballoc);
+   auto dst_d3d12 = d3d12_resource_underlying(dst, &dst_offset_suballoc);
+   src_offset += src_offset_suballoc;
+   dst_offset += dst_offset_suballoc;
+
+   // Same-resource copies not supported, since the resource would need to be in both states
+   assert(src_d3d12 != dst_d3d12);
+   d3d12_transition_resource_state(ctx, src, D3D12_RESOURCE_STATE_COPY_SOURCE);
+   d3d12_transition_resource_state(ctx, dst, D3D12_RESOURCE_STATE_COPY_DEST);
+   d3d12_apply_resource_states(ctx);
+   ctx->cmdlist->CopyBufferRegion(dst_d3d12, dst_offset,
+                                  src_d3d12, src_offset,
+                                  width);
+}
+
 static unsigned
 linear_offset(int x, int y, int z, unsigned stride, unsigned layer_stride)
 {
@@ -846,6 +876,8 @@ write_zs_surface(struct pipe_context *pctx, struct d3d12_resource *res,
    transfer_buf_to_image(d3d12_context(pctx), res, stencil_buffer, trans, 1);
 }
 
+#define BUFFER_MAP_ALIGNMENT 64
+
 static void *
 d3d12_transfer_map(struct pipe_context *pctx,
                    struct pipe_resource *pres,
@@ -912,23 +944,40 @@ d3d12_transfer_map(struct pipe_context *pctx,
          ptrans->layer_stride = align(ptrans->layer_stride,
                                       D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);
 
+      unsigned staging_res_size = ptrans->layer_stride * box->depth;
+      if (res->base.target == PIPE_BUFFER) {
+         /* To properly support ARB_map_buffer_alignment, we need to return a pointer
+          * that's appropriately offset from a 64-byte-aligned base address.
+          */
+         assert(box->x >= 0);
+         unsigned aligned_x = (unsigned)box->x % BUFFER_MAP_ALIGNMENT;
+         staging_res_size = align(box->width + aligned_x,
+                                  D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
+         range.Begin = aligned_x;
+      }
+
       trans->staging_res = pipe_buffer_create(pctx->screen, 0,
                                               PIPE_USAGE_STAGING,
-                                              ptrans->layer_stride * box->depth);
+                                              staging_res_size);
       if (!trans->staging_res)
          return NULL;
 
       struct d3d12_resource *staging_res = d3d12_resource(trans->staging_res);
 
       if (usage & PIPE_MAP_READ) {
-         bool ret = transfer_image_to_buf(ctx, res, staging_res, trans, 0);
-         if (ret == false)
+         bool ret = true;
+         if (pres->target == PIPE_BUFFER) {
+            uint64_t src_offset = box->x;
+            uint64_t dst_offset = src_offset % BUFFER_MAP_ALIGNMENT;
+            transfer_buf_to_buf(ctx, res, staging_res, src_offset, dst_offset, box->width);
+         } else
+            ret = transfer_image_to_buf(ctx, res, staging_res, trans, 0);
+         if (!ret)
             return NULL;
          d3d12_flush_cmdlist_and_wait(ctx);
       }
 
-      range.Begin = 0;
-      range.End = ptrans->layer_stride * box->depth;
+      range.End = staging_res_size - range.Begin;
 
       ptr = d3d12_bo_map(staging_res->bo, &range);
    }
@@ -953,14 +1002,21 @@ d3d12_transfer_unmap(struct pipe_context *pctx,
       struct d3d12_resource *staging_res = d3d12_resource(trans->staging_res);
 
       if (trans->base.usage & PIPE_MAP_WRITE) {
-         range.Begin = 0;
-         range.End = ptrans->layer_stride * ptrans->box.depth;
+         assert(ptrans->box.x >= 0);
+         range.Begin = res->base.target == PIPE_BUFFER ?
+            (unsigned)ptrans->box.x % BUFFER_MAP_ALIGNMENT : 0;
+         range.End = staging_res->base.width0 - range.Begin;
       }
       d3d12_bo_unmap(staging_res->bo, &range);
 
       if (trans->base.usage & PIPE_MAP_WRITE) {
          struct d3d12_context *ctx = d3d12_context(pctx);
-         transfer_buf_to_image(ctx, res, staging_res, trans, 0);
+         if (res->base.target == PIPE_BUFFER) {
+            uint64_t dst_offset = trans->base.box.x;
+            uint64_t src_offset = dst_offset % BUFFER_MAP_ALIGNMENT;
+            transfer_buf_to_buf(ctx, staging_res, res, src_offset, dst_offset, ptrans->box.width);
+         } else
+            transfer_buf_to_image(ctx, res, staging_res, trans, 0);
       }
 
       pipe_resource_reference(&trans->staging_res, NULL);



More information about the mesa-commit mailing list