diff --git a/src/gallium/drivers/d3d12/d3d12_bufmgr.cpp b/src/gallium/drivers/d3d12/d3d12_bufmgr.cpp index ace6cb23df0..1d161d97eaf 100644 --- a/src/gallium/drivers/d3d12/d3d12_bufmgr.cpp +++ b/src/gallium/drivers/d3d12/d3d12_bufmgr.cpp @@ -215,6 +215,57 @@ d3d12_bo_unreference(struct d3d12_bo *bo) } } +bool +d3d12_screen_reclaim_completed(struct d3d12_screen *screen) +{ + uint64_t completed = screen->fence->GetCompletedValue(); + struct list_head retired; + list_inithead(&retired); + + mtx_lock(&screen->pending_free_lock); + list_for_each_entry_safe(struct d3d12_pending_free_entry, entry, + &screen->pending_free_list, link) { + if (entry->fence_value > completed) + break; + list_del(&entry->link); + list_addtail(&entry->link, &retired); + } + mtx_unlock(&screen->pending_free_lock); + + bool dropped = !list_is_empty(&retired); + list_for_each_entry_safe(struct d3d12_pending_free_entry, entry, &retired, link) { + d3d12_bo_unreference(entry->bo); + FREE(entry); + } + return dropped; +} + +bool +d3d12_screen_reclaim_one(struct d3d12_screen *screen) +{ + uint64_t target = 0; + bool have_target = false; + + mtx_lock(&screen->pending_free_lock); + if (!list_is_empty(&screen->pending_free_list)) { + struct d3d12_pending_free_entry *head = + list_first_entry(&screen->pending_free_list, + struct d3d12_pending_free_entry, link); + target = head->fence_value; + have_target = true; + } + mtx_unlock(&screen->pending_free_lock); + + if (!have_target) + return false; + + if (screen->fence->GetCompletedValue() < target) + screen->fence->SetEventOnCompletion(target, nullptr); + + d3d12_screen_reclaim_completed(screen); + return true; +} + void * d3d12_bo_map(struct d3d12_bo *bo, D3D12_RANGE *range) { diff --git a/src/gallium/drivers/d3d12/d3d12_bufmgr.h b/src/gallium/drivers/d3d12/d3d12_bufmgr.h index 068c0cb3681..38b8165527d 100644 --- a/src/gallium/drivers/d3d12/d3d12_bufmgr.h +++ b/src/gallium/drivers/d3d12/d3d12_bufmgr.h @@ -158,6 +158,18 @@ d3d12_bo_map(struct d3d12_bo *bo, D3D12_RANGE *range); void d3d12_bo_unmap(struct d3d12_bo *bo, D3D12_RANGE *range); +struct d3d12_pending_free_entry { + struct list_head link; + struct d3d12_bo *bo; + uint64_t fence_value; +}; + +bool +d3d12_screen_reclaim_completed(struct d3d12_screen *screen); + +bool +d3d12_screen_reclaim_one(struct d3d12_screen *screen); + struct pb_manager * d3d12_bufmgr_create(struct d3d12_screen *screen); diff --git a/src/gallium/drivers/d3d12/d3d12_screen.cpp b/src/gallium/drivers/d3d12/d3d12_screen.cpp index ce9aca84486..8c3a4550541 100644 --- a/src/gallium/drivers/d3d12/d3d12_screen.cpp +++ b/src/gallium/drivers/d3d12/d3d12_screen.cpp @@ -598,6 +598,9 @@ d3d12_is_format_supported(struct pipe_screen *pscreen, void d3d12_deinit_screen(struct d3d12_screen *screen) { + while (d3d12_screen_reclaim_one(screen)) + ; + #ifdef HAVE_GALLIUM_D3D12_GRAPHICS if (screen->max_feature_level >= D3D_FEATURE_LEVEL_11_0) { if (screen->rtv_pool) { @@ -666,6 +669,7 @@ d3d12_destroy_screen(struct d3d12_screen *screen) { slab_destroy_parent(&screen->transfer_pool); mtx_destroy(&screen->submit_mutex); + mtx_destroy(&screen->pending_free_lock); mtx_destroy(&screen->descriptor_pool_mutex); #ifdef HAVE_GALLIUM_D3D12_GRAPHICS @@ -1300,6 +1304,8 @@ d3d12_init_screen_base(struct d3d12_screen *screen, struct sw_winsys *winsys, LU screen->adapter_luid = *adapter_luid; mtx_init(&screen->descriptor_pool_mutex, mtx_plain); mtx_init(&screen->submit_mutex, mtx_plain); + mtx_init(&screen->pending_free_lock, mtx_plain); + list_inithead(&screen->pending_free_list); list_inithead(&screen->context_list); screen->context_id_count = 16; diff --git a/src/gallium/drivers/d3d12/d3d12_screen.h b/src/gallium/drivers/d3d12/d3d12_screen.h index 4b99977cbc3..d5d8e902642 100644 --- a/src/gallium/drivers/d3d12/d3d12_screen.h +++ b/src/gallium/drivers/d3d12/d3d12_screen.h @@ -87,6 +87,9 @@ struct d3d12_screen { ID3D12Fence *fence; uint64_t fence_value; + mtx_t pending_free_lock; + struct list_head pending_free_list; + struct list_head residency_list; ID3D12Fence *residency_fence; uint64_t residency_fence_value;