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);
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

View File

@@ -25,6 +25,7 @@
#define D3D12_BATCH_H
#include "util/u_dynarray.h"
#include "util/hash_table.h"
#include <stdint.h>
#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,

View File

@@ -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;

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);
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) {

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.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);

View File

@@ -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++;

View File

@@ -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)

View File

@@ -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,