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>
This commit is contained in:
parent
b1e735ee8f
commit
2c42c0da93
|
@ -645,3 +645,116 @@ void vkd3d_breadcrumb_tracer_end_command_list(struct d3d12_command_list *list)
|
|||
cmd.type = VKD3D_BREADCRUMB_COMMAND_SET_BOTTOM_MARKER;
|
||||
vkd3d_breadcrumb_tracer_add_command(list, &cmd);
|
||||
}
|
||||
|
||||
/* There is no obvious home for this code. It could be in heap.c, but this kind of
|
||||
* debug is only really useful when doing crash debugging, i.e. breadcrumbs,
|
||||
* so might as well have it here. */
|
||||
|
||||
static bool d3d12_resource_is_linear_placement(const struct d3d12_resource *resource)
|
||||
{
|
||||
return (resource->desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER &&
|
||||
!(resource->flags & VKD3D_RESOURCE_ACCELERATION_STRUCTURE)) ||
|
||||
(resource->flags & VKD3D_RESOURCE_LINEAR_TILING);
|
||||
}
|
||||
|
||||
static void d3d12_resource_report_parameters(char *buf, size_t buf_size, const struct d3d12_resource *resource)
|
||||
{
|
||||
if (resource->desc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER)
|
||||
{
|
||||
snprintf(buf, buf_size,
|
||||
"IMAGE: format = %s, width = %"PRIu64", height = %u, depth/layers = %u, levels = %u, flags = #%x",
|
||||
debug_dxgi_format(resource->desc.Format),
|
||||
resource->desc.Width,
|
||||
resource->desc.Height,
|
||||
resource->desc.DepthOrArraySize,
|
||||
resource->desc.MipLevels,
|
||||
resource->desc.Flags);
|
||||
}
|
||||
else if (resource->flags & VKD3D_RESOURCE_ACCELERATION_STRUCTURE)
|
||||
snprintf(buf, buf_size, "RTAS");
|
||||
else
|
||||
snprintf(buf, buf_size, "BUFFER");
|
||||
}
|
||||
|
||||
void vkd3d_breadcrumb_tracer_register_placed_resource(struct d3d12_heap *heap,
|
||||
struct d3d12_resource *resource,
|
||||
VkDeviceSize heap_offset, VkDeviceSize required_size)
|
||||
{
|
||||
const struct d3d12_heap_resource_placement *placement;
|
||||
bool candidate_resource_is_linear;
|
||||
bool placed_resource_is_linear;
|
||||
VkDeviceSize begin_overlap;
|
||||
VkDeviceSize end_overlap;
|
||||
char report_buffer[1024];
|
||||
bool has_alias = false;
|
||||
const char *msg;
|
||||
size_t i;
|
||||
|
||||
/* Linear aliasing with other linear resources is fine.
|
||||
* Image <-> Image, and Image <-> Buffer is far more dangerous however. */
|
||||
placed_resource_is_linear = d3d12_resource_is_linear_placement(resource);
|
||||
|
||||
pthread_mutex_lock(&heap->placement_lock);
|
||||
|
||||
for (i = 0; i < heap->placements_count; i++)
|
||||
{
|
||||
placement = &heap->placements[i];
|
||||
candidate_resource_is_linear = d3d12_resource_is_linear_placement(placement->resource);
|
||||
|
||||
begin_overlap = max(placement->heap_offset, heap_offset);
|
||||
end_overlap = min(placement->heap_offset + placement->size, heap_offset + required_size);
|
||||
|
||||
if (begin_overlap < end_overlap && candidate_resource_is_linear != placed_resource_is_linear)
|
||||
{
|
||||
/* Overlap. */
|
||||
/* Potentially problematic scenario, report this. */
|
||||
if (!has_alias)
|
||||
{
|
||||
if (resource->desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
|
||||
msg = "Attempting to place linear buffer resource on heap, placement aliases with non-linear layout.";
|
||||
else
|
||||
msg = "Attempting to place opaque resource on heap, placement aliases with other resources.";
|
||||
|
||||
d3d12_resource_report_parameters(report_buffer, sizeof(report_buffer), resource);
|
||||
INFO("\n%s\n New placement: resource cookie = %"PRIu64", offset = %"PRIu64", size = %"PRIu64", VA = %"PRIx64"\n\t%s\n",
|
||||
msg,
|
||||
resource->res.cookie,
|
||||
heap_offset, required_size, resource->res.va,
|
||||
report_buffer);
|
||||
|
||||
has_alias = true;
|
||||
}
|
||||
|
||||
d3d12_resource_report_parameters(report_buffer, sizeof(report_buffer), placement->resource);
|
||||
INFO("\n Existing aliasing resource : cookie = %"PRIu64", offset = %"PRIu64", size = %"PRIu64".\n\t\t%s\n",
|
||||
placement->resource->res.cookie, placement->heap_offset, placement->size,
|
||||
report_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
vkd3d_array_reserve((void**)&heap->placements, &heap->placements_size,
|
||||
heap->placements_count + 1, sizeof(*heap->placements));
|
||||
|
||||
heap->placements[heap->placements_count].resource = resource;
|
||||
heap->placements[heap->placements_count].heap_offset = heap_offset;
|
||||
heap->placements[heap->placements_count].size = required_size;
|
||||
heap->placements_count++;
|
||||
|
||||
pthread_mutex_unlock(&heap->placement_lock);
|
||||
}
|
||||
|
||||
void vkd3d_breadcrumb_tracer_unregister_placed_resource(struct d3d12_heap *heap, struct d3d12_resource *resource)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
pthread_mutex_lock(&heap->placement_lock);
|
||||
for (i = 0; i < heap->placements_count; i++)
|
||||
{
|
||||
if (heap->placements[i].resource == resource)
|
||||
{
|
||||
heap->placements[i] = heap->placements[--heap->placements_count];
|
||||
break;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&heap->placement_lock);
|
||||
}
|
|
@ -59,9 +59,13 @@ static void d3d12_heap_destroy(struct d3d12_heap *heap)
|
|||
{
|
||||
TRACE("Destroying heap %p.\n", heap);
|
||||
|
||||
#ifdef VKD3D_ENABLE_BREADCRUMBS
|
||||
vkd3d_free(heap->placements);
|
||||
pthread_mutex_destroy(&heap->placement_lock);
|
||||
#endif
|
||||
|
||||
vkd3d_free_memory(heap->device, &heap->device->memory_allocator, &heap->allocation);
|
||||
vkd3d_private_store_destroy(&heap->private_store);
|
||||
d3d12_device_release(heap->device);
|
||||
vkd3d_free(heap);
|
||||
}
|
||||
|
||||
|
@ -72,6 +76,18 @@ static void d3d12_heap_set_name(struct d3d12_heap *heap, const char *name)
|
|||
VK_OBJECT_TYPE_DEVICE_MEMORY, name);
|
||||
}
|
||||
|
||||
void d3d12_heap_dec_ref(struct d3d12_heap *heap)
|
||||
{
|
||||
ULONG refcount = InterlockedDecrement(&heap->internal_refcount);
|
||||
if (!refcount)
|
||||
d3d12_heap_destroy(heap);
|
||||
}
|
||||
|
||||
void d3d12_heap_inc_ref(struct d3d12_heap *heap)
|
||||
{
|
||||
InterlockedIncrement(&heap->internal_refcount);
|
||||
}
|
||||
|
||||
static ULONG STDMETHODCALLTYPE d3d12_heap_Release(d3d12_heap_iface *iface)
|
||||
{
|
||||
struct d3d12_heap *heap = impl_from_ID3D12Heap1(iface);
|
||||
|
@ -80,7 +96,11 @@ static ULONG STDMETHODCALLTYPE d3d12_heap_Release(d3d12_heap_iface *iface)
|
|||
TRACE("%p decreasing refcount to %u.\n", heap, refcount);
|
||||
|
||||
if (!refcount)
|
||||
d3d12_heap_destroy(heap);
|
||||
{
|
||||
struct d3d12_device *device = heap->device;
|
||||
d3d12_heap_dec_ref(heap);
|
||||
d3d12_device_release(device);
|
||||
}
|
||||
|
||||
return refcount;
|
||||
}
|
||||
|
@ -225,6 +245,7 @@ static HRESULT d3d12_heap_init(struct d3d12_heap *heap, struct d3d12_device *dev
|
|||
memset(heap, 0, sizeof(*heap));
|
||||
heap->ID3D12Heap_iface.lpVtbl = &d3d12_heap_vtbl;
|
||||
heap->refcount = 1;
|
||||
heap->internal_refcount = 1;
|
||||
heap->desc = *desc;
|
||||
heap->device = device;
|
||||
|
||||
|
@ -252,6 +273,10 @@ static HRESULT d3d12_heap_init(struct d3d12_heap *heap, struct d3d12_device *dev
|
|||
return hr;
|
||||
}
|
||||
|
||||
#ifdef VKD3D_ENABLE_BREADCRUMBS
|
||||
pthread_mutex_init(&heap->placement_lock, NULL);
|
||||
#endif
|
||||
|
||||
d3d12_device_add_ref(heap->device);
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -1419,7 +1419,14 @@ static ULONG d3d12_resource_decref(struct d3d12_resource *resource)
|
|||
TRACE("%p decreasing refcount to %u.\n", resource, refcount);
|
||||
|
||||
if (!refcount)
|
||||
{
|
||||
VKD3D_UNUSED struct d3d12_heap *heap = resource->heap;
|
||||
d3d12_resource_destroy(resource, resource->device);
|
||||
#ifdef VKD3D_ENABLE_BREADCRUMBS
|
||||
if (heap && (vkd3d_config_flags & VKD3D_CONFIG_FLAG_BREADCRUMBS))
|
||||
d3d12_heap_dec_ref(heap);
|
||||
#endif
|
||||
}
|
||||
|
||||
return refcount;
|
||||
}
|
||||
|
@ -1511,7 +1518,6 @@ static ULONG STDMETHODCALLTYPE d3d12_resource_AddRef(d3d12_resource_iface *iface
|
|||
if (refcount == 1)
|
||||
{
|
||||
struct d3d12_device *device = resource->device;
|
||||
|
||||
d3d12_device_add_ref(device);
|
||||
d3d12_resource_incref(resource);
|
||||
}
|
||||
|
@ -2605,6 +2611,11 @@ static void d3d12_resource_destroy(struct d3d12_resource *resource, struct d3d12
|
|||
if (resource->vrs_view)
|
||||
VK_CALL(vkDestroyImageView(device->vk_device, resource->vrs_view, NULL));
|
||||
|
||||
#ifdef VKD3D_ENABLE_BREADCRUMBS
|
||||
if ((vkd3d_config_flags & VKD3D_CONFIG_FLAG_BREADCRUMBS) && resource->heap)
|
||||
vkd3d_breadcrumb_tracer_unregister_placed_resource(resource->heap, resource);
|
||||
#endif
|
||||
|
||||
vkd3d_private_store_destroy(&resource->private_store);
|
||||
d3d12_device_release(resource->device);
|
||||
vkd3d_free(resource);
|
||||
|
@ -2861,6 +2872,7 @@ HRESULT d3d12_resource_create_placed(struct d3d12_device *device, const D3D12_RE
|
|||
{
|
||||
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
||||
VkMemoryRequirements memory_requirements;
|
||||
VKD3D_UNUSED VkDeviceSize required_size;
|
||||
VkBindImageMemoryInfo bind_info;
|
||||
struct d3d12_resource *object;
|
||||
VkResult vr;
|
||||
|
@ -2900,11 +2912,13 @@ HRESULT d3d12_resource_create_placed(struct d3d12_device *device, const D3D12_RE
|
|||
|
||||
if (heap_offset + memory_requirements.size > heap->allocation.resource.size)
|
||||
{
|
||||
ERR("Heap too small for the texture (heap=%"PRIu64", res=%"PRIu64".\n",
|
||||
ERR("Heap too small for the texture (heap=%"PRIu64", res=%"PRIu64").\n",
|
||||
heap->allocation.resource.size, heap_offset + memory_requirements.size);
|
||||
hr = E_INVALIDARG;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
required_size = memory_requirements.size;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2915,6 +2929,8 @@ HRESULT d3d12_resource_create_placed(struct d3d12_device *device, const D3D12_RE
|
|||
hr = E_INVALIDARG;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
required_size = desc->Width;
|
||||
}
|
||||
|
||||
vkd3d_memory_allocation_slice(&object->mem, &heap->allocation, heap_offset, 0);
|
||||
|
@ -2956,6 +2972,14 @@ HRESULT d3d12_resource_create_placed(struct d3d12_device *device, const D3D12_RE
|
|||
if (desc->Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL))
|
||||
object->initial_layout_transition = 0;
|
||||
|
||||
#ifdef VKD3D_ENABLE_BREADCRUMBS
|
||||
if (vkd3d_config_flags & VKD3D_CONFIG_FLAG_BREADCRUMBS)
|
||||
{
|
||||
vkd3d_breadcrumb_tracer_register_placed_resource(heap, object, heap_offset, required_size);
|
||||
d3d12_heap_inc_ref(heap);
|
||||
}
|
||||
#endif
|
||||
|
||||
*resource = object;
|
||||
return S_OK;
|
||||
|
||||
|
|
|
@ -740,18 +740,38 @@ HRESULT vkd3d_memory_allocator_flush_clears(struct vkd3d_memory_allocator *alloc
|
|||
/* ID3D12Heap */
|
||||
typedef ID3D12Heap1 d3d12_heap_iface;
|
||||
|
||||
#ifdef VKD3D_ENABLE_BREADCRUMBS
|
||||
struct d3d12_heap_resource_placement
|
||||
{
|
||||
struct d3d12_resource *resource;
|
||||
VkDeviceSize heap_offset;
|
||||
VkDeviceSize size;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct d3d12_heap
|
||||
{
|
||||
d3d12_heap_iface ID3D12Heap_iface;
|
||||
LONG refcount;
|
||||
LONG internal_refcount;
|
||||
|
||||
D3D12_HEAP_DESC desc;
|
||||
struct vkd3d_memory_allocation allocation;
|
||||
|
||||
#ifdef VKD3D_ENABLE_BREADCRUMBS
|
||||
struct d3d12_heap_resource_placement *placements;
|
||||
size_t placements_count;
|
||||
size_t placements_size;
|
||||
pthread_mutex_t placement_lock;
|
||||
#endif
|
||||
|
||||
struct d3d12_device *device;
|
||||
struct vkd3d_private_store private_store;
|
||||
};
|
||||
|
||||
void d3d12_heap_inc_ref(struct d3d12_heap *heap);
|
||||
void d3d12_heap_dec_ref(struct d3d12_heap *heap);
|
||||
|
||||
HRESULT d3d12_heap_create(struct d3d12_device *device, const D3D12_HEAP_DESC *desc,
|
||||
void *host_address, struct d3d12_heap **heap);
|
||||
HRESULT d3d12_device_validate_custom_heap_type(struct d3d12_device *device,
|
||||
|
@ -2622,6 +2642,10 @@ void vkd3d_breadcrumb_tracer_add_command(struct d3d12_command_list *list,
|
|||
void vkd3d_breadcrumb_tracer_signal(struct d3d12_command_list *list);
|
||||
void vkd3d_breadcrumb_tracer_end_command_list(struct d3d12_command_list *list);
|
||||
|
||||
void vkd3d_breadcrumb_tracer_register_placed_resource(struct d3d12_heap *heap, struct d3d12_resource *resource,
|
||||
VkDeviceSize heap_offset, VkDeviceSize required_size);
|
||||
void vkd3d_breadcrumb_tracer_unregister_placed_resource(struct d3d12_heap *heap, struct d3d12_resource *resource);
|
||||
|
||||
#define VKD3D_BREADCRUMB_COMMAND(cmd_type) do { \
|
||||
if (vkd3d_config_flags & VKD3D_CONFIG_FLAG_BREADCRUMBS) { \
|
||||
struct vkd3d_breadcrumb_command breadcrumb_cmd; \
|
||||
|
|
Loading…
Reference in New Issue