vkd3d: Do not destroy a heap until its resource count is zero.

Fixes a crash on exit in Horizon Zero Dawn (which requres added SM 6.0 support).

Placed resources should hold a reference to their heap:
https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-createheap
This commit is contained in:
Conor McCarthy 2023-03-27 16:30:43 +10:00 committed by Alexandre Julliard
parent 7a9e393ea0
commit 88667098eb
Notes: Alexandre Julliard 2023-04-03 22:09:05 +02:00
Approved-by: Giovanni Mascellani (@giomasce)
Approved-by: Henri Verbeet (@hverbeet)
Approved-by: Alexandre Julliard (@julliard)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/127
2 changed files with 15 additions and 3 deletions

View File

@ -346,12 +346,19 @@ 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);
if (!refcount) /* A heap must not be destroyed until all contained resources are destroyed. */
if (!refcount && !heap->resource_count)
d3d12_heap_destroy(heap); d3d12_heap_destroy(heap);
return refcount; return refcount;
} }
static void d3d12_heap_resource_destroyed(struct d3d12_heap *heap)
{
if (!InterlockedDecrement(&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)
{ {
@ -561,6 +568,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->is_private = !!resource; heap->is_private = !!resource;
@ -628,6 +636,8 @@ 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;
return S_OK; return S_OK;
} }
@ -1027,8 +1037,8 @@ static void d3d12_resource_destroy(struct d3d12_resource *resource, struct d3d12
else else
VK_CALL(vkDestroyImage(device->vk_device, resource->u.vk_image, NULL)); VK_CALL(vkDestroyImage(device->vk_device, resource->u.vk_image, NULL));
if (resource->flags & VKD3D_RESOURCE_DEDICATED_HEAP) if (resource->heap)
d3d12_heap_destroy(resource->heap); d3d12_heap_resource_destroyed(resource->heap);
} }
static ULONG d3d12_resource_incref(struct d3d12_resource *resource) static ULONG d3d12_resource_incref(struct d3d12_resource *resource)
@ -1941,6 +1951,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;
InterlockedIncrement(&heap->resource_count);
} }
else else
{ {

View File

@ -563,6 +563,7 @@ struct d3d12_heap
{ {
ID3D12Heap ID3D12Heap_iface; ID3D12Heap ID3D12Heap_iface;
LONG refcount; LONG refcount;
LONG resource_count;
bool is_private; bool is_private;
D3D12_HEAP_DESC desc; D3D12_HEAP_DESC desc;