d3d12: Don't wait for GPU reads to do CPU reads

Reviewed By: Bill Kristiansen <billkris@microsoft.com>

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13669>
This commit is contained in:
Jesse Natalie
2021-11-03 17:05:05 -07:00
committed by Marge Bot
parent 8ea1e58f0e
commit fde36d7992
8 changed files with 61 additions and 41 deletions

View File

@@ -40,8 +40,8 @@ d3d12_init_batch(struct d3d12_context *ctx, struct d3d12_batch *batch)
{ {
struct d3d12_screen *screen = d3d12_screen(ctx->base.screen); struct d3d12_screen *screen = d3d12_screen(ctx->base.screen);
batch->bos = _mesa_set_create(NULL, _mesa_hash_pointer, batch->bos = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
_mesa_key_pointer_equal); _mesa_key_pointer_equal);
batch->sampler_views = _mesa_set_create(NULL, _mesa_hash_pointer, batch->sampler_views = _mesa_set_create(NULL, _mesa_hash_pointer,
_mesa_key_pointer_equal); _mesa_key_pointer_equal);
batch->surfaces = _mesa_set_create(NULL, _mesa_hash_pointer, 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 static void
delete_bo(set_entry *entry) delete_bo(hash_entry *entry)
{ {
struct d3d12_bo *bo = (struct d3d12_bo *)entry->key; struct d3d12_bo *bo = (struct d3d12_bo *)entry->key;
d3d12_bo_unreference(bo); 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); 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->sampler_views, delete_sampler_view);
_mesa_set_clear(batch->surfaces, delete_surface); _mesa_set_clear(batch->surfaces, delete_surface);
_mesa_set_clear(batch->objects, delete_object); _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(); batch->cmdalloc->Release();
d3d12_descriptor_heap_free(batch->sampler_heap); d3d12_descriptor_heap_free(batch->sampler_heap);
d3d12_descriptor_heap_free(batch->view_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->sampler_views, NULL);
_mesa_set_destroy(batch->surfaces, NULL); _mesa_set_destroy(batch->surfaces, NULL);
_mesa_set_destroy(batch->objects, 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); 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 bool
d3d12_batch_has_references(struct d3d12_batch *batch, 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 void
d3d12_batch_reference_resource(struct d3d12_batch *batch, d3d12_batch_reference_resource(struct d3d12_batch *batch,
struct d3d12_resource *res) struct d3d12_resource *res,
bool write)
{ {
bool found = false; hash_entry *entry = _mesa_hash_table_insert(batch->bos, res->bo, NULL);
_mesa_set_search_and_add(batch->bos, res->bo, &found); if (entry->data == NULL)
if (!found)
d3d12_bo_reference(res->bo); 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 void
@@ -239,7 +253,7 @@ void
d3d12_batch_reference_surface_texture(struct d3d12_batch *batch, d3d12_batch_reference_surface_texture(struct d3d12_batch *batch,
struct d3d12_surface *surf) 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 void

View File

@@ -25,6 +25,7 @@
#define D3D12_BATCH_H #define D3D12_BATCH_H
#include "util/u_dynarray.h" #include "util/u_dynarray.h"
#include "util/hash_table.h"
#include <stdint.h> #include <stdint.h>
#ifndef _WIN32 #ifndef _WIN32
@@ -41,7 +42,7 @@ struct d3d12_fence;
struct d3d12_batch { struct d3d12_batch {
struct d3d12_fence *fence; struct d3d12_fence *fence;
struct set *bos; struct hash_table *bos;
struct set *sampler_views; struct set *sampler_views;
struct set *surfaces; struct set *surfaces;
struct set *objects; struct set *objects;
@@ -71,11 +72,13 @@ d3d12_reset_batch(struct d3d12_context *ctx, struct d3d12_batch *batch, uint64_t
bool bool
d3d12_batch_has_references(struct d3d12_batch *batch, d3d12_batch_has_references(struct d3d12_batch *batch,
struct d3d12_bo *bo); struct d3d12_bo *bo,
bool want_to_write);
void void
d3d12_batch_reference_resource(struct d3d12_batch *batch, d3d12_batch_reference_resource(struct d3d12_batch *batch,
struct d3d12_resource *res); struct d3d12_resource *res,
bool write);
void void
d3d12_batch_reference_sampler_view(struct d3d12_batch *batch, d3d12_batch_reference_sampler_view(struct d3d12_batch *batch,

View File

@@ -123,8 +123,8 @@ blit_resolve(struct d3d12_context *ctx, const struct pipe_blit_info *info)
d3d12_apply_resource_states(ctx); d3d12_apply_resource_states(ctx);
d3d12_batch_reference_resource(batch, src); d3d12_batch_reference_resource(batch, src, false);
d3d12_batch_reference_resource(batch, dst); d3d12_batch_reference_resource(batch, dst, true);
DXGI_FORMAT dxgi_format = d3d12_get_resource_srv_format(src->base.b.format, src->base.b.target); 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_apply_resource_states(ctx);
d3d12_batch_reference_resource(batch, src); d3d12_batch_reference_resource(batch, src, false);
d3d12_batch_reference_resource(batch, dst); d3d12_batch_reference_resource(batch, dst, true);
if (src->base.b.target == PIPE_BUFFER) { if (src->base.b.target == PIPE_BUFFER) {
copy_buffer_region_no_barriers(ctx, dst, pdst_box->x, 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); d3d12_apply_resource_states(ctx);
struct d3d12_batch *batch = d3d12_current_batch(ctx); struct d3d12_batch *batch = d3d12_current_batch(ctx);
d3d12_batch_reference_resource(batch, d3d12_resource(tmp)); d3d12_batch_reference_resource(batch, d3d12_resource(tmp), false);
d3d12_batch_reference_resource(batch, dst); d3d12_batch_reference_resource(batch, dst, true);
D3D12_BOX src_box; D3D12_BOX src_box;
src_box.left = src_box.top = src_box.front = 0; src_box.left = src_box.top = src_box.front = 0;

View File

@@ -1493,7 +1493,7 @@ d3d12_enable_fake_so_buffers(struct d3d12_context *ctx, unsigned factor)
pipe_reference_init(&fake_target->base.reference, 1); pipe_reference_init(&fake_target->base.reference, 1);
fake_target->base.context = &ctx->base; 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 */ /* Check if another target is using the same buffer */
for (unsigned j = 0; j < i; ++j) { for (unsigned j = 0; j < i; ++j) {

View File

@@ -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.BufferLocation = d3d12_resource_gpu_virtual_address(res) + buffer->buffer_offset;
cbv_desc.SizeInBytes = MIN2(D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 16, cbv_desc.SizeInBytes = MIN2(D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 16,
align(buffer->buffer_size, 256)); align(buffer->buffer_size, 256));
d3d12_batch_reference_resource(batch, res); d3d12_batch_reference_resource(batch, res, false);
} }
struct d3d12_descriptor_handle handle; 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); 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); 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) 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) 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 || if (ctx->cmdlist_dirty & D3D12_DIRTY_INDEX_BUFFER ||
memcmp(&ctx->ibv, &ibv, sizeof(D3D12_INDEX_BUFFER_VIEW)) != 0) { memcmp(&ctx->ibv, &ibv, sizeof(D3D12_INDEX_BUFFER_VIEW)) != 0) {
ctx->ibv = ibv; ctx->ibv = ibv;
d3d12_batch_reference_resource(batch, res); d3d12_batch_reference_resource(batch, res, false);
ctx->cmdlist->IASetIndexBuffer(&ibv); ctx->cmdlist->IASetIndexBuffer(&ibv);
} }
@@ -714,8 +714,8 @@ d3d12_draw_vbo(struct pipe_context *pctx,
d3d12_resource_make_writeable(pctx, target->base.buffer); d3d12_resource_make_writeable(pctx, target->base.buffer);
if (ctx->cmdlist_dirty & D3D12_DIRTY_STREAM_OUTPUT) { if (ctx->cmdlist_dirty & D3D12_DIRTY_STREAM_OUTPUT) {
d3d12_batch_reference_resource(batch, so_buffer); d3d12_batch_reference_resource(batch, so_buffer, true);
d3d12_batch_reference_resource(batch, fill_buffer); d3d12_batch_reference_resource(batch, fill_buffer, true);
} }
d3d12_transition_resource_state(ctx, so_buffer, D3D12_RESOURCE_STATE_STREAM_OUT, D3D12_BIND_INVALIDATE_NONE); d3d12_transition_resource_state(ctx, so_buffer, D3D12_RESOURCE_STATE_STREAM_OUT, D3D12_BIND_INVALIDATE_NONE);

View File

@@ -382,7 +382,7 @@ end_query(struct d3d12_context *ctx, struct d3d12_query *q)
resolve_count, d3d12_res, offset); resolve_count, d3d12_res, offset);
d3d12_batch_reference_object(batch, q->query_heap); 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); assert(q->curr_query < q->num_queries);
q->curr_query++; q->curr_query++;

View File

@@ -72,27 +72,29 @@ d3d12_resource_destroy(struct pipe_screen *pscreen,
static bool static bool
resource_is_busy(struct d3d12_context *ctx, resource_is_busy(struct d3d12_context *ctx,
struct d3d12_resource *res) struct d3d12_resource *res,
bool want_to_write)
{ {
bool busy = false; bool busy = false;
for (unsigned i = 0; i < ARRAY_SIZE(ctx->batches); i++) 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; return busy;
} }
void void
d3d12_resource_wait_idle(struct d3d12_context *ctx, 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); d3d12_flush_cmdlist_and_wait(ctx);
} else { } else {
d3d12_foreach_submitted_batch(ctx, batch) { 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); d3d12_reset_batch(ctx, batch, PIPE_TIMEOUT_INFINITE);
if (!resource_is_busy(ctx, res)) if (!resource_is_busy(ctx, res, want_to_write))
break; break;
} }
} }
@@ -418,8 +420,8 @@ copy_texture_region(struct d3d12_context *ctx,
{ {
auto batch = d3d12_current_batch(ctx); auto batch = d3d12_current_batch(ctx);
d3d12_batch_reference_resource(batch, info.src); d3d12_batch_reference_resource(batch, info.src, false);
d3d12_batch_reference_resource(batch, info.dst); 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.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_transition_resource_state(ctx, info.dst, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_BIND_INVALIDATE_FULL);
d3d12_apply_resource_states(ctx); d3d12_apply_resource_states(ctx);
@@ -587,8 +589,8 @@ transfer_buf_to_buf(struct d3d12_context *ctx,
{ {
auto batch = d3d12_current_batch(ctx); auto batch = d3d12_current_batch(ctx);
d3d12_batch_reference_resource(batch, src); d3d12_batch_reference_resource(batch, src, false);
d3d12_batch_reference_resource(batch, dst); d3d12_batch_reference_resource(batch, dst, true);
uint64_t src_offset_suballoc = 0; uint64_t src_offset_suballoc = 0;
uint64_t dst_offset_suballoc = 0; uint64_t dst_offset_suballoc = 0;
@@ -645,11 +647,11 @@ synchronize(struct d3d12_context *ctx,
usage |= PIPE_MAP_UNSYNCHRONIZED; 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) if (usage & PIPE_MAP_DONTBLOCK)
return false; return false;
d3d12_resource_wait_idle(ctx, res); d3d12_resource_wait_idle(ctx, res, usage & PIPE_MAP_WRITE);
} }
if (usage & PIPE_MAP_WRITE) if (usage & PIPE_MAP_WRITE)

View File

@@ -112,7 +112,8 @@ d3d12_resource_release(struct d3d12_resource *res);
void void
d3d12_resource_wait_idle(struct d3d12_context *ctx, d3d12_resource_wait_idle(struct d3d12_context *ctx,
struct d3d12_resource *res); struct d3d12_resource *res,
bool want_to_write);
void void
d3d12_resource_make_writeable(struct pipe_context *pctx, d3d12_resource_make_writeable(struct pipe_context *pctx,