Module: Mesa Branch: master Commit: 47125bce8ba5a978fdc1dab6f78341d9933f6232 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=47125bce8ba5a978fdc1dab6f78341d9933f6232
Author: Jesse Natalie <[email protected]> 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 <[email protected]> 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); _______________________________________________ mesa-commit mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/mesa-commit
