mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2024-11-21 16:46:41 -08:00
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:
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
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user