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