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);
if (!refcount)
/* A heap must not be destroyed until all contained resources are destroyed. */
if (!refcount && !heap->resource_count)
d3d12_heap_destroy(heap);
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,
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->refcount = 1;
heap->resource_count = 0;
heap->is_private = !!resource;
@ -628,6 +636,8 @@ static HRESULT d3d12_heap_init(struct d3d12_heap *heap,
heap->device = device;
if (!heap->is_private)
d3d12_device_add_ref(heap->device);
else
heap->resource_count = 1;
return S_OK;
}
@ -1027,8 +1037,8 @@ static void d3d12_resource_destroy(struct d3d12_resource *resource, struct d3d12
else
VK_CALL(vkDestroyImage(device->vk_device, resource->u.vk_image, NULL));
if (resource->flags & VKD3D_RESOURCE_DEDICATED_HEAP)
d3d12_heap_destroy(resource->heap);
if (resource->heap)
d3d12_heap_resource_destroyed(resource->heap);
}
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_offset = heap_offset;
InterlockedIncrement(&heap->resource_count);
}
else
{

View File

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