mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-25 02:40:46 +02:00
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@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8095>
This commit is contained in:
parent
4d83306a9a
commit
47125bce8b
1 changed files with 64 additions and 8 deletions
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue