diff --git a/src/gallium/drivers/d3d12/d3d12_batch.cpp b/src/gallium/drivers/d3d12/d3d12_batch.cpp index 99c5bbc4dab..900c3db5927 100644 --- a/src/gallium/drivers/d3d12/d3d12_batch.cpp +++ b/src/gallium/drivers/d3d12/d3d12_batch.cpp @@ -60,6 +60,7 @@ d3d12_init_batch(struct d3d12_context *ctx, struct d3d12_batch *batch) _mesa_key_pointer_equal); batch->local_bos = UTIL_DYNARRAY_INIT; + batch->local_bo_pending = UTIL_DYNARRAY_INIT; #ifdef HAVE_GALLIUM_D3D12_GRAPHICS batch->surfaces = _mesa_set_create(NULL, _mesa_hash_pointer, @@ -183,13 +184,17 @@ d3d12_reset_batch(struct d3d12_context *ctx, struct d3d12_batch *batch, uint64_t #endif // HAVE_GALLIUM_D3D12_GRAPHICS _mesa_set_clear(batch->objects, delete_object); - + util_dynarray_foreach(&batch->local_bos, d3d12_bo*, bo) { (*bo)->local_reference_mask[batch->ctx_id] &= ~(1 << batch->ctx_index); delete_bo(*bo); } util_dynarray_clear(&batch->local_bos); + util_dynarray_foreach(&batch->local_bo_pending, struct d3d12_pending_free_entry*, entry) + FREE(*entry); + util_dynarray_clear(&batch->local_bo_pending); + #ifdef HAVE_GALLIUM_D3D12_GRAPHICS if (d3d12_screen(ctx->base.screen)->max_feature_level >= D3D_FEATURE_LEVEL_11_0) { _mesa_hash_table_clear(batch->sampler_tables, delete_sampler_view_table); @@ -234,6 +239,7 @@ d3d12_destroy_batch(struct d3d12_context *ctx, struct d3d12_batch *batch) _mesa_set_destroy(batch->objects, NULL); util_dynarray_fini(&batch->local_bos); + util_dynarray_fini(&batch->local_bo_pending); } void @@ -320,6 +326,38 @@ d3d12_end_batch(struct d3d12_context *ctx, struct d3d12_batch *batch) batch->fence = d3d12_create_fence(screen, true); + if (batch->fence) { + unsigned n_local = util_dynarray_num_elements(&batch->local_bo_pending, + struct d3d12_pending_free_entry*); + bool all_ok = n_local > 0; + struct d3d12_pending_free_entry **entries = + (struct d3d12_pending_free_entry **)util_dynarray_begin(&batch->local_bo_pending); + for (unsigned i = 0; i < n_local; ++i) { + if (!entries[i]) { + all_ok = false; + break; + } + } + + if (all_ok) { + struct d3d12_bo **bos = + (struct d3d12_bo **)util_dynarray_begin(&batch->local_bos); + uint64_t fv = batch->fence->value; + + mtx_lock(&screen->pending_free_lock); + for (unsigned i = 0; i < n_local; ++i) { + entries[i]->fence_value = fv; + list_addtail(&entries[i]->link, &screen->pending_free_list); + } + mtx_unlock(&screen->pending_free_lock); + + for (unsigned i = 0; i < n_local; ++i) + bos[i]->local_reference_mask[batch->ctx_id] &= ~(1 << batch->ctx_index); + util_dynarray_clear(&batch->local_bos); + util_dynarray_clear(&batch->local_bo_pending); + } + } + #ifdef HAVE_GALLIUM_D3D12_GRAPHICS /* batch->queries is NULL when no grfx supported */ if (screen->max_feature_level >= D3D_FEATURE_LEVEL_11_0) { @@ -365,6 +403,10 @@ d3d12_batch_acquire_reference(struct d3d12_batch *batch, if ((bo->local_reference_mask[batch->ctx_id] & (1 << batch->ctx_index)) == 0) { d3d12_bo_reference(bo); util_dynarray_append(&batch->local_bos, bo); + struct d3d12_pending_free_entry *entry = MALLOC_STRUCT(d3d12_pending_free_entry); + if (entry) + entry->bo = bo; + util_dynarray_append(&batch->local_bo_pending, entry); bo->local_reference_mask[batch->ctx_id] |= (1 << batch->ctx_index); bo->local_reference_state[batch->ctx_id][batch->ctx_index] = batch_bo_reference_none; } diff --git a/src/gallium/drivers/d3d12/d3d12_batch.h b/src/gallium/drivers/d3d12/d3d12_batch.h index c0b8dcf0c1a..3b3723dc20e 100644 --- a/src/gallium/drivers/d3d12/d3d12_batch.h +++ b/src/gallium/drivers/d3d12/d3d12_batch.h @@ -47,6 +47,7 @@ struct d3d12_batch { struct hash_table *bos; struct util_dynarray local_bos; + struct util_dynarray local_bo_pending; struct hash_table *sampler_tables; struct set *sampler_views; #ifdef HAVE_GALLIUM_D3D12_GRAPHICS