Skip to content

Commit 598fae0

Browse files
vkd3d: Add a crude form of alias debugging.
Report any placed aliases which could cause issues. Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
1 parent 8d9eee4 commit 598fae0

File tree

3 files changed

+186
-4
lines changed

3 files changed

+186
-4
lines changed

libs/vkd3d/heap.c

Lines changed: 138 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,13 @@ static void d3d12_heap_destroy(struct d3d12_heap *heap)
5959
{
6060
TRACE("Destroying heap %p.\n", heap);
6161

62+
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
63+
vkd3d_free(heap->placements);
64+
pthread_mutex_destroy(&heap->placement_lock);
65+
#endif
66+
6267
vkd3d_free_memory(heap->device, &heap->device->memory_allocator, &heap->allocation);
6368
vkd3d_private_store_destroy(&heap->private_store);
64-
d3d12_device_release(heap->device);
6569
vkd3d_free(heap);
6670
}
6771

@@ -72,6 +76,18 @@ static void d3d12_heap_set_name(struct d3d12_heap *heap, const char *name)
7276
VK_OBJECT_TYPE_DEVICE_MEMORY, name);
7377
}
7478

79+
void d3d12_heap_dec_ref(struct d3d12_heap *heap)
80+
{
81+
ULONG refcount = InterlockedDecrement(&heap->internal_refcount);
82+
if (!refcount)
83+
d3d12_heap_destroy(heap);
84+
}
85+
86+
void d3d12_heap_inc_ref(struct d3d12_heap *heap)
87+
{
88+
InterlockedIncrement(&heap->internal_refcount);
89+
}
90+
7591
static ULONG STDMETHODCALLTYPE d3d12_heap_Release(d3d12_heap_iface *iface)
7692
{
7793
struct d3d12_heap *heap = impl_from_ID3D12Heap1(iface);
@@ -80,7 +96,11 @@ static ULONG STDMETHODCALLTYPE d3d12_heap_Release(d3d12_heap_iface *iface)
8096
TRACE("%p decreasing refcount to %u.\n", heap, refcount);
8197

8298
if (!refcount)
83-
d3d12_heap_destroy(heap);
99+
{
100+
struct d3d12_device *device = heap->device;
101+
d3d12_heap_dec_ref(heap);
102+
d3d12_device_release(device);
103+
}
84104

85105
return refcount;
86106
}
@@ -216,6 +236,117 @@ static HRESULT validate_heap_desc(struct d3d12_device *device, const D3D12_HEAP_
216236
return S_OK;
217237
}
218238

239+
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
240+
static bool d3d12_resource_is_linear_placement(const struct d3d12_resource *resource)
241+
{
242+
return (resource->desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER &&
243+
!(resource->flags & VKD3D_RESOURCE_ACCELERATION_STRUCTURE)) ||
244+
(resource->flags & VKD3D_RESOURCE_LINEAR_TILING);
245+
}
246+
247+
static void d3d12_resource_report_parameters(char *buf, size_t buf_size, const struct d3d12_resource *resource)
248+
{
249+
if (resource->desc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER)
250+
{
251+
snprintf(buf, buf_size,
252+
"IMAGE: format = %s, width = %"PRIu64", height = %u, depth/layers = %u, levels = %u, flags = #%x",
253+
debug_dxgi_format(resource->desc.Format),
254+
resource->desc.Width,
255+
resource->desc.Height,
256+
resource->desc.DepthOrArraySize,
257+
resource->desc.MipLevels,
258+
resource->desc.Flags);
259+
}
260+
else if (resource->flags & VKD3D_RESOURCE_ACCELERATION_STRUCTURE)
261+
snprintf(buf, buf_size, "RTAS");
262+
else
263+
snprintf(buf, buf_size, "BUFFER");
264+
}
265+
266+
void d3d12_heap_register_placed_resource(struct d3d12_heap *heap,
267+
struct d3d12_resource *resource,
268+
VkDeviceSize heap_offset, VkDeviceSize required_size)
269+
{
270+
const struct d3d12_heap_resource_placement *placement;
271+
bool candidate_resource_is_linear;
272+
bool placed_resource_is_linear;
273+
VkDeviceSize begin_overlap;
274+
VkDeviceSize end_overlap;
275+
char report_buffer[1024];
276+
bool has_alias = false;
277+
const char *msg;
278+
size_t i;
279+
280+
/* Linear aliasing with other linear resources is fine.
281+
* Image <-> Image, and Image <-> Buffer is far more dangerous however. */
282+
placed_resource_is_linear = d3d12_resource_is_linear_placement(resource);
283+
284+
pthread_mutex_lock(&heap->placement_lock);
285+
286+
for (i = 0; i < heap->placements_count; i++)
287+
{
288+
placement = &heap->placements[i];
289+
candidate_resource_is_linear = d3d12_resource_is_linear_placement(placement->resource);
290+
291+
begin_overlap = max(placement->heap_offset, heap_offset);
292+
end_overlap = min(placement->heap_offset + placement->size, heap_offset + required_size);
293+
294+
if (begin_overlap < end_overlap && candidate_resource_is_linear != placed_resource_is_linear)
295+
{
296+
/* Overlap. */
297+
/* Potentially problematic scenario, report this. */
298+
if (!has_alias)
299+
{
300+
if (resource->desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
301+
msg = "Attempting to place linear buffer resource on heap, placement aliases with non-linear layout.";
302+
else
303+
msg = "Attempting to place opaque resource on heap, placement aliases with other resources.";
304+
305+
d3d12_resource_report_parameters(report_buffer, sizeof(report_buffer), resource);
306+
INFO("\n%s\n New placement: resource cookie = %"PRIu64", offset = %"PRIu64", size = %"PRIu64", VA = %"PRIx64"\n\t%s\n",
307+
msg,
308+
resource->res.cookie,
309+
heap_offset, required_size, resource->res.va,
310+
report_buffer);
311+
312+
has_alias = true;
313+
}
314+
315+
d3d12_resource_report_parameters(report_buffer, sizeof(report_buffer), placement->resource);
316+
INFO("\n Existing aliasing resource : cookie = %"PRIu64", offset = %"PRIu64", size = %"PRIu64".\n\t\t%s\n",
317+
placement->resource->res.cookie, placement->heap_offset, placement->size,
318+
report_buffer);
319+
}
320+
}
321+
322+
vkd3d_array_reserve((void**)&heap->placements, &heap->placements_size,
323+
heap->placements_count + 1, sizeof(*heap->placements));
324+
325+
heap->placements[heap->placements_count].resource = resource;
326+
heap->placements[heap->placements_count].heap_offset = heap_offset;
327+
heap->placements[heap->placements_count].size = required_size;
328+
heap->placements_count++;
329+
330+
pthread_mutex_unlock(&heap->placement_lock);
331+
}
332+
333+
void d3d12_heap_unregister_placed_resource(struct d3d12_heap *heap, struct d3d12_resource *resource)
334+
{
335+
size_t i;
336+
337+
pthread_mutex_lock(&heap->placement_lock);
338+
for (i = 0; i < heap->placements_count; i++)
339+
{
340+
if (heap->placements[i].resource == resource)
341+
{
342+
heap->placements[i] = heap->placements[--heap->placements_count];
343+
break;
344+
}
345+
}
346+
pthread_mutex_unlock(&heap->placement_lock);
347+
}
348+
#endif
349+
219350
static HRESULT d3d12_heap_init(struct d3d12_heap *heap, struct d3d12_device *device,
220351
const D3D12_HEAP_DESC *desc, void* host_address)
221352
{
@@ -225,6 +356,7 @@ static HRESULT d3d12_heap_init(struct d3d12_heap *heap, struct d3d12_device *dev
225356
memset(heap, 0, sizeof(*heap));
226357
heap->ID3D12Heap_iface.lpVtbl = &d3d12_heap_vtbl;
227358
heap->refcount = 1;
359+
heap->internal_refcount = 1;
228360
heap->desc = *desc;
229361
heap->device = device;
230362

@@ -252,6 +384,10 @@ static HRESULT d3d12_heap_init(struct d3d12_heap *heap, struct d3d12_device *dev
252384
return hr;
253385
}
254386

387+
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
388+
pthread_mutex_init(&heap->placement_lock, NULL);
389+
#endif
390+
255391
d3d12_device_add_ref(heap->device);
256392
return S_OK;
257393
}

libs/vkd3d/resource.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1419,7 +1419,14 @@ static ULONG d3d12_resource_decref(struct d3d12_resource *resource)
14191419
TRACE("%p decreasing refcount to %u.\n", resource, refcount);
14201420

14211421
if (!refcount)
1422+
{
1423+
VKD3D_UNUSED struct d3d12_heap *heap = resource->heap;
14221424
d3d12_resource_destroy(resource, resource->device);
1425+
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
1426+
if (heap)
1427+
d3d12_heap_dec_ref(heap);
1428+
#endif
1429+
}
14231430

14241431
return refcount;
14251432
}
@@ -1511,7 +1518,6 @@ static ULONG STDMETHODCALLTYPE d3d12_resource_AddRef(d3d12_resource_iface *iface
15111518
if (refcount == 1)
15121519
{
15131520
struct d3d12_device *device = resource->device;
1514-
15151521
d3d12_device_add_ref(device);
15161522
d3d12_resource_incref(resource);
15171523
}
@@ -2605,6 +2611,11 @@ static void d3d12_resource_destroy(struct d3d12_resource *resource, struct d3d12
26052611
if (resource->vrs_view)
26062612
VK_CALL(vkDestroyImageView(device->vk_device, resource->vrs_view, NULL));
26072613

2614+
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
2615+
if (resource->heap)
2616+
d3d12_heap_unregister_placed_resource(resource->heap, resource);
2617+
#endif
2618+
26082619
vkd3d_private_store_destroy(&resource->private_store);
26092620
d3d12_device_release(resource->device);
26102621
vkd3d_free(resource);
@@ -2861,6 +2872,7 @@ HRESULT d3d12_resource_create_placed(struct d3d12_device *device, const D3D12_RE
28612872
{
28622873
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
28632874
VkMemoryRequirements memory_requirements;
2875+
VKD3D_UNUSED VkDeviceSize required_size;
28642876
VkBindImageMemoryInfo bind_info;
28652877
struct d3d12_resource *object;
28662878
bool force_committed;
@@ -2910,11 +2922,13 @@ HRESULT d3d12_resource_create_placed(struct d3d12_device *device, const D3D12_RE
29102922

29112923
if (heap_offset + memory_requirements.size > heap->allocation.resource.size)
29122924
{
2913-
ERR("Heap too small for the texture (heap=%"PRIu64", res=%"PRIu64".\n",
2925+
ERR("Heap too small for the texture (heap=%"PRIu64", res=%"PRIu64").\n",
29142926
heap->allocation.resource.size, heap_offset + memory_requirements.size);
29152927
hr = E_INVALIDARG;
29162928
goto fail;
29172929
}
2930+
2931+
required_size = memory_requirements.size;
29182932
}
29192933
else
29202934
{
@@ -2925,6 +2939,8 @@ HRESULT d3d12_resource_create_placed(struct d3d12_device *device, const D3D12_RE
29252939
hr = E_INVALIDARG;
29262940
goto fail;
29272941
}
2942+
2943+
required_size = desc->Width;
29282944
}
29292945

29302946
vkd3d_memory_allocation_slice(&object->mem, &heap->allocation, heap_offset, 0);
@@ -2957,6 +2973,11 @@ HRESULT d3d12_resource_create_placed(struct d3d12_device *device, const D3D12_RE
29572973
goto fail;
29582974
}
29592975

2976+
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
2977+
d3d12_heap_register_placed_resource(heap, object, heap_offset, required_size);
2978+
d3d12_heap_inc_ref(heap);
2979+
#endif
2980+
29602981
*resource = object;
29612982
return S_OK;
29622983

libs/vkd3d/vkd3d_private.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,18 +740,43 @@ HRESULT vkd3d_memory_allocator_flush_clears(struct vkd3d_memory_allocator *alloc
740740
/* ID3D12Heap */
741741
typedef ID3D12Heap1 d3d12_heap_iface;
742742

743+
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
744+
struct d3d12_heap_resource_placement
745+
{
746+
struct d3d12_resource *resource;
747+
VkDeviceSize heap_offset;
748+
VkDeviceSize size;
749+
};
750+
#endif
751+
743752
struct d3d12_heap
744753
{
745754
d3d12_heap_iface ID3D12Heap_iface;
746755
LONG refcount;
756+
LONG internal_refcount;
747757

748758
D3D12_HEAP_DESC desc;
749759
struct vkd3d_memory_allocation allocation;
750760

761+
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
762+
struct d3d12_heap_resource_placement *placements;
763+
size_t placements_count;
764+
size_t placements_size;
765+
pthread_mutex_t placement_lock;
766+
#endif
767+
751768
struct d3d12_device *device;
752769
struct vkd3d_private_store private_store;
753770
};
754771

772+
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
773+
void d3d12_heap_register_placed_resource(struct d3d12_heap *heap, struct d3d12_resource *resource,
774+
VkDeviceSize heap_offset, VkDeviceSize required_size);
775+
void d3d12_heap_unregister_placed_resource(struct d3d12_heap *heap, struct d3d12_resource *resource);
776+
#endif
777+
void d3d12_heap_inc_ref(struct d3d12_heap *heap);
778+
void d3d12_heap_dec_ref(struct d3d12_heap *heap);
779+
755780
HRESULT d3d12_heap_create(struct d3d12_device *device, const D3D12_HEAP_DESC *desc,
756781
void *host_address, struct d3d12_heap **heap);
757782
HRESULT d3d12_device_validate_custom_heap_type(struct d3d12_device *device,

0 commit comments

Comments
 (0)