From fde36d79920dee4c0ec399d44b4071d6b3f5b8c1 Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Wed, 3 Nov 2021 17:05:05 -0700 Subject: [PATCH] d3d12: Don't wait for GPU reads to do CPU reads Reviewed By: Bill Kristiansen Part-of: --- src/gallium/drivers/d3d12/d3d12_batch.cpp | 38 +++++++++++++++++++--------- src/gallium/drivers/d3d12/d3d12_batch.h | 9 ++++--- src/gallium/drivers/d3d12/d3d12_blit.cpp | 12 ++++----- src/gallium/drivers/d3d12/d3d12_context.cpp | 2 +- src/gallium/drivers/d3d12/d3d12_draw.cpp | 10 ++++---- src/gallium/drivers/d3d12/d3d12_query.cpp | 2 +- src/gallium/drivers/d3d12/d3d12_resource.cpp | 26 ++++++++++--------- src/gallium/drivers/d3d12/d3d12_resource.h | 3 ++- 8 files changed, 61 insertions(+), 41 deletions(-) diff --git a/src/gallium/drivers/d3d12/d3d12_batch.cpp b/src/gallium/drivers/d3d12/d3d12_batch.cpp index d9bd318..d45ba6e 100644 --- a/src/gallium/drivers/d3d12/d3d12_batch.cpp +++ b/src/gallium/drivers/d3d12/d3d12_batch.cpp @@ -40,8 +40,8 @@ d3d12_init_batch(struct d3d12_context *ctx, struct d3d12_batch *batch) { struct d3d12_screen *screen = d3d12_screen(ctx->base.screen); - batch->bos = _mesa_set_create(NULL, _mesa_hash_pointer, - _mesa_key_pointer_equal); + batch->bos = _mesa_hash_table_create(NULL, _mesa_hash_pointer, + _mesa_key_pointer_equal); batch->sampler_views = _mesa_set_create(NULL, _mesa_hash_pointer, _mesa_key_pointer_equal); batch->surfaces = _mesa_set_create(NULL, _mesa_hash_pointer, @@ -79,7 +79,7 @@ d3d12_init_batch(struct d3d12_context *ctx, struct d3d12_batch *batch) } static void -delete_bo(set_entry *entry) +delete_bo(hash_entry *entry) { struct d3d12_bo *bo = (struct d3d12_bo *)entry->key; d3d12_bo_unreference(bo); @@ -119,7 +119,7 @@ d3d12_reset_batch(struct d3d12_context *ctx, struct d3d12_batch *batch, uint64_t d3d12_fence_reference(&batch->fence, NULL); } - _mesa_set_clear(batch->bos, delete_bo); + _mesa_hash_table_clear(batch->bos, delete_bo); _mesa_set_clear(batch->sampler_views, delete_sampler_view); _mesa_set_clear(batch->surfaces, delete_surface); _mesa_set_clear(batch->objects, delete_object); @@ -146,7 +146,7 @@ d3d12_destroy_batch(struct d3d12_context *ctx, struct d3d12_batch *batch) batch->cmdalloc->Release(); d3d12_descriptor_heap_free(batch->sampler_heap); d3d12_descriptor_heap_free(batch->view_heap); - _mesa_set_destroy(batch->bos, NULL); + _mesa_hash_table_destroy(batch->bos, NULL); _mesa_set_destroy(batch->sampler_views, NULL); _mesa_set_destroy(batch->surfaces, NULL); _mesa_set_destroy(batch->objects, NULL); @@ -207,21 +207,35 @@ d3d12_end_batch(struct d3d12_context *ctx, struct d3d12_batch *batch) batch->fence = d3d12_create_fence(screen, ctx); } +enum batch_bo_reference_state +{ + batch_bo_reference_read = (1 << 0), + batch_bo_reference_written = (1 << 1), +}; + bool d3d12_batch_has_references(struct d3d12_batch *batch, - struct d3d12_bo *bo) + struct d3d12_bo *bo, + bool want_to_write) { - return (_mesa_set_search(batch->bos, bo) != NULL); + hash_entry *entry = _mesa_hash_table_search(batch->bos, bo); + if (entry == NULL) + return false; + bool resource_was_written = ((batch_bo_reference_state)(size_t)entry->data & batch_bo_reference_written) != 0; + return want_to_write || resource_was_written; } void d3d12_batch_reference_resource(struct d3d12_batch *batch, - struct d3d12_resource *res) + struct d3d12_resource *res, + bool write) { - bool found = false; - _mesa_set_search_and_add(batch->bos, res->bo, &found); - if (!found) + hash_entry *entry = _mesa_hash_table_insert(batch->bos, res->bo, NULL); + if (entry->data == NULL) d3d12_bo_reference(res->bo); + size_t new_data = write ? batch_bo_reference_written : batch_bo_reference_read; + size_t old_data = (size_t)entry->data; + entry->data = (void*)(old_data | new_data); } void @@ -239,7 +253,7 @@ void d3d12_batch_reference_surface_texture(struct d3d12_batch *batch, struct d3d12_surface *surf) { - d3d12_batch_reference_resource(batch, d3d12_resource(surf->base.texture)); + d3d12_batch_reference_resource(batch, d3d12_resource(surf->base.texture), true); } void diff --git a/src/gallium/drivers/d3d12/d3d12_batch.h b/src/gallium/drivers/d3d12/d3d12_batch.h index 05039eb..f49fe61 100644 --- a/src/gallium/drivers/d3d12/d3d12_batch.h +++ b/src/gallium/drivers/d3d12/d3d12_batch.h @@ -25,6 +25,7 @@ #define D3D12_BATCH_H #include "util/u_dynarray.h" +#include "util/hash_table.h" #include #ifndef _WIN32 @@ -41,7 +42,7 @@ struct d3d12_fence; struct d3d12_batch { struct d3d12_fence *fence; - struct set *bos; + struct hash_table *bos; struct set *sampler_views; struct set *surfaces; struct set *objects; @@ -71,11 +72,13 @@ d3d12_reset_batch(struct d3d12_context *ctx, struct d3d12_batch *batch, uint64_t bool d3d12_batch_has_references(struct d3d12_batch *batch, - struct d3d12_bo *bo); + struct d3d12_bo *bo, + bool want_to_write); void d3d12_batch_reference_resource(struct d3d12_batch *batch, - struct d3d12_resource *res); + struct d3d12_resource *res, + bool write); void d3d12_batch_reference_sampler_view(struct d3d12_batch *batch, diff --git a/src/gallium/drivers/d3d12/d3d12_blit.cpp b/src/gallium/drivers/d3d12/d3d12_blit.cpp index ad54e34..55a741a 100644 --- a/src/gallium/drivers/d3d12/d3d12_blit.cpp +++ b/src/gallium/drivers/d3d12/d3d12_blit.cpp @@ -123,8 +123,8 @@ blit_resolve(struct d3d12_context *ctx, const struct pipe_blit_info *info) d3d12_apply_resource_states(ctx); - d3d12_batch_reference_resource(batch, src); - d3d12_batch_reference_resource(batch, dst); + d3d12_batch_reference_resource(batch, src, false); + d3d12_batch_reference_resource(batch, dst, true); DXGI_FORMAT dxgi_format = d3d12_get_resource_srv_format(src->base.b.format, src->base.b.target); @@ -434,8 +434,8 @@ d3d12_direct_copy(struct d3d12_context *ctx, d3d12_apply_resource_states(ctx); - d3d12_batch_reference_resource(batch, src); - d3d12_batch_reference_resource(batch, dst); + d3d12_batch_reference_resource(batch, src, false); + d3d12_batch_reference_resource(batch, dst, true); if (src->base.b.target == PIPE_BUFFER) { copy_buffer_region_no_barriers(ctx, dst, pdst_box->x, @@ -827,8 +827,8 @@ blit_resolve_stencil(struct d3d12_context *ctx, d3d12_apply_resource_states(ctx); struct d3d12_batch *batch = d3d12_current_batch(ctx); - d3d12_batch_reference_resource(batch, d3d12_resource(tmp)); - d3d12_batch_reference_resource(batch, dst); + d3d12_batch_reference_resource(batch, d3d12_resource(tmp), false); + d3d12_batch_reference_resource(batch, dst, true); D3D12_BOX src_box; src_box.left = src_box.top = src_box.front = 0; diff --git a/src/gallium/drivers/d3d12/d3d12_context.cpp b/src/gallium/drivers/d3d12/d3d12_context.cpp index 53a0d4b..d09315a 100644 --- a/src/gallium/drivers/d3d12/d3d12_context.cpp +++ b/src/gallium/drivers/d3d12/d3d12_context.cpp @@ -1493,7 +1493,7 @@ d3d12_enable_fake_so_buffers(struct d3d12_context *ctx, unsigned factor) pipe_reference_init(&fake_target->base.reference, 1); fake_target->base.context = &ctx->base; - d3d12_resource_wait_idle(ctx, d3d12_resource(target->base.buffer)); + d3d12_resource_wait_idle(ctx, d3d12_resource(target->base.buffer), false); /* Check if another target is using the same buffer */ for (unsigned j = 0; j < i; ++j) { diff --git a/src/gallium/drivers/d3d12/d3d12_draw.cpp b/src/gallium/drivers/d3d12/d3d12_draw.cpp index a7512f5..77372b7 100644 --- a/src/gallium/drivers/d3d12/d3d12_draw.cpp +++ b/src/gallium/drivers/d3d12/d3d12_draw.cpp @@ -67,7 +67,7 @@ fill_cbv_descriptors(struct d3d12_context *ctx, cbv_desc.BufferLocation = d3d12_resource_gpu_virtual_address(res) + buffer->buffer_offset; cbv_desc.SizeInBytes = MIN2(D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 16, align(buffer->buffer_size, 256)); - d3d12_batch_reference_resource(batch, res); + d3d12_batch_reference_resource(batch, res, false); } struct d3d12_descriptor_handle handle; @@ -654,7 +654,7 @@ d3d12_draw_vbo(struct pipe_context *pctx, struct d3d12_resource *res = d3d12_resource(ctx->vbs[i].buffer.resource); d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, D3D12_BIND_INVALIDATE_NONE); if (ctx->cmdlist_dirty & D3D12_DIRTY_VERTEX_BUFFERS) - d3d12_batch_reference_resource(batch, res); + d3d12_batch_reference_resource(batch, res, false); } } if (ctx->cmdlist_dirty & D3D12_DIRTY_VERTEX_BUFFERS) @@ -670,7 +670,7 @@ d3d12_draw_vbo(struct pipe_context *pctx, if (ctx->cmdlist_dirty & D3D12_DIRTY_INDEX_BUFFER || memcmp(&ctx->ibv, &ibv, sizeof(D3D12_INDEX_BUFFER_VIEW)) != 0) { ctx->ibv = ibv; - d3d12_batch_reference_resource(batch, res); + d3d12_batch_reference_resource(batch, res, false); ctx->cmdlist->IASetIndexBuffer(&ibv); } @@ -714,8 +714,8 @@ d3d12_draw_vbo(struct pipe_context *pctx, d3d12_resource_make_writeable(pctx, target->base.buffer); if (ctx->cmdlist_dirty & D3D12_DIRTY_STREAM_OUTPUT) { - d3d12_batch_reference_resource(batch, so_buffer); - d3d12_batch_reference_resource(batch, fill_buffer); + d3d12_batch_reference_resource(batch, so_buffer, true); + d3d12_batch_reference_resource(batch, fill_buffer, true); } d3d12_transition_resource_state(ctx, so_buffer, D3D12_RESOURCE_STATE_STREAM_OUT, D3D12_BIND_INVALIDATE_NONE); diff --git a/src/gallium/drivers/d3d12/d3d12_query.cpp b/src/gallium/drivers/d3d12/d3d12_query.cpp index 29d66bd..5b279d8 100644 --- a/src/gallium/drivers/d3d12/d3d12_query.cpp +++ b/src/gallium/drivers/d3d12/d3d12_query.cpp @@ -382,7 +382,7 @@ end_query(struct d3d12_context *ctx, struct d3d12_query *q) resolve_count, d3d12_res, offset); d3d12_batch_reference_object(batch, q->query_heap); - d3d12_batch_reference_resource(batch, res); + d3d12_batch_reference_resource(batch, res, true); assert(q->curr_query < q->num_queries); q->curr_query++; diff --git a/src/gallium/drivers/d3d12/d3d12_resource.cpp b/src/gallium/drivers/d3d12/d3d12_resource.cpp index 4246001..dc32a18 100644 --- a/src/gallium/drivers/d3d12/d3d12_resource.cpp +++ b/src/gallium/drivers/d3d12/d3d12_resource.cpp @@ -72,27 +72,29 @@ d3d12_resource_destroy(struct pipe_screen *pscreen, static bool resource_is_busy(struct d3d12_context *ctx, - struct d3d12_resource *res) + struct d3d12_resource *res, + bool want_to_write) { bool busy = false; for (unsigned i = 0; i < ARRAY_SIZE(ctx->batches); i++) - busy |= d3d12_batch_has_references(&ctx->batches[i], res->bo); + busy |= d3d12_batch_has_references(&ctx->batches[i], res->bo, want_to_write); return busy; } void d3d12_resource_wait_idle(struct d3d12_context *ctx, - struct d3d12_resource *res) + struct d3d12_resource *res, + bool want_to_write) { - if (d3d12_batch_has_references(d3d12_current_batch(ctx), res->bo)) { + if (d3d12_batch_has_references(d3d12_current_batch(ctx), res->bo, want_to_write)) { d3d12_flush_cmdlist_and_wait(ctx); } else { d3d12_foreach_submitted_batch(ctx, batch) { - if (d3d12_batch_has_references(batch, res->bo)) { + if (d3d12_batch_has_references(batch, res->bo, want_to_write)) { d3d12_reset_batch(ctx, batch, PIPE_TIMEOUT_INFINITE); - if (!resource_is_busy(ctx, res)) + if (!resource_is_busy(ctx, res, want_to_write)) break; } } @@ -418,8 +420,8 @@ copy_texture_region(struct d3d12_context *ctx, { auto batch = d3d12_current_batch(ctx); - d3d12_batch_reference_resource(batch, info.src); - d3d12_batch_reference_resource(batch, info.dst); + d3d12_batch_reference_resource(batch, info.src, false); + d3d12_batch_reference_resource(batch, info.dst, true); d3d12_transition_resource_state(ctx, info.src, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_BIND_INVALIDATE_FULL); d3d12_transition_resource_state(ctx, info.dst, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_BIND_INVALIDATE_FULL); d3d12_apply_resource_states(ctx); @@ -587,8 +589,8 @@ transfer_buf_to_buf(struct d3d12_context *ctx, { auto batch = d3d12_current_batch(ctx); - d3d12_batch_reference_resource(batch, src); - d3d12_batch_reference_resource(batch, dst); + d3d12_batch_reference_resource(batch, src, false); + d3d12_batch_reference_resource(batch, dst, true); uint64_t src_offset_suballoc = 0; uint64_t dst_offset_suballoc = 0; @@ -645,11 +647,11 @@ synchronize(struct d3d12_context *ctx, usage |= PIPE_MAP_UNSYNCHRONIZED; } - if (!(usage & PIPE_MAP_UNSYNCHRONIZED) && resource_is_busy(ctx, res)) { + if (!(usage & PIPE_MAP_UNSYNCHRONIZED) && resource_is_busy(ctx, res, usage & PIPE_MAP_WRITE)) { if (usage & PIPE_MAP_DONTBLOCK) return false; - d3d12_resource_wait_idle(ctx, res); + d3d12_resource_wait_idle(ctx, res, usage & PIPE_MAP_WRITE); } if (usage & PIPE_MAP_WRITE) diff --git a/src/gallium/drivers/d3d12/d3d12_resource.h b/src/gallium/drivers/d3d12/d3d12_resource.h index a6df8be..57f5a0f 100644 --- a/src/gallium/drivers/d3d12/d3d12_resource.h +++ b/src/gallium/drivers/d3d12/d3d12_resource.h @@ -112,7 +112,8 @@ d3d12_resource_release(struct d3d12_resource *res); void d3d12_resource_wait_idle(struct d3d12_context *ctx, - struct d3d12_resource *res); + struct d3d12_resource *res, + bool want_to_write); void d3d12_resource_make_writeable(struct pipe_context *pctx, -- 2.7.4