d3d12: Handle THREAD_SAFE maps and use them for async query results
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41061>
This commit is contained in:
Jesse Natalie 2026-04-20 08:51:12 -07:00 committed by Marge Bot
parent c8ae72f51d
commit 7adfea17e3
2 changed files with 31 additions and 7 deletions

View file

@ -203,7 +203,11 @@ accumulate_subresult_cpu(struct d3d12_context *ctx, struct d3d12_query *q_parent
unsigned access = PIPE_MAP_READ;
void *results;
access |= PIPE_MAP_UNSYNCHRONIZED;
/* When called from tc_get_query_result on the app thread (flushed query),
* the driver thread may be running concurrently. Use PIPE_MAP_THREAD_SAFE
* to avoid slab allocator races on transfer_pool.
*/
access |= PIPE_MAP_UNSYNCHRONIZED | PIPE_MAP_THREAD_SAFE;
results = pipe_buffer_map_range(&ctx->base, q->buffer, q->buffer_offset,
q->num_queries * q->query_size,

View file

@ -1782,9 +1782,15 @@ d3d12_transfer_map(struct pipe_context *pctx,
if (usage & PIPE_MAP_DIRECTLY || !res->bo)
return NULL;
slab_child_pool* transfer_pool = (usage & TC_TRANSFER_MAP_THREADED_UNSYNC) ?
&ctx->transfer_pool_unsync : &ctx->transfer_pool;
struct d3d12_transfer *trans = (struct d3d12_transfer *)slab_zalloc(transfer_pool);
slab_child_pool* transfer_pool = NULL;
struct d3d12_transfer *trans;
if (usage & PIPE_MAP_THREAD_SAFE) {
trans = (struct d3d12_transfer *)CALLOC_STRUCT(d3d12_transfer);
} else {
transfer_pool = (usage & TC_TRANSFER_MAP_THREADED_UNSYNC) ?
&ctx->transfer_pool_unsync : &ctx->transfer_pool;
trans = (struct d3d12_transfer *)slab_zalloc(transfer_pool);
}
struct pipe_transfer *ptrans = &trans->base.b;
if (!trans)
return NULL;
@ -1810,7 +1816,10 @@ d3d12_transfer_map(struct pipe_context *pctx,
range = linear_range(box, ptrans->stride, ptrans->layer_stride);
if (!synchronize(ctx, res, usage, &range)) {
slab_free(transfer_pool, trans);
if (usage & PIPE_MAP_THREAD_SAFE)
FREE(trans);
else
slab_free(transfer_pool, trans);
return NULL;
}
ptr = d3d12_bo_map(res->bo, &range);
@ -1934,7 +1943,10 @@ d3d12_transfer_map(struct pipe_context *pctx,
staging_usage,
staging_res_size);
if (!trans->staging_res) {
slab_free(transfer_pool, trans);
if (usage & PIPE_MAP_THREAD_SAFE)
FREE(trans);
else
slab_free(transfer_pool, trans);
return NULL;
}
@ -2062,7 +2074,15 @@ d3d12_transfer_unmap(struct pipe_context *pctx,
}
pipe_resource_reference(&ptrans->resource, NULL);
slab_free(&d3d12_context(pctx)->transfer_pool, ptrans);
if (ptrans->usage & PIPE_MAP_THREAD_SAFE) {
FREE(ptrans);
} else {
/* transfer_unmap is always called from the driver thread, so we use
* transfer_pool, not transfer_pool_unsync. Freeing an object into a
* different pool is allowed, however.
*/
slab_free(&d3d12_context(pctx)->transfer_pool, ptrans);
}
}
void