vkd3d: Rewrite descriptor QA.

Adds support for GPU-assisted validation of descriptor usage in the
CBV_SRV_UAV heap.

Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
This commit is contained in:
Hans-Kristian Arntzen 2021-05-14 14:00:00 +02:00
parent 815277e392
commit a256a9266e
9 changed files with 562 additions and 119 deletions

View File

@ -21,6 +21,7 @@
#include "vkd3d_private.h"
#include "vkd3d_swapchain_factory.h"
#include "vkd3d_descriptor_debug.h"
#ifdef VKD3D_ENABLE_RENDERDOC
#include "vkd3d_renderdoc.h"
#endif
@ -312,9 +313,10 @@ static void vkd3d_wait_for_gpu_timeline_semaphore(struct vkd3d_fence_worker *wor
return;
}
/* This is a good time to kick the debug ring thread into action. */
/* This is a good time to kick the debug threads into action. */
if (device->debug_ring.active)
pthread_cond_signal(&device->debug_ring.ring_cond);
vkd3d_descriptor_debug_kick_qa_check(device->descriptor_qa_global_info);
TRACE("Signaling fence %p value %#"PRIx64".\n", fence->fence, fence->value);
if (FAILED(hr = d3d12_fence_signal(fence->fence, fence->value)))

View File

@ -26,19 +26,73 @@
static pthread_once_t debug_once = PTHREAD_ONCE_INIT;
static pthread_mutex_t debug_lock = PTHREAD_MUTEX_INITIALIZER;
static bool descriptor_debug_active;
static bool descriptor_debug_active_qa_checks;
static bool descriptor_debug_active_log;
static FILE *descriptor_debug_file;
struct vkd3d_descriptor_qa_global_info
{
struct vkd3d_descriptor_qa_global_buffer_data *data;
VkDescriptorBufferInfo descriptor;
VkBuffer vk_buffer;
VkDeviceMemory vk_memory;
unsigned int num_cookies;
pthread_t ring_thread;
pthread_mutex_t ring_lock;
pthread_cond_t ring_cond;
bool active;
};
static const char *debug_descriptor_type(vkd3d_descriptor_qa_flags type_flags)
{
bool has_raw_va = !!(type_flags & VKD3D_DESCRIPTOR_QA_TYPE_RAW_VA_BIT);
switch (type_flags & ~VKD3D_DESCRIPTOR_QA_TYPE_RAW_VA_BIT)
{
case VKD3D_DESCRIPTOR_QA_TYPE_SAMPLER_BIT: return "SAMPLER";
case VKD3D_DESCRIPTOR_QA_TYPE_SAMPLED_IMAGE_BIT: return "SAMPLED_IMAGE";
case VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_IMAGE_BIT: return "STORAGE_IMAGE";
case VKD3D_DESCRIPTOR_QA_TYPE_UNIFORM_BUFFER_BIT: return "UNIFORM_BUFFER";
case VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_BUFFER_BIT: return "STORAGE_BUFFER";
case VKD3D_DESCRIPTOR_QA_TYPE_UNIFORM_TEXEL_BUFFER_BIT: return "UNIFORM_TEXEL_BUFFER";
case VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_TEXEL_BUFFER_BIT: return "STORAGE_TEXEL_BUFFER";
case VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_TEXEL_BUFFER_BIT | VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_BUFFER_BIT:
return has_raw_va ? "STORAGE_TEXEL_BUFFER / STORAGE_BUFFER (w/ counter)" : "STORAGE_TEXEL_BUFFER / STORAGE_BUFFER";
case VKD3D_DESCRIPTOR_QA_TYPE_UNIFORM_TEXEL_BUFFER_BIT | VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_BUFFER_BIT:
return has_raw_va ? "UNIFORM_TEXEL_BUFFER / STORAGE_BUFFER (w/ counter)" : "UNIFORM_TEXEL_BUFFER / STORAGE_BUFFER";
case VKD3D_DESCRIPTOR_QA_TYPE_RT_ACCELERATION_STRUCTURE_BIT:
return "RTAS";
case 0:
return "NONE";
default: return "?";
}
}
static void vkd3d_descriptor_debug_init_once(void)
{
const char *env = getenv("VKD3D_DESCRIPTOR_QA_LOG");
const char *env;
env = getenv("VKD3D_DESCRIPTOR_QA_LOG");
if (env)
{
INFO("Enabling VKD3D_DESCRIPTOR_QA_LOG\n");
descriptor_debug_file = fopen(env, "w");
if (!descriptor_debug_file)
ERR("Failed to open file: %s.\n", env);
else
descriptor_debug_active = true;
descriptor_debug_active_log = true;
}
if (vkd3d_config_flags & VKD3D_CONFIG_FLAG_DESCRIPTOR_QA_CHECKS)
{
INFO("Enabling descriptor QA checks!\n");
descriptor_debug_active_qa_checks = true;
}
}
@ -47,9 +101,196 @@ void vkd3d_descriptor_debug_init(void)
pthread_once(&debug_once, vkd3d_descriptor_debug_init_once);
}
bool vkd3d_descriptor_debug_active(void)
bool vkd3d_descriptor_debug_active_log(void)
{
return descriptor_debug_active;
return descriptor_debug_active_log;
}
bool vkd3d_descriptor_debug_active_qa_checks(void)
{
return descriptor_debug_active_qa_checks;
}
VkDeviceSize vkd3d_descriptor_debug_heap_info_size(unsigned int num_descriptors)
{
return offsetof(struct vkd3d_descriptor_qa_heap_buffer_data, desc) + num_descriptors *
sizeof(struct vkd3d_descriptor_qa_cookie_descriptor);
}
static void vkd3d_descriptor_debug_set_live_status_bit(
struct vkd3d_descriptor_qa_global_info *global_info, uint64_t cookie)
{
if (!global_info || !global_info->active || !global_info->data)
return;
if (cookie < global_info->num_cookies)
{
vkd3d_atomic_uint32_or(&global_info->data->live_status_table[cookie / 32],
1u << (cookie & 31), vkd3d_memory_order_relaxed);
}
else
INFO("Cookie index %"PRIu64" is out of range, cannot be tracked.\n", cookie);
}
static void vkd3d_descriptor_debug_unset_live_status_bit(
struct vkd3d_descriptor_qa_global_info *global_info, uint64_t cookie)
{
if (!global_info || !global_info->active || !global_info->data)
return;
if (cookie < global_info->num_cookies)
{
vkd3d_atomic_uint32_and(&global_info->data->live_status_table[cookie / 32],
~(1u << (cookie & 31)), vkd3d_memory_order_relaxed);
}
}
static void vkd3d_descriptor_debug_qa_check_report_fault(
struct vkd3d_descriptor_qa_global_info *global_info);
static void *vkd3d_descriptor_debug_qa_check_entry(void *userdata)
{
struct vkd3d_descriptor_qa_global_info *global_info = userdata;
bool active = true;
while (active)
{
/* Don't spin endlessly, this thread is kicked after a successful fence wait. */
pthread_mutex_lock(&global_info->ring_lock);
pthread_cond_wait(&global_info->ring_cond, &global_info->ring_lock);
active = global_info->active;
pthread_mutex_unlock(&global_info->ring_lock);
if (global_info->data->fault_type != 0)
{
vkd3d_descriptor_debug_qa_check_report_fault(global_info);
ERR("Num failed checks: %u\n", global_info->data->fault_atomic);
/* Reset the latch so we can get more reports. */
vkd3d_atomic_uint32_store_explicit(&global_info->data->fault_type, 0, vkd3d_memory_order_relaxed);
vkd3d_atomic_uint32_store_explicit(&global_info->data->fault_atomic, 0, vkd3d_memory_order_release);
}
}
return NULL;
}
void vkd3d_descriptor_debug_kick_qa_check(struct vkd3d_descriptor_qa_global_info *global_info)
{
if (global_info && global_info->active)
pthread_cond_signal(&global_info->ring_cond);
}
const VkDescriptorBufferInfo *vkd3d_descriptor_debug_get_global_info_descriptor(
struct vkd3d_descriptor_qa_global_info *global_info)
{
if (global_info)
return &global_info->descriptor;
else
return NULL;
}
HRESULT vkd3d_descriptor_debug_alloc_global_info(
struct vkd3d_descriptor_qa_global_info **out_global_info, unsigned int num_cookies,
struct d3d12_device *device)
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
struct vkd3d_descriptor_qa_global_info *global_info;
D3D12_RESOURCE_DESC buffer_desc;
D3D12_HEAP_PROPERTIES heap_info;
D3D12_HEAP_FLAGS heap_flags;
VkResult vr;
HRESULT hr;
global_info = vkd3d_calloc(1, sizeof(*global_info));
if (!global_info)
return E_OUTOFMEMORY;
memset(&buffer_desc, 0, sizeof(buffer_desc));
buffer_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
buffer_desc.Width = sizeof(uint32_t) * ((num_cookies + 31) / 32) +
offsetof(struct vkd3d_descriptor_qa_global_buffer_data, live_status_table);
buffer_desc.Height = 1;
buffer_desc.DepthOrArraySize = 1;
buffer_desc.MipLevels = 1;
buffer_desc.SampleDesc.Count = 1;
buffer_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
buffer_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
/* host-visible device memory */
memset(&heap_info, 0, sizeof(heap_info));
heap_info.Type = D3D12_HEAP_TYPE_UPLOAD;
heap_flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;
if (FAILED(hr = vkd3d_create_buffer(device, &heap_info, heap_flags, &buffer_desc, &global_info->vk_buffer)))
{
vkd3d_descriptor_debug_free_global_info(global_info, device);
return hr;
}
if (FAILED(hr = vkd3d_allocate_buffer_memory(device, global_info->vk_buffer,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
&global_info->vk_memory)))
{
vkd3d_descriptor_debug_free_global_info(global_info, device);
return hr;
}
if ((vr = VK_CALL(vkMapMemory(device->vk_device, global_info->vk_memory,
0, VK_WHOLE_SIZE, 0, (void**)&global_info->data))))
{
ERR("Failed to map buffer, vr %d.\n", vr);
vkd3d_descriptor_debug_free_global_info(global_info, device);
return hresult_from_vk_result(vr);
}
memset(global_info->data, 0, buffer_desc.Width);
/* The NULL descriptor has cookie 0, and is always considered live. */
global_info->data->live_status_table[0] = 1u << 0;
global_info->descriptor.buffer = global_info->vk_buffer;
global_info->descriptor.offset = 0;
global_info->descriptor.range = buffer_desc.Width;
global_info->num_cookies = num_cookies;
pthread_mutex_init(&global_info->ring_lock, NULL);
pthread_cond_init(&global_info->ring_cond, NULL);
global_info->active = true;
if (pthread_create(&global_info->ring_thread, NULL, vkd3d_descriptor_debug_qa_check_entry, global_info) != 0)
{
vkd3d_descriptor_debug_free_global_info(global_info, device);
return E_OUTOFMEMORY;
}
*out_global_info = global_info;
return S_OK;
}
void vkd3d_descriptor_debug_free_global_info(
struct vkd3d_descriptor_qa_global_info *global_info,
struct d3d12_device *device)
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
if (!global_info)
return;
if (global_info->active)
{
pthread_mutex_lock(&global_info->ring_lock);
global_info->active = false;
pthread_cond_signal(&global_info->ring_cond);
pthread_mutex_unlock(&global_info->ring_lock);
pthread_join(global_info->ring_thread, NULL);
pthread_mutex_destroy(&global_info->ring_lock);
pthread_cond_destroy(&global_info->ring_cond);
}
VK_CALL(vkFreeMemory(device->vk_device, global_info->vk_memory, NULL));
VK_CALL(vkDestroyBuffer(device->vk_device, global_info->vk_buffer, NULL));
vkd3d_free(global_info);
}
#define DECL_BUFFER() \
@ -67,13 +308,52 @@ bool vkd3d_descriptor_debug_active(void)
#define APPEND_SNPRINTF(...) do { ptr += strlen(ptr); snprintf(ptr, (buffer + ARRAY_SIZE(buffer)) - ptr, __VA_ARGS__); } while(0)
void vkd3d_descriptor_debug_register_heap(void *heap, const D3D12_DESCRIPTOR_HEAP_DESC *desc)
static void vkd3d_descriptor_debug_qa_check_report_fault(
struct vkd3d_descriptor_qa_global_info *global_info)
{
DECL_BUFFER();
if (!vkd3d_descriptor_debug_active())
if (global_info->data->fault_type & VKD3D_DESCRIPTOR_FAULT_TYPE_HEAP_OF_OF_RANGE)
APPEND_SNPRINTF("Fault type: HEAP_OUT_OF_RANGE\n");
if (global_info->data->fault_type & VKD3D_DESCRIPTOR_FAULT_TYPE_MISMATCH_DESCRIPTOR_TYPE)
APPEND_SNPRINTF("Fault type: MISMATCH_DESCRIPTOR_TYPE\n");
if (global_info->data->fault_type & VKD3D_DESCRIPTOR_FAULT_TYPE_DESTROYED_RESOURCE)
APPEND_SNPRINTF("Fault type: DESTROYED_RESOURCE\n");
APPEND_SNPRINTF("CBV_SRV_UAV heap cookie: %u\n", global_info->data->failed_heap);
APPEND_SNPRINTF("Shader hash and instruction: %"PRIx64" (%u)\n",
global_info->data->failed_hash, global_info->data->failed_instruction);
APPEND_SNPRINTF("Accessed resource/view cookie: %u\n", global_info->data->failed_cookie);
APPEND_SNPRINTF("Shader desired descriptor type: %u (%s)\n",
global_info->data->failed_descriptor_type_mask,
debug_descriptor_type(global_info->data->failed_descriptor_type_mask));
APPEND_SNPRINTF("Found descriptor type in heap: %u (%s)\n",
global_info->data->actual_descriptor_type_mask,
debug_descriptor_type(global_info->data->actual_descriptor_type_mask));
APPEND_SNPRINTF("Failed heap index: %u\n", global_info->data->failed_offset);
ERR("\n============\n%s==========\n", buffer);
if (!vkd3d_descriptor_debug_active_log())
return;
FLUSH_BUFFER();
}
void vkd3d_descriptor_debug_register_heap(
struct vkd3d_descriptor_qa_heap_buffer_data *heap, uint64_t cookie,
const D3D12_DESCRIPTOR_HEAP_DESC *desc)
{
DECL_BUFFER();
if (heap)
{
heap->num_descriptors = desc->NumDescriptors;
heap->heap_index = cookie <= UINT32_MAX ? (uint32_t)cookie : 0u;
memset(heap->desc, 0, desc->NumDescriptors * sizeof(*heap->desc));
}
if (!vkd3d_descriptor_debug_active_log())
return;
APPEND_SNPRINTF("REGISTER HEAP %p || COUNT = %u", heap, desc->NumDescriptors);
APPEND_SNPRINTF("REGISTER HEAP %"PRIu64" || COUNT = %u", cookie, desc->NumDescriptors);
if (desc->Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE)
APPEND_SNPRINTF(" || SHADER");
@ -103,21 +383,25 @@ void vkd3d_descriptor_debug_register_heap(void *heap, const D3D12_DESCRIPTOR_HEA
FLUSH_BUFFER();
}
void vkd3d_descriptor_debug_unregister_heap(void *heap)
void vkd3d_descriptor_debug_unregister_heap(uint64_t cookie)
{
DECL_BUFFER();
if (!vkd3d_descriptor_debug_active())
if (!vkd3d_descriptor_debug_active_log())
return;
APPEND_SNPRINTF("DESTROY HEAP %p", heap);
APPEND_SNPRINTF("DESTROY HEAP %"PRIu64, cookie);
FLUSH_BUFFER();
}
void vkd3d_descriptor_debug_register_resource_cookie(uint64_t cookie, const D3D12_RESOURCE_DESC *desc)
void vkd3d_descriptor_debug_register_resource_cookie(struct vkd3d_descriptor_qa_global_info *global_info,
uint64_t cookie, const D3D12_RESOURCE_DESC *desc)
{
const char *fmt;
DECL_BUFFER();
if (!vkd3d_descriptor_debug_active())
vkd3d_descriptor_debug_set_live_status_bit(global_info, cookie);
if (!vkd3d_descriptor_debug_active_log())
return;
APPEND_SNPRINTF("RESOURCE CREATE #%"PRIu64" || ", cookie);
@ -164,67 +448,82 @@ void vkd3d_descriptor_debug_register_resource_cookie(uint64_t cookie, const D3D1
FLUSH_BUFFER();
}
void vkd3d_descriptor_debug_register_allocation_cookie(uint64_t cookie, const struct vkd3d_allocate_memory_info *info)
void vkd3d_descriptor_debug_register_allocation_cookie(
struct vkd3d_descriptor_qa_global_info *global_info,
uint64_t cookie, const struct vkd3d_allocate_memory_info *info)
{
D3D12_RESOURCE_DESC desc;
memset(&desc, 0, sizeof(desc));
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
desc.Width = info->memory_requirements.size;
vkd3d_descriptor_debug_register_resource_cookie(cookie, &desc);
vkd3d_descriptor_debug_register_resource_cookie(global_info, cookie, &desc);
}
void vkd3d_descriptor_debug_register_view_cookie(uint64_t cookie, uint64_t resource_cookie)
void vkd3d_descriptor_debug_register_view_cookie(
struct vkd3d_descriptor_qa_global_info *global_info,
uint64_t cookie, uint64_t resource_cookie)
{
DECL_BUFFER();
if (!vkd3d_descriptor_debug_active())
vkd3d_descriptor_debug_set_live_status_bit(global_info, cookie);
if (!vkd3d_descriptor_debug_active_log())
return;
APPEND_SNPRINTF("VIEW CREATE #%"PRIu64" <- RESOURCE #%"PRIu64, cookie, resource_cookie);
FLUSH_BUFFER();
}
void vkd3d_descriptor_debug_unregister_cookie(uint64_t cookie)
void vkd3d_descriptor_debug_unregister_cookie(
struct vkd3d_descriptor_qa_global_info *global_info,
uint64_t cookie)
{
DECL_BUFFER();
if (!vkd3d_descriptor_debug_active())
/* Don't unset the null descriptor by mistake. */
if (cookie != 0)
vkd3d_descriptor_debug_unset_live_status_bit(global_info, cookie);
if (!vkd3d_descriptor_debug_active_log())
return;
APPEND_SNPRINTF("COOKIE DESTROY #%"PRIu64, cookie);
FLUSH_BUFFER();
}
static const char *debug_descriptor_type(VkDescriptorType type)
void vkd3d_descriptor_debug_write_descriptor(struct vkd3d_descriptor_qa_heap_buffer_data *heap, uint64_t heap_cookie,
uint32_t offset, vkd3d_descriptor_qa_flags type_flags, uint64_t cookie)
{
switch (type)
DECL_BUFFER();
if (heap && offset < heap->num_descriptors)
{
case VK_DESCRIPTOR_TYPE_SAMPLER: return "SAMPLER";
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: return "SAMPLED_IMAGE";
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: return "STORAGE_IMAGE";
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: return "UNIFORM_BUFFER";
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: return "STORAGE_BUFFER";
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: return "UNIFORM_TEXEL_BUFFER";
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: return "STORAGE_TEXEL_BUFFER";
default: return "?";
/* Should never overflow here except if game is literally spamming allocations every frame and we
* wait around for hours/days.
* This case will trigger warnings either way. */
heap->desc[offset].cookie = cookie <= UINT32_MAX ? (uint32_t)cookie : 0u;
heap->desc[offset].descriptor_type = type_flags;
}
}
void vkd3d_descriptor_debug_write_descriptor(void *heap, uint32_t offset, VkDescriptorType type, uint64_t cookie)
{
DECL_BUFFER();
if (!vkd3d_descriptor_debug_active())
if (!vkd3d_descriptor_debug_active_log())
return;
APPEND_SNPRINTF("WRITE %p || OFFSET = %u || TYPE = %s || COOKIE = #%"PRIu64,
heap, offset, debug_descriptor_type(type), cookie);
APPEND_SNPRINTF("WRITE HEAP %"PRIu64" || OFFSET = %u || TYPE = %s || COOKIE = #%"PRIu64,
heap_cookie, offset, debug_descriptor_type(type_flags), cookie);
FLUSH_BUFFER();
}
void vkd3d_descriptor_debug_copy_descriptor(void *dst_heap, uint32_t dst_offset,
void *src_heap, uint32_t src_offset,
uint64_t cookie)
void vkd3d_descriptor_debug_copy_descriptor(
struct vkd3d_descriptor_qa_heap_buffer_data *dst_heap, uint64_t dst_heap_cookie, uint32_t dst_offset,
struct vkd3d_descriptor_qa_heap_buffer_data *src_heap, uint64_t src_heap_cookie, uint32_t src_offset,
uint64_t cookie)
{
DECL_BUFFER();
if (!vkd3d_descriptor_debug_active())
if (dst_heap && src_heap && dst_offset < dst_heap->num_descriptors && src_offset < src_heap->num_descriptors)
dst_heap->desc[dst_offset] = src_heap->desc[src_offset];
if (!vkd3d_descriptor_debug_active_log())
return;
APPEND_SNPRINTF("COPY %p || DST OFFSET = %u || COOKIE = #%"PRIu64" || SRC %p || SRC OFFSET = %u",
dst_heap, dst_offset, cookie, src_heap, src_offset);
APPEND_SNPRINTF("COPY DST HEAP %"PRIu64" || DST OFFSET = %u || COOKIE = #%"PRIu64" || SRC HEAP %"PRIu64" || SRC OFFSET = %u",
dst_heap_cookie, dst_offset, cookie, src_heap_cookie, src_offset);
FLUSH_BUFFER();
}

View File

@ -20,15 +20,12 @@
#include "vkd3d_private.h"
#include "vkd3d_sonames.h"
#include "vkd3d_descriptor_debug.h"
#ifdef VKD3D_ENABLE_RENDERDOC
#include "vkd3d_renderdoc.h"
#endif
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
#include "vkd3d_descriptor_debug.h"
#endif
static uint32_t vkd3d_get_vk_version(void)
{
int major, minor, patch;
@ -2416,6 +2413,8 @@ static void d3d12_device_destroy(struct d3d12_device *device)
vkd3d_render_pass_cache_cleanup(&device->render_pass_cache, device);
d3d12_device_destroy_vkd3d_queues(device);
vkd3d_memory_allocator_cleanup(&device->memory_allocator, device);
/* Tear down descriptor global info late, so we catch last minute faults after we drain the queues. */
vkd3d_descriptor_debug_free_global_info(device->descriptor_qa_global_info, device);
VK_CALL(vkDestroyDevice(device->vk_device, NULL));
pthread_mutex_destroy(&device->mutex);
if (device->parent)
@ -5050,6 +5049,13 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
if (FAILED(hr = vkd3d_shader_debug_ring_init(&device->debug_ring, device)))
goto out_cleanup_meta_ops;
if (vkd3d_descriptor_debug_active_qa_checks())
{
if (FAILED(hr = vkd3d_descriptor_debug_alloc_global_info(&device->descriptor_qa_global_info,
VKD3D_DESCRIPTOR_DEBUG_DEFAULT_NUM_COOKIES, device)))
goto out_cleanup_debug_ring;
}
vkd3d_render_pass_cache_init(&device->render_pass_cache);
if ((device->parent = create_info->parent))
@ -5058,6 +5064,8 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
d3d12_device_caps_init(device);
return S_OK;
out_cleanup_debug_ring:
vkd3d_shader_debug_ring_cleanup(&device->debug_ring, device);
out_cleanup_meta_ops:
vkd3d_meta_ops_cleanup(&device->meta_ops, device);
out_cleanup_sampler_state:

View File

@ -19,10 +19,7 @@
#define VKD3D_DBG_CHANNEL VKD3D_DBG_CHANNEL_API
#include "vkd3d_private.h"
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
#include "vkd3d_descriptor_debug.h"
#endif
static void vkd3d_memory_allocator_wait_allocation(struct vkd3d_memory_allocator *allocator,
struct d3d12_device *device, const struct vkd3d_memory_allocation *allocation);
@ -334,9 +331,7 @@ static void vkd3d_memory_allocation_free(const struct vkd3d_memory_allocation *a
TRACE("allocation %p, device %p, allocator %p.\n", allocation, device, allocator);
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
vkd3d_descriptor_debug_unregister_cookie(allocation->resource.cookie);
#endif
vkd3d_descriptor_debug_unregister_cookie(device->descriptor_qa_global_info, allocation->resource.cookie);
if (allocation->flags & VKD3D_ALLOCATION_FLAG_ALLOW_WRITE_WATCH)
vkd3d_free_write_watch_pointer(allocation->cpu_address);
@ -493,9 +488,8 @@ static HRESULT vkd3d_memory_allocation_init(struct vkd3d_memory_allocation *allo
}
allocation->resource.cookie = vkd3d_allocate_cookie();
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
vkd3d_descriptor_debug_register_allocation_cookie(allocation->resource.cookie, info);
#endif
vkd3d_descriptor_debug_register_allocation_cookie(device->descriptor_qa_global_info,
allocation->resource.cookie, info);
TRACE("Created allocation %p on memory type %u (%"PRIu64" bytes).\n",
allocation, allocation->vk_memory_type, allocation->resource.size);

View File

@ -890,6 +890,10 @@ static HRESULT d3d12_state_object_compile_pipeline(struct d3d12_state_object *ob
shader_interface_info.push_constant_buffer_count = global_signature->root_constant_count;
shader_interface_info.push_constant_ubo_binding = &global_signature->push_constant_ubo_binding;
shader_interface_info.offset_buffer_binding = &global_signature->offset_buffer_binding;
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
shader_interface_info.descriptor_qa_global_binding = &global_signature->descriptor_qa_global_info;
shader_interface_info.descriptor_qa_heap_binding = &global_signature->descriptor_qa_heap_binding;
#endif
}
shader_interface_local_info.descriptor_size = sizeof(struct d3d12_desc);

View File

@ -23,11 +23,8 @@
#include "vkd3d_private.h"
#include "vkd3d_rw_spinlock.h"
#include "hashmap.h"
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
#include "vkd3d_descriptor_debug.h"
#endif
#include "hashmap.h"
#define VKD3D_NULL_SRV_FORMAT DXGI_FORMAT_R8G8B8A8_UNORM
#define VKD3D_NULL_UAV_FORMAT DXGI_FORMAT_R32_UINT
@ -822,9 +819,8 @@ struct vkd3d_view *vkd3d_view_map_create_view(struct vkd3d_view_map *view_map,
if (!success)
return NULL;
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
vkd3d_descriptor_debug_register_view_cookie(view->cookie, view_map->resource_cookie);
#endif
vkd3d_descriptor_debug_register_view_cookie(device->descriptor_qa_global_info,
view->cookie, view_map->resource_cookie);
entry.key = *key;
entry.view = view;
@ -2264,9 +2260,7 @@ static void d3d12_resource_destroy(struct d3d12_resource *resource, struct d3d12
vkd3d_view_map_destroy(&resource->view_map, resource->device);
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
vkd3d_descriptor_debug_unregister_cookie(resource->res.cookie);
#endif
vkd3d_descriptor_debug_unregister_cookie(device->descriptor_qa_global_info, resource->res.cookie);
if (resource->flags & VKD3D_RESOURCE_EXTERNAL)
return;
@ -2370,6 +2364,9 @@ static HRESULT d3d12_resource_create(struct d3d12_device *device, uint32_t flags
object->flags = flags;
object->format = vkd3d_format_from_d3d12_resource_desc(device, desc, 0);
object->res.cookie = vkd3d_allocate_cookie();
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
object->view_map.resource_cookie = object->res.cookie;
#endif
/* RTAS are "special" buffers. They can never transition out of this state. */
if (initial_state == D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE)
@ -2381,9 +2378,8 @@ static HRESULT d3d12_resource_create(struct d3d12_device *device, uint32_t flags
d3d12_device_add_ref(device);
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
vkd3d_descriptor_debug_register_resource_cookie(object->res.cookie, desc);
#endif
vkd3d_descriptor_debug_register_resource_cookie(device->descriptor_qa_global_info,
object->res.cookie, desc);
*resource = object;
return S_OK;
@ -2723,9 +2719,7 @@ static void vkd3d_view_destroy(struct vkd3d_view *view, struct d3d12_device *dev
TRACE("Destroying view %p.\n", view);
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
vkd3d_descriptor_debug_unregister_cookie(view->cookie);
#endif
vkd3d_descriptor_debug_unregister_cookie(device->descriptor_qa_global_info, view->cookie);
switch (view->type)
{
@ -2932,8 +2926,8 @@ void d3d12_desc_copy(struct d3d12_desc *dst, struct d3d12_desc *src,
for (i = 0; i < count; i++)
{
vkd3d_descriptor_debug_copy_descriptor(
dst[i].heap, dst[i].heap_offset,
src[i].heap, src[i].heap_offset,
dst[i].heap->descriptor_heap_info.host_ptr, dst[i].heap->cookie, dst[i].heap_offset,
src[i].heap->descriptor_heap_info.host_ptr, src[i].heap->cookie, src[i].heap_offset,
src[i].metadata.cookie);
}
#endif
@ -3449,9 +3443,10 @@ void d3d12_desc_create_cbv(struct d3d12_desc *descriptor,
vkd3d_bindless_state_binding_from_info_index(&device->bindless_state, info_index),
vk_descriptor_type, &descriptor_info);
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
vkd3d_descriptor_debug_write_descriptor(descriptor->heap, descriptor->heap_offset, vk_write.descriptorType, descriptor->metadata.cookie);
#endif
vkd3d_descriptor_debug_write_descriptor(descriptor->heap->descriptor_heap_info.host_ptr,
descriptor->heap->cookie,
descriptor->heap_offset,
VKD3D_DESCRIPTOR_QA_TYPE_UNIFORM_BUFFER_BIT, descriptor->metadata.cookie);
VK_CALL(vkUpdateDescriptorSets(device->vk_device, 1, &vk_write, 0, NULL));
}
@ -3586,6 +3581,7 @@ static void vkd3d_create_buffer_srv(struct d3d12_desc *descriptor,
{
struct vkd3d_null_resources *null_resources = &device->null_resources;
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
VKD3D_UNUSED vkd3d_descriptor_qa_flags descriptor_qa_flags = 0;
struct vkd3d_bound_buffer_range bound_range = { 0, 0, 0, 0 };
union vkd3d_descriptor_info descriptor_info[2];
VkDescriptorType vk_descriptor_type;
@ -3617,6 +3613,11 @@ static void vkd3d_create_buffer_srv(struct d3d12_desc *descriptor,
else
WARN("Using CreateSRV for RTAS without RT support?\n");
vkd3d_descriptor_debug_write_descriptor(descriptor->heap->descriptor_heap_info.host_ptr,
descriptor->heap->cookie, descriptor->heap_offset,
VKD3D_DESCRIPTOR_QA_TYPE_RT_ACCELERATION_STRUCTURE_BIT | VKD3D_DESCRIPTOR_QA_TYPE_RAW_VA_BIT,
descriptor->metadata.cookie);
return;
}
@ -3651,6 +3652,7 @@ static void vkd3d_create_buffer_srv(struct d3d12_desc *descriptor,
descriptor->metadata.flags |= VKD3D_DESCRIPTOR_FLAG_BUFFER_OFFSET;
vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
descriptor_qa_flags |= VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_BUFFER_BIT;
vkd3d_init_write_descriptor_set(&vk_write[vk_write_count], descriptor,
vkd3d_bindless_state_binding_from_info_index(&device->bindless_state, info_index),
vk_descriptor_type, &descriptor_info[vk_write_count]);
@ -3694,6 +3696,7 @@ static void vkd3d_create_buffer_srv(struct d3d12_desc *descriptor,
descriptor->metadata.flags |= VKD3D_DESCRIPTOR_FLAG_BUFFER_OFFSET;
vk_descriptor_type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
descriptor_qa_flags |= VKD3D_DESCRIPTOR_QA_TYPE_UNIFORM_TEXEL_BUFFER_BIT;
vkd3d_init_write_descriptor_set(&vk_write[vk_write_count], descriptor,
vkd3d_bindless_state_binding_from_info_index(&device->bindless_state, info_index),
@ -3706,9 +3709,8 @@ static void vkd3d_create_buffer_srv(struct d3d12_desc *descriptor,
buffer_ranges[descriptor->heap_offset] = bound_range;
}
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
vkd3d_descriptor_debug_write_descriptor(descriptor->heap, descriptor->heap_offset, vk_descriptor_type, descriptor->metadata.cookie);
#endif
vkd3d_descriptor_debug_write_descriptor(descriptor->heap->descriptor_heap_info.host_ptr,
descriptor->heap->cookie, descriptor->heap_offset, descriptor_qa_flags, descriptor->metadata.cookie);
if (vk_write_count)
VK_CALL(vkUpdateDescriptorSets(device->vk_device, vk_write_count, vk_write, 0, NULL));
@ -3876,9 +3878,9 @@ static void vkd3d_create_texture_srv(struct d3d12_desc *descriptor,
vkd3d_bindless_state_binding_from_info_index(&device->bindless_state, info_index),
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &descriptor_info);
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
vkd3d_descriptor_debug_write_descriptor(descriptor->heap, descriptor->heap_offset, vk_write.descriptorType, descriptor->metadata.cookie);
#endif
vkd3d_descriptor_debug_write_descriptor(descriptor->heap->descriptor_heap_info.host_ptr,
descriptor->heap->cookie, descriptor->heap_offset,
VKD3D_DESCRIPTOR_QA_TYPE_SAMPLED_IMAGE_BIT, descriptor->metadata.cookie);
VK_CALL(vkUpdateDescriptorSets(device->vk_device, 1, &vk_write, 0, NULL));
}
@ -3950,6 +3952,7 @@ static void vkd3d_create_buffer_uav(struct d3d12_desc *descriptor, struct d3d12_
{
struct vkd3d_null_resources *null_resources = &device->null_resources;
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
VKD3D_UNUSED vkd3d_descriptor_qa_flags descriptor_qa_flags = 0;
struct vkd3d_bound_buffer_range bound_range = { 0, 0, 0, 0 };
union vkd3d_descriptor_info descriptor_info[3];
unsigned int flags, vk_write_count = 0;
@ -4003,6 +4006,7 @@ static void vkd3d_create_buffer_uav(struct d3d12_desc *descriptor, struct d3d12_
descriptor->metadata.flags |= VKD3D_DESCRIPTOR_FLAG_BUFFER_OFFSET;
vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
descriptor_qa_flags |= VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_BUFFER_BIT;
vkd3d_init_write_descriptor_set(&vk_write[vk_write_count], descriptor,
vkd3d_bindless_state_binding_from_info_index(&device->bindless_state, info_index),
@ -4046,6 +4050,7 @@ static void vkd3d_create_buffer_uav(struct d3d12_desc *descriptor, struct d3d12_
descriptor_info[vk_write_count].buffer_view = view ? view->vk_buffer_view : VK_NULL_HANDLE;
vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
descriptor_qa_flags |= VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_TEXEL_BUFFER_BIT;
vkd3d_init_write_descriptor_set(&vk_write[vk_write_count], descriptor,
vkd3d_bindless_state_binding_from_info_index(&device->bindless_state, info_index),
@ -4058,10 +4063,6 @@ static void vkd3d_create_buffer_uav(struct d3d12_desc *descriptor, struct d3d12_
buffer_ranges[descriptor->heap_offset] = bound_range;
}
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
vkd3d_descriptor_debug_write_descriptor(descriptor->heap, descriptor->heap_offset, vk_descriptor_type, descriptor->metadata.cookie);
#endif
/* Handle UAV counter */
uav_counter_view = VK_NULL_HANDLE;
uav_counter_address = 0;
@ -4086,6 +4087,9 @@ static void vkd3d_create_buffer_uav(struct d3d12_desc *descriptor, struct d3d12_
uav_counter_view = view->vk_buffer_view;
}
/* This is used to denote that a counter descriptor is present, irrespective of underlying descriptor type. */
descriptor_qa_flags |= VKD3D_DESCRIPTOR_QA_TYPE_RAW_VA_BIT;
}
else if (!device->device_info.robustness2_features.nullDescriptor)
uav_counter_view = device->null_resources.vk_storage_buffer_view;
@ -4108,6 +4112,10 @@ static void vkd3d_create_buffer_uav(struct d3d12_desc *descriptor, struct d3d12_
vk_write_count++;
}
vkd3d_descriptor_debug_write_descriptor(descriptor->heap->descriptor_heap_info.host_ptr,
descriptor->heap->cookie, descriptor->heap_offset,
descriptor_qa_flags, descriptor->metadata.cookie);
VK_CALL(vkUpdateDescriptorSets(device->vk_device, vk_write_count, vk_write, 0, NULL));
}
@ -4236,9 +4244,9 @@ static void vkd3d_create_texture_uav(struct d3d12_desc *descriptor,
vkd3d_bindless_state_binding_from_info_index(&device->bindless_state, info_index),
VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptor_info);
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
vkd3d_descriptor_debug_write_descriptor(descriptor->heap, descriptor->heap_offset, vk_write.descriptorType, descriptor->metadata.cookie);
#endif
vkd3d_descriptor_debug_write_descriptor(descriptor->heap->descriptor_heap_info.host_ptr,
descriptor->heap->cookie, descriptor->heap_offset,
VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_IMAGE_BIT, descriptor->metadata.cookie);
VK_CALL(vkUpdateDescriptorSets(device->vk_device, 1, &vk_write, 0, NULL));
}
@ -4528,9 +4536,7 @@ void d3d12_desc_create_sampler(struct d3d12_desc *sampler,
if (!(view = vkd3d_view_map_create_view(&device->sampler_map, device, &key)))
return;
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
vkd3d_descriptor_debug_register_view_cookie(view->cookie, 0);
#endif
vkd3d_descriptor_debug_register_view_cookie(device->descriptor_qa_global_info, view->cookie, 0);
info_index = vkd3d_bindless_state_find_set_info_index(&device->bindless_state, VKD3D_BINDLESS_SET_SAMPLER);
@ -4547,9 +4553,9 @@ void d3d12_desc_create_sampler(struct d3d12_desc *sampler,
vkd3d_bindless_state_binding_from_info_index(&device->bindless_state, info_index),
VK_DESCRIPTOR_TYPE_SAMPLER, &descriptor_info);
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
vkd3d_descriptor_debug_write_descriptor(sampler->heap, sampler->heap_offset, vk_write.descriptorType, sampler->metadata.cookie);
#endif
vkd3d_descriptor_debug_write_descriptor(sampler->heap->descriptor_heap_info.host_ptr,
sampler->heap->cookie, sampler->heap_offset,
VKD3D_DESCRIPTOR_QA_TYPE_SAMPLER_BIT, sampler->metadata.cookie);
VK_CALL(vkUpdateDescriptorSets(device->vk_device, 1, &vk_write, 0, NULL));
}
@ -4651,9 +4657,7 @@ void d3d12_rtv_desc_create_rtv(struct d3d12_rtv_desc *rtv_desc, struct d3d12_dev
if (!(view = vkd3d_view_map_create_view(&resource->view_map, device, &key)))
return;
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
vkd3d_descriptor_debug_register_view_cookie(view->cookie, resource->res.cookie);
#endif
vkd3d_descriptor_debug_register_view_cookie(device->descriptor_qa_global_info, view->cookie, resource->res.cookie);
rtv_desc->sample_count = vk_samples_from_dxgi_sample_desc(&resource->desc.SampleDesc);
rtv_desc->format = key.u.texture.format;
@ -4765,9 +4769,7 @@ void d3d12_rtv_desc_create_dsv(struct d3d12_rtv_desc *dsv_desc, struct d3d12_dev
if (!(view = vkd3d_view_map_create_view(&resource->view_map, device, &key)))
return;
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
vkd3d_descriptor_debug_register_view_cookie(view->cookie, resource->res.cookie);
#endif
vkd3d_descriptor_debug_register_view_cookie(device->descriptor_qa_global_info, view->cookie, resource->res.cookie);
dsv_desc->sample_count = vk_samples_from_dxgi_sample_desc(&resource->desc.SampleDesc);
dsv_desc->format = key.u.texture.format;
@ -4961,6 +4963,12 @@ static HRESULT d3d12_descriptor_heap_create_descriptor_pool(struct d3d12_descrip
vk_pool_size->type = set_info->vk_descriptor_type;
vk_pool_size->descriptorCount = descriptor_heap->desc.NumDescriptors;
if (vkd3d_descriptor_debug_active_qa_checks() &&
descriptor_heap->desc.Type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)
{
vk_pool_size->descriptorCount += VKD3D_DESCRIPTOR_DEBUG_NUM_PAD_DESCRIPTORS;
}
if (set_info->vk_descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
ssbo_pool = vk_pool_size;
}
@ -5076,6 +5084,9 @@ static HRESULT d3d12_descriptor_heap_create_descriptor_set(struct d3d12_descript
VkDescriptorSetAllocateInfo vk_set_info;
VkResult vr;
if (vkd3d_descriptor_debug_active_qa_checks() && descriptor_heap->desc.Type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)
descriptor_count += VKD3D_DESCRIPTOR_DEBUG_NUM_PAD_DESCRIPTORS;
vk_variable_count_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT;
vk_variable_count_info.pNext = NULL;
vk_variable_count_info.descriptorSetCount = 1;
@ -5135,6 +5146,7 @@ static HRESULT d3d12_descriptor_heap_init_data_buffer(struct d3d12_descriptor_he
VkDeviceSize alignment = max(device->device_info.properties2.properties.limits.minStorageBufferOffsetAlignment,
device->device_info.properties2.properties.limits.nonCoherentAtomSize);
VkDeviceSize raw_va_buffer_size = 0, offset_buffer_size = 0;
VKD3D_UNUSED VkDeviceSize descriptor_heap_info_size = 0;
VkDeviceSize buffer_size, offset;
D3D12_HEAP_PROPERTIES heap_info;
D3D12_RESOURCE_DESC buffer_desc;
@ -5142,16 +5154,25 @@ static HRESULT d3d12_descriptor_heap_init_data_buffer(struct d3d12_descriptor_he
VkResult vr;
HRESULT hr;
if (desc->Type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)
{
if (device->bindless_state.flags & VKD3D_RAW_VA_AUX_BUFFER)
{
raw_va_buffer_size = align(desc->NumDescriptors * sizeof(VkDeviceAddress), alignment);
if (vkd3d_descriptor_debug_active_qa_checks())
raw_va_buffer_size += align(VKD3D_DESCRIPTOR_DEBUG_NUM_PAD_DESCRIPTORS * sizeof(VkDeviceAddress), alignment);
}
if (device->bindless_state.flags & (VKD3D_SSBO_OFFSET_BUFFER | VKD3D_TYPED_OFFSET_BUFFER))
offset_buffer_size = align(desc->NumDescriptors * sizeof(struct vkd3d_bound_buffer_range), alignment);
if (vkd3d_descriptor_debug_active_qa_checks())
descriptor_heap_info_size = align(vkd3d_descriptor_debug_heap_info_size(desc->NumDescriptors), alignment);
}
buffer_size = raw_va_buffer_size + offset_buffer_size;
buffer_size += descriptor_heap_info_size;
if (!buffer_size)
return S_OK;
@ -5200,6 +5221,11 @@ static HRESULT d3d12_descriptor_heap_init_data_buffer(struct d3d12_descriptor_he
d3d12_descriptor_heap_get_buffer_range(descriptor_heap, &offset, raw_va_buffer_size, &descriptor_heap->raw_va_aux_buffer);
d3d12_descriptor_heap_get_buffer_range(descriptor_heap, &offset, offset_buffer_size, &descriptor_heap->buffer_ranges);
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
d3d12_descriptor_heap_get_buffer_range(descriptor_heap, &offset,
descriptor_heap_info_size,
&descriptor_heap->descriptor_heap_info);
#endif
return S_OK;
}
@ -5249,8 +5275,18 @@ static void d3d12_descriptor_heap_update_extra_bindings(struct d3d12_descriptor_
*vk_buffer = descriptor_heap->buffer_ranges.descriptor;
break;
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
case VKD3D_BINDLESS_SET_EXTRA_GLOBAL_HEAP_INFO_BUFFER:
*vk_buffer = *vkd3d_descriptor_debug_get_global_info_descriptor(device->descriptor_qa_global_info);
break;
case VKD3D_BINDLESS_SET_EXTRA_DESCRIPTOR_HEAP_INFO_BUFFER:
*vk_buffer = descriptor_heap->descriptor_heap_info.descriptor;
break;
#endif
default:
ERR("Unsupported etra flags %#x.\n", flag);
ERR("Unsupported extra flags %#x.\n", flag);
continue;
}
@ -5389,7 +5425,8 @@ HRESULT d3d12_descriptor_heap_create(struct d3d12_device *device,
TRACE("Created descriptor heap %p.\n", object);
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
vkd3d_descriptor_debug_register_heap(object, desc);
object->cookie = vkd3d_allocate_cookie();
vkd3d_descriptor_debug_register_heap(object->descriptor_heap_info.host_ptr, object->cookie, desc);
#endif
*descriptor_heap = object;
@ -5413,9 +5450,7 @@ void d3d12_descriptor_heap_cleanup(struct d3d12_descriptor_heap *descriptor_heap
VK_CALL(vkDestroyDescriptorPool(device->vk_device, descriptor_heap->vk_descriptor_pool, NULL));
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
vkd3d_descriptor_debug_unregister_heap(descriptor_heap);
#endif
vkd3d_descriptor_debug_unregister_heap(descriptor_heap->cookie);
}
static void d3d12_query_heap_set_name(struct d3d12_query_heap *heap, const char *name)

View File

@ -20,6 +20,7 @@
#define VKD3D_DBG_CHANNEL VKD3D_DBG_CHANNEL_API
#include "vkd3d_private.h"
#include "vkd3d_descriptor_debug.h"
#include <stdio.h>
/* ID3D12RootSignature */
@ -768,6 +769,18 @@ static void d3d12_root_signature_init_extra_bindings(struct d3d12_root_signature
VKD3D_BINDLESS_SET_EXTRA_OFFSET_BUFFER,
&root_signature->offset_buffer_binding);
}
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
if (vkd3d_descriptor_debug_active_qa_checks())
{
vkd3d_bindless_state_find_binding(&root_signature->device->bindless_state,
VKD3D_BINDLESS_SET_EXTRA_DESCRIPTOR_HEAP_INFO_BUFFER,
&root_signature->descriptor_qa_heap_binding);
vkd3d_bindless_state_find_binding(&root_signature->device->bindless_state,
VKD3D_BINDLESS_SET_EXTRA_GLOBAL_HEAP_INFO_BUFFER,
&root_signature->descriptor_qa_global_info);
}
#endif
}
static HRESULT d3d12_root_signature_init_shader_record_descriptors(
@ -1332,6 +1345,9 @@ unsigned int d3d12_root_signature_get_shader_interface_flags(const struct d3d12_
if (root_signature->device->bindless_state.flags & VKD3D_BINDLESS_CBV_AS_SSBO)
flags |= VKD3D_SHADER_INTERFACE_BINDLESS_CBV_AS_STORAGE_BUFFER;
if (vkd3d_descriptor_debug_active_qa_checks())
flags |= VKD3D_SHADER_INTERFACE_DESCRIPTOR_QA_BUFFER;
return flags;
}
@ -2156,6 +2172,10 @@ static HRESULT d3d12_pipeline_state_init_compute(struct d3d12_pipeline_state *st
shader_interface.offset_buffer_binding = &root_signature->offset_buffer_binding;
shader_interface.stage = VK_SHADER_STAGE_COMPUTE_BIT;
shader_interface.xfb_info = NULL;
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
shader_interface.descriptor_qa_global_binding = &root_signature->descriptor_qa_global_info;
shader_interface.descriptor_qa_heap_binding = &root_signature->descriptor_qa_heap_binding;
#endif
if ((hr = vkd3d_create_pipeline_cache_from_d3d12_desc(device, &desc->cached_pso, &state->vk_pso_cache)) < 0)
{
@ -3033,6 +3053,10 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
shader_interface.push_constant_buffer_count = root_signature->root_constant_count;
shader_interface.push_constant_ubo_binding = &root_signature->push_constant_ubo_binding;
shader_interface.offset_buffer_binding = &root_signature->offset_buffer_binding;
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
shader_interface.descriptor_qa_global_binding = &root_signature->descriptor_qa_global_info;
shader_interface.descriptor_qa_heap_binding = &root_signature->descriptor_qa_heap_binding;
#endif
graphics->patch_vertex_count = 0;
@ -3883,6 +3907,8 @@ static uint32_t d3d12_max_descriptor_count_from_heap_type(D3D12_DESCRIPTOR_HEAP_
switch (heap_type)
{
case D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV:
if (vkd3d_descriptor_debug_active_qa_checks())
return 1000000 + VKD3D_DESCRIPTOR_DEBUG_NUM_PAD_DESCRIPTORS;
return 1000000;
case D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER:
@ -4213,6 +4239,12 @@ HRESULT vkd3d_bindless_state_init(struct vkd3d_bindless_state *bindless_state,
if (bindless_state->flags & (VKD3D_SSBO_OFFSET_BUFFER | VKD3D_TYPED_OFFSET_BUFFER))
extra_bindings |= VKD3D_BINDLESS_SET_EXTRA_OFFSET_BUFFER;
if (vkd3d_descriptor_debug_active_qa_checks())
{
extra_bindings |= VKD3D_BINDLESS_SET_EXTRA_GLOBAL_HEAP_INFO_BUFFER |
VKD3D_BINDLESS_SET_EXTRA_DESCRIPTOR_HEAP_INFO_BUFFER;
}
if (FAILED(hr = vkd3d_bindless_state_add_binding(bindless_state, device,
VKD3D_BINDLESS_SET_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLER)))
goto fail;

View File

@ -20,20 +20,75 @@
#define __VKD3D_DESCRIPTOR_DEBUG_H
#include "vkd3d_private.h"
#include "vkd3d_descriptor_qa_data.h"
/* Cost is 1 bit per cookie, and spending 256 MB of host memory on this is reasonable,
* and overflowing this pool should never happen. */
#define VKD3D_DESCRIPTOR_DEBUG_DEFAULT_NUM_COOKIES (2 * 1000 * 1000 * 1000)
#define VKD3D_DESCRIPTOR_DEBUG_NUM_PAD_DESCRIPTORS 1
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
HRESULT vkd3d_descriptor_debug_alloc_global_info(
struct vkd3d_descriptor_qa_global_info **global_info,
unsigned int num_cookies,
struct d3d12_device *device);
void vkd3d_descriptor_debug_free_global_info(
struct vkd3d_descriptor_qa_global_info *global_info,
struct d3d12_device *device);
void vkd3d_descriptor_debug_kick_qa_check(struct vkd3d_descriptor_qa_global_info *global_info);
const VkDescriptorBufferInfo *vkd3d_descriptor_debug_get_global_info_descriptor(
struct vkd3d_descriptor_qa_global_info *global_info);
void vkd3d_descriptor_debug_init(void);
bool vkd3d_descriptor_debug_active(void);
bool vkd3d_descriptor_debug_active_log(void);
bool vkd3d_descriptor_debug_active_qa_checks(void);
void vkd3d_descriptor_debug_register_heap(void *heap, const D3D12_DESCRIPTOR_HEAP_DESC *desc);
void vkd3d_descriptor_debug_unregister_heap(void *heap);
void vkd3d_descriptor_debug_register_heap(
struct vkd3d_descriptor_qa_heap_buffer_data *heap, uint64_t cookie,
const D3D12_DESCRIPTOR_HEAP_DESC *desc);
void vkd3d_descriptor_debug_unregister_heap(uint64_t cookie);
void vkd3d_descriptor_debug_register_resource_cookie(uint64_t cookie, const D3D12_RESOURCE_DESC *desc);
void vkd3d_descriptor_debug_register_allocation_cookie(uint64_t cookie, const struct vkd3d_allocate_memory_info *info);
void vkd3d_descriptor_debug_register_view_cookie(uint64_t cookie, uint64_t resource_cookie);
void vkd3d_descriptor_debug_unregister_cookie(uint64_t cookie);
void vkd3d_descriptor_debug_register_resource_cookie(
struct vkd3d_descriptor_qa_global_info *global_info,
uint64_t cookie, const D3D12_RESOURCE_DESC *desc);
void vkd3d_descriptor_debug_register_allocation_cookie(
struct vkd3d_descriptor_qa_global_info *global_info,
uint64_t cookie, const struct vkd3d_allocate_memory_info *info);
void vkd3d_descriptor_debug_register_view_cookie(
struct vkd3d_descriptor_qa_global_info *global_info,
uint64_t cookie, uint64_t resource_cookie);
void vkd3d_descriptor_debug_unregister_cookie(
struct vkd3d_descriptor_qa_global_info *global_info,
uint64_t cookie);
void vkd3d_descriptor_debug_write_descriptor(void *heap, uint32_t offset, VkDescriptorType type, uint64_t cookie);
void vkd3d_descriptor_debug_copy_descriptor(void *dst_heap, uint32_t dst_offset,
void *src_heap, uint32_t src_offset, uint64_t cookie);
void vkd3d_descriptor_debug_write_descriptor(
struct vkd3d_descriptor_qa_heap_buffer_data *heap, uint64_t heap_cookie, uint32_t offset,
vkd3d_descriptor_qa_flags type_flags, uint64_t cookie);
void vkd3d_descriptor_debug_copy_descriptor(
struct vkd3d_descriptor_qa_heap_buffer_data *dst_heap, uint64_t dst_heap_cookie, uint32_t dst_offset,
struct vkd3d_descriptor_qa_heap_buffer_data *src_heap, uint64_t src_heap_cookie, uint32_t src_offset,
uint64_t cookie);
VkDeviceSize vkd3d_descriptor_debug_heap_info_size(unsigned int num_descriptors);
#else
#define vkd3d_descriptor_debug_alloc_global_info(global_info, num_cookies, device) (S_OK)
#define vkd3d_descriptor_debug_free_global_info(global_info, device) ((void)0)
#define vkd3d_descriptor_debug_kick_qa_check(global_info) ((void)0)
#define vkd3d_descriptor_debug_get_global_info_descriptor(global_info) ((const VkDescriptorBufferInfo *)NULL)
#define vkd3d_descriptor_debug_init() ((void)0)
#define vkd3d_descriptor_debug_active_log() ((void)0)
#define vkd3d_descriptor_debug_active_qa_checks() (false)
#define vkd3d_descriptor_debug_register_heap(heap, cookie, desc) ((void)0)
#define vkd3d_descriptor_debug_unregister_heap(cookie) ((void)0)
#define vkd3d_descriptor_debug_register_resource_cookie(global_info, cookie, desc) ((void)0)
#define vkd3d_descriptor_debug_register_allocation_cookie(global_info, cookie, info) ((void)0)
#define vkd3d_descriptor_debug_register_view_cookie(global_info, cookie, resource_cookie) ((void)0)
#define vkd3d_descriptor_debug_unregister_cookie(global_info, cookie) ((void)0)
#define vkd3d_descriptor_debug_write_descriptor(heap, heap_cookie, offset, type_flags, cookie) ((void)0)
#define vkd3d_descriptor_debug_copy_descriptor(dst_heap, dst_heap_cookie, dst_offset, src_heap, src_heap_cookie, src_offset, cookie) ((void)0)
#define vkd3d_descriptor_debug_heap_info_size(num_descriptors) 0
#endif
#endif

View File

@ -1072,6 +1072,10 @@ struct d3d12_descriptor_heap
struct vkd3d_host_visible_buffer_range raw_va_aux_buffer;
struct vkd3d_host_visible_buffer_range buffer_ranges;
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
struct vkd3d_host_visible_buffer_range descriptor_heap_info;
uint64_t cookie;
#endif
struct d3d12_device *device;
@ -1190,6 +1194,10 @@ struct d3d12_root_signature
struct vkd3d_shader_descriptor_binding push_constant_ubo_binding;
struct vkd3d_shader_descriptor_binding raw_va_aux_buffer_binding;
struct vkd3d_shader_descriptor_binding offset_buffer_binding;
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
struct vkd3d_shader_descriptor_binding descriptor_qa_heap_binding;
struct vkd3d_shader_descriptor_binding descriptor_qa_global_info;
#endif
uint32_t descriptor_table_offset;
uint32_t descriptor_table_count;
@ -2113,8 +2121,10 @@ enum vkd3d_bindless_set_flag
VKD3D_BINDLESS_SET_RAW_SSBO = (1u << 7),
VKD3D_BINDLESS_SET_MUTABLE = (1u << 8),
VKD3D_BINDLESS_SET_EXTRA_RAW_VA_AUX_BUFFER = (1u << 24),
VKD3D_BINDLESS_SET_EXTRA_OFFSET_BUFFER = (1u << 25),
VKD3D_BINDLESS_SET_EXTRA_RAW_VA_AUX_BUFFER = (1u << 24),
VKD3D_BINDLESS_SET_EXTRA_OFFSET_BUFFER = (1u << 25),
VKD3D_BINDLESS_SET_EXTRA_GLOBAL_HEAP_INFO_BUFFER = (1u << 26),
VKD3D_BINDLESS_SET_EXTRA_DESCRIPTOR_HEAP_INFO_BUFFER = (1u << 27),
VKD3D_BINDLESS_SET_EXTRA_MASK = 0xff000000u
};
@ -2556,6 +2566,9 @@ struct vkd3d_queue_family_info
/* ID3D12Device */
typedef ID3D12Device6 d3d12_device_iface;
struct vkd3d_descriptor_qa_global_info;
struct vkd3d_descriptor_qa_heap_buffer_data;
struct d3d12_device
{
d3d12_device_iface ID3D12Device_iface;
@ -2613,6 +2626,7 @@ struct d3d12_device
struct vkd3d_view_map sampler_map;
struct vkd3d_sampler_state sampler_state;
struct vkd3d_shader_debug_ring debug_ring;
struct vkd3d_descriptor_qa_global_info *descriptor_qa_global_info;
};
HRESULT d3d12_device_create(struct vkd3d_instance *instance,