mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-09-12 18:50:22 -07:00
vkd3d: Replace the resource count field of struct d3d12_heap with an internal refcount.
When a heap was released at the same time as the last resource on that heap, it was possible for both to see each other's refcount/resource_count as 0 and both would try to destroy the heap. Avoid that by converting "resource_count" to an internal refcount, which holds an extra +1 if the main refcount is nonzero. The final release will then be synchronized between the two since both will operate on "internal_refcount".
This commit is contained in:
Notes:
Henri Verbeet
2025-06-25 17:09:25 +02:00
Approved-by: Henri Verbeet (@hverbeet) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1602
@@ -310,6 +310,9 @@ static ULONG STDMETHODCALLTYPE d3d12_heap_AddRef(ID3D12Heap *iface)
|
|||||||
struct d3d12_heap *heap = impl_from_ID3D12Heap(iface);
|
struct d3d12_heap *heap = impl_from_ID3D12Heap(iface);
|
||||||
unsigned int refcount = vkd3d_atomic_increment_u32(&heap->refcount);
|
unsigned int refcount = vkd3d_atomic_increment_u32(&heap->refcount);
|
||||||
|
|
||||||
|
if (refcount == 1)
|
||||||
|
vkd3d_atomic_increment_u32(&heap->internal_refcount);
|
||||||
|
|
||||||
TRACE("%p increasing refcount to %u.\n", heap, refcount);
|
TRACE("%p increasing refcount to %u.\n", heap, refcount);
|
||||||
|
|
||||||
VKD3D_ASSERT(!heap->is_private);
|
VKD3D_ASSERT(!heap->is_private);
|
||||||
@@ -342,6 +345,12 @@ static void d3d12_heap_destroy(struct d3d12_heap *heap)
|
|||||||
d3d12_device_release(device);
|
d3d12_device_release(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void d3d12_heap_decref(struct d3d12_heap *heap)
|
||||||
|
{
|
||||||
|
if (!vkd3d_atomic_decrement_u32(&heap->internal_refcount))
|
||||||
|
d3d12_heap_destroy(heap);
|
||||||
|
}
|
||||||
|
|
||||||
static ULONG STDMETHODCALLTYPE d3d12_heap_Release(ID3D12Heap *iface)
|
static ULONG STDMETHODCALLTYPE d3d12_heap_Release(ID3D12Heap *iface)
|
||||||
{
|
{
|
||||||
struct d3d12_heap *heap = impl_from_ID3D12Heap(iface);
|
struct d3d12_heap *heap = impl_from_ID3D12Heap(iface);
|
||||||
@@ -350,18 +359,12 @@ static ULONG STDMETHODCALLTYPE d3d12_heap_Release(ID3D12Heap *iface)
|
|||||||
TRACE("%p decreasing refcount to %u.\n", heap, refcount);
|
TRACE("%p decreasing refcount to %u.\n", heap, refcount);
|
||||||
|
|
||||||
/* A heap must not be destroyed until all contained resources are destroyed. */
|
/* A heap must not be destroyed until all contained resources are destroyed. */
|
||||||
if (!refcount && !heap->resource_count)
|
if (!refcount)
|
||||||
d3d12_heap_destroy(heap);
|
d3d12_heap_decref(heap);
|
||||||
|
|
||||||
return refcount;
|
return refcount;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void d3d12_heap_resource_destroyed(struct d3d12_heap *heap)
|
|
||||||
{
|
|
||||||
if (!vkd3d_atomic_decrement_u32(&heap->resource_count) && (!heap->refcount || heap->is_private))
|
|
||||||
d3d12_heap_destroy(heap);
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT STDMETHODCALLTYPE d3d12_heap_GetPrivateData(ID3D12Heap *iface,
|
static HRESULT STDMETHODCALLTYPE d3d12_heap_GetPrivateData(ID3D12Heap *iface,
|
||||||
REFGUID guid, UINT *data_size, void *data)
|
REFGUID guid, UINT *data_size, void *data)
|
||||||
{
|
{
|
||||||
@@ -487,7 +490,7 @@ static HRESULT d3d12_heap_init(struct d3d12_heap *heap,
|
|||||||
|
|
||||||
heap->ID3D12Heap_iface.lpVtbl = &d3d12_heap_vtbl;
|
heap->ID3D12Heap_iface.lpVtbl = &d3d12_heap_vtbl;
|
||||||
heap->refcount = 1;
|
heap->refcount = 1;
|
||||||
heap->resource_count = 0;
|
heap->internal_refcount = 1;
|
||||||
|
|
||||||
heap->is_private = !!resource;
|
heap->is_private = !!resource;
|
||||||
|
|
||||||
@@ -555,8 +558,6 @@ static HRESULT d3d12_heap_init(struct d3d12_heap *heap,
|
|||||||
heap->device = device;
|
heap->device = device;
|
||||||
if (!heap->is_private)
|
if (!heap->is_private)
|
||||||
d3d12_device_add_ref(heap->device);
|
d3d12_device_add_ref(heap->device);
|
||||||
else
|
|
||||||
heap->resource_count = 1;
|
|
||||||
|
|
||||||
if (d3d12_heap_get_memory_property_flags(heap) & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
|
if (d3d12_heap_get_memory_property_flags(heap) & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
|
||||||
{
|
{
|
||||||
@@ -998,7 +999,7 @@ static void d3d12_resource_destroy(struct d3d12_resource *resource, struct d3d12
|
|||||||
d3d12_resource_tile_info_cleanup(resource);
|
d3d12_resource_tile_info_cleanup(resource);
|
||||||
|
|
||||||
if (resource->heap)
|
if (resource->heap)
|
||||||
d3d12_heap_resource_destroyed(resource->heap);
|
d3d12_heap_decref(resource->heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ULONG d3d12_resource_incref(struct d3d12_resource *resource)
|
static ULONG d3d12_resource_incref(struct d3d12_resource *resource)
|
||||||
@@ -2200,7 +2201,7 @@ static HRESULT vkd3d_bind_heap_memory(struct d3d12_device *device,
|
|||||||
{
|
{
|
||||||
resource->heap = heap;
|
resource->heap = heap;
|
||||||
resource->heap_offset = heap_offset;
|
resource->heap_offset = heap_offset;
|
||||||
vkd3d_atomic_increment_u32(&heap->resource_count);
|
vkd3d_atomic_increment_u32(&heap->internal_refcount);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -436,7 +436,7 @@ struct d3d12_heap
|
|||||||
{
|
{
|
||||||
ID3D12Heap ID3D12Heap_iface;
|
ID3D12Heap ID3D12Heap_iface;
|
||||||
unsigned int refcount;
|
unsigned int refcount;
|
||||||
unsigned int resource_count;
|
unsigned int internal_refcount;
|
||||||
|
|
||||||
bool is_private;
|
bool is_private;
|
||||||
D3D12_HEAP_DESC desc;
|
D3D12_HEAP_DESC desc;
|
||||||
|
Reference in New Issue
Block a user