diff --git a/include/private/vkd3d_descriptor_qa_data.h b/include/private/vkd3d_descriptor_qa_data.h index ff5e3fa8c7..37227a3b6b 100644 --- a/include/private/vkd3d_descriptor_qa_data.h +++ b/include/private/vkd3d_descriptor_qa_data.h @@ -66,6 +66,13 @@ struct vkd3d_descriptor_qa_global_buffer_data uint32_t live_status_table[]; }; +struct vkd3d_instruction_qa_payload_data +{ + uint64_t hash; + uint32_t instruction; + uint32_t value; +}; + /* Physical layout of QA heap buffer. */ struct vkd3d_descriptor_qa_heap_buffer_data { diff --git a/include/vkd3d.h b/include/vkd3d.h index 575caf8fd1..7a9d202868 100644 --- a/include/vkd3d.h +++ b/include/vkd3d.h @@ -108,6 +108,7 @@ extern "C" { #define VKD3D_CONFIG_FLAG_NO_STAGGERED_SUBMIT (1ull << 50) #define VKD3D_CONFIG_FLAG_CLEAR_UAV_SYNC (1ull << 51) #define VKD3D_CONFIG_FLAG_FORCE_DYNAMIC_MSAA (1ull << 52) +#define VKD3D_CONFIG_FLAG_INSTRUCTION_QA_CHECKS (1ull << 53) struct vkd3d_instance; diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index cee2ffcb82..552d7c6755 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -228,6 +228,7 @@ enum vkd3d_shader_interface_flag VKD3D_SHADER_INTERFACE_DESCRIPTOR_QA_BUFFER = 0x00000010u, /* In this model, use descriptor_size_cbv_srv_uav as array stride for raw VA buffer. */ VKD3D_SHADER_INTERFACE_RAW_VA_ALIAS_DESCRIPTOR_BUFFER = 0x00000020u, + VKD3D_SHADER_INTERFACE_INSTRUCTION_QA_BUFFER = 0x00000040u, }; struct vkd3d_shader_stage_io_entry @@ -270,10 +271,10 @@ struct vkd3d_shader_interface_info const struct vkd3d_shader_descriptor_binding *offset_buffer_binding; #ifdef VKD3D_ENABLE_DESCRIPTOR_QA - /* Ignored unless VKD3D_SHADER_INTERFACE_DESCRIPTOR_QA_BUFFER is set. */ - const struct vkd3d_shader_descriptor_binding *descriptor_qa_global_binding; - /* Ignored unless VKD3D_SHADER_INTERFACE_DESCRIPTOR_QA_BUFFER is set. */ - const struct vkd3d_shader_descriptor_binding *descriptor_qa_heap_binding; + /* Ignored unless VKD3D_SHADER_INTERFACE_{DESCRIPTOR,INSTRUCTION}_QA_BUFFER is set. */ + const struct vkd3d_shader_descriptor_binding *descriptor_qa_payload_binding; + /* Ignored unless VKD3D_SHADER_INTERFACE_{DESCRIPTOR,INSTRUCTION}_QA_BUFFER is set. */ + const struct vkd3d_shader_descriptor_binding *descriptor_qa_control_binding; #endif const struct vkd3d_shader_stage_io_map *stage_input_map; diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 9a64ac8387..b923b06c5e 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -722,10 +722,10 @@ int vkd3d_shader_compile_dxil(const struct vkd3d_shader_code *dxbc, helper.enabled = DXIL_SPV_TRUE; helper.version = DXIL_SPV_DESCRIPTOR_QA_INTERFACE_VERSION; helper.shader_hash = hash; - helper.global_desc_set = shader_interface_info->descriptor_qa_global_binding->set; - helper.global_binding = shader_interface_info->descriptor_qa_global_binding->binding; - helper.heap_desc_set = shader_interface_info->descriptor_qa_heap_binding->set; - helper.heap_binding = shader_interface_info->descriptor_qa_heap_binding->binding; + helper.global_desc_set = shader_interface_info->descriptor_qa_payload_binding->set; + helper.global_binding = shader_interface_info->descriptor_qa_payload_binding->binding; + helper.heap_desc_set = shader_interface_info->descriptor_qa_control_binding->set; + helper.heap_binding = shader_interface_info->descriptor_qa_control_binding->binding; if (dxil_spv_converter_add_option(converter, &helper.base) != DXIL_SPV_SUCCESS) { @@ -734,6 +734,26 @@ int vkd3d_shader_compile_dxil(const struct vkd3d_shader_code *dxbc, goto end; } } + else if (shader_interface_info->flags & VKD3D_SHADER_INTERFACE_INSTRUCTION_QA_BUFFER) + { + struct dxil_spv_option_instruction_instrumentation helper; + helper.base.type = DXIL_SPV_OPTION_INSTRUCTION_INSTRUMENTATION; + helper.enabled = DXIL_SPV_TRUE; + helper.version = DXIL_SPV_INSTRUCTION_INSTRUMENTATION_INTERFACE_VERSION; + helper.shader_hash = hash; + helper.payload_desc_set = shader_interface_info->descriptor_qa_payload_binding->set; + helper.payload_binding = shader_interface_info->descriptor_qa_payload_binding->binding; + helper.control_desc_set = shader_interface_info->descriptor_qa_control_binding->set; + helper.control_binding = shader_interface_info->descriptor_qa_control_binding->binding; + helper.type = DXIL_SPV_INSTRUCTION_INSTRUMENTATION_TYPE_EXTERNALLY_VISIBLE_WRITE_NAN_INF; + + if (dxil_spv_converter_add_option(converter, &helper.base) != DXIL_SPV_SUCCESS) + { + ERR("dxil-spirv does not support INSTRUCTION_INSTRUMENTATION.\n"); + ret = VKD3D_ERROR_NOT_IMPLEMENTED; + goto end; + } + } #endif if (shader_interface_info->flags & VKD3D_SHADER_INTERFACE_RAW_VA_ALIAS_DESCRIPTOR_BUFFER) @@ -1419,10 +1439,10 @@ int vkd3d_shader_compile_dxil_export(const struct vkd3d_shader_code *dxil, helper.enabled = DXIL_SPV_TRUE; helper.version = DXIL_SPV_DESCRIPTOR_QA_INTERFACE_VERSION; helper.shader_hash = hash; - helper.global_desc_set = shader_interface_info->descriptor_qa_global_binding->set; - helper.global_binding = shader_interface_info->descriptor_qa_global_binding->binding; - helper.heap_desc_set = shader_interface_info->descriptor_qa_heap_binding->set; - helper.heap_binding = shader_interface_info->descriptor_qa_heap_binding->binding; + helper.global_desc_set = shader_interface_info->descriptor_qa_payload_binding->set; + helper.global_binding = shader_interface_info->descriptor_qa_payload_binding->binding; + helper.heap_desc_set = shader_interface_info->descriptor_qa_control_binding->set; + helper.heap_binding = shader_interface_info->descriptor_qa_control_binding->binding; if (dxil_spv_converter_add_option(converter, &helper.base) != DXIL_SPV_SUCCESS) { @@ -1431,6 +1451,26 @@ int vkd3d_shader_compile_dxil_export(const struct vkd3d_shader_code *dxil, goto end; } } + else if (shader_interface_info->flags & VKD3D_SHADER_INTERFACE_INSTRUCTION_QA_BUFFER) + { + struct dxil_spv_option_instruction_instrumentation helper; + helper.base.type = DXIL_SPV_OPTION_INSTRUCTION_INSTRUMENTATION; + helper.enabled = DXIL_SPV_TRUE; + helper.version = DXIL_SPV_INSTRUCTION_INSTRUMENTATION_INTERFACE_VERSION; + helper.shader_hash = hash; + helper.payload_desc_set = shader_interface_info->descriptor_qa_payload_binding->set; + helper.payload_binding = shader_interface_info->descriptor_qa_payload_binding->binding; + helper.control_desc_set = shader_interface_info->descriptor_qa_control_binding->set; + helper.control_binding = shader_interface_info->descriptor_qa_control_binding->binding; + helper.type = DXIL_SPV_INSTRUCTION_INSTRUMENTATION_TYPE_EXTERNALLY_VISIBLE_WRITE_NAN_INF; + + if (dxil_spv_converter_add_option(converter, &helper.base) != DXIL_SPV_SUCCESS) + { + ERR("dxil-spirv does not support INSTRUCTION_INSTRUMENTATION.\n"); + ret = VKD3D_ERROR_NOT_IMPLEMENTED; + goto end; + } + } #endif { diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 9ddc25c20f..ad6c74db34 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -6269,8 +6269,8 @@ static uint32_t vkd3d_dxbc_compiler_emit_descriptor_qa_heap(struct vkd3d_dxbc_co vkd3d_spirv_build_op_name(builder, heap_struct_type_id, "descriptor_qa_heap_data"); pointer_id = vkd3d_spirv_build_op_type_pointer(builder, SpvStorageClassUniform, heap_struct_type_id); var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, pointer_id, SpvStorageClassUniform, 0); - vkd3d_spirv_build_op_decorate1(builder, var_id, SpvDecorationDescriptorSet, shader_interface->descriptor_qa_heap_binding->set); - vkd3d_spirv_build_op_decorate1(builder, var_id, SpvDecorationBinding, shader_interface->descriptor_qa_heap_binding->binding); + vkd3d_spirv_build_op_decorate1(builder, var_id, SpvDecorationDescriptorSet, shader_interface->descriptor_qa_control_binding->set); + vkd3d_spirv_build_op_decorate1(builder, var_id, SpvDecorationBinding, shader_interface->descriptor_qa_control_binding->binding); vkd3d_spirv_build_op_decorate(builder, var_id, SpvDecorationNonWritable, NULL, 0); vkd3d_spirv_build_op_name(builder, var_id, "descriptor_qa_heap"); @@ -6314,8 +6314,8 @@ static uint32_t vkd3d_dxbc_compiler_emit_descriptor_qa_global_data(struct vkd3d_ vkd3d_spirv_build_op_name(builder, global_struct_type_id, "descriptor_qa_global_data"); pointer_id = vkd3d_spirv_build_op_type_pointer(builder, SpvStorageClassUniform, global_struct_type_id); var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, pointer_id, SpvStorageClassUniform, 0); - vkd3d_spirv_build_op_decorate1(builder, var_id, SpvDecorationDescriptorSet, shader_interface->descriptor_qa_global_binding->set); - vkd3d_spirv_build_op_decorate1(builder, var_id, SpvDecorationBinding, shader_interface->descriptor_qa_global_binding->binding); + vkd3d_spirv_build_op_decorate1(builder, var_id, SpvDecorationDescriptorSet, shader_interface->descriptor_qa_payload_binding->set); + vkd3d_spirv_build_op_decorate1(builder, var_id, SpvDecorationBinding, shader_interface->descriptor_qa_payload_binding->binding); vkd3d_spirv_build_op_name(builder, var_id, "descriptor_qa_global"); return var_id; diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index 9c8b6d16cc..83437cd1d3 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -4800,6 +4800,13 @@ static void d3d12_command_list_invalidate_push_constants(struct vkd3d_pipeline_b bindings->root_descriptor_dirty_mask = bindings->root_signature->root_descriptor_raw_va_mask | bindings->root_signature->root_descriptor_push_mask; + + if (vkd3d_descriptor_debug_active_instruction_qa_checks()) + { + /* Even if root signature itself doesn't have root descriptors, force us to go through that path. */ + bindings->root_descriptor_dirty_mask = UINT64_MAX; + } + bindings->root_constant_dirty_mask = bindings->root_signature->root_constant_mask; } @@ -5654,6 +5661,13 @@ static void d3d12_command_list_reset_api_state(struct d3d12_command_list *list, memset(&list->compute_bindings, 0, sizeof(list->compute_bindings)); memset(&list->descriptor_heap, 0, sizeof(list->descriptor_heap)); + if (vkd3d_descriptor_debug_active_instruction_qa_checks()) + { + /* Even if root signature does not have root descriptors, force us to go through that path. */ + list->graphics_bindings.root_descriptor_dirty_mask = UINT64_MAX; + list->compute_bindings.root_descriptor_dirty_mask = UINT64_MAX; + } + d3d12_command_list_init_default_descriptor_buffers(list); list->state = NULL; @@ -6420,6 +6434,27 @@ static void d3d12_command_list_update_root_descriptors(struct d3d12_command_list root_parameter_data.root_descriptor_vas)); } +#ifdef VKD3D_ENABLE_DESCRIPTOR_QA + if (vkd3d_descriptor_debug_active_instruction_qa_checks()) + { + VkWriteDescriptorSet *write = &descriptor_writes[descriptor_write_count]; + memset(write, 0, 2 * sizeof(*write)); + write[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + write[0].descriptorCount = 1; + write[0].dstBinding = root_signature->descriptor_qa_control_binding.binding; + write[0].pBufferInfo = vkd3d_descriptor_debug_get_control_info_descriptor(list->device->descriptor_qa_global_info); + + write[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + write[1].descriptorCount = 1; + write[1].dstBinding = root_signature->descriptor_qa_payload_binding.binding; + write[1].pBufferInfo = vkd3d_descriptor_debug_get_payload_info_descriptor(list->device->descriptor_qa_global_info); + + descriptor_write_count += 2; + } +#endif + if (descriptor_write_count) { VK_CALL(vkCmdPushDescriptorSetKHR(list->cmd.vk_command_buffer, vk_bind_point, diff --git a/libs/vkd3d/descriptor_debug.c b/libs/vkd3d/descriptor_debug.c index c7531bf79b..a4b032679c 100644 --- a/libs/vkd3d/descriptor_debug.c +++ b/libs/vkd3d/descriptor_debug.c @@ -26,16 +26,24 @@ static pthread_once_t debug_once = PTHREAD_ONCE_INIT; static pthread_mutex_t debug_lock = PTHREAD_MUTEX_INITIALIZER; -static bool descriptor_debug_active_qa_checks; +static bool descriptor_debug_active_descriptor_checks; +static bool descriptor_debug_active_instruction_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; - struct vkd3d_device_memory_allocation device_allocation; + struct vkd3d_descriptor_qa_global_buffer_data *payload_data; + + VkDescriptorBufferInfo payload_descriptor; + VkBuffer vk_payload_buffer; + struct vkd3d_device_memory_allocation payload_device_allocation; + + uint32_t *control_data; + VkBuffer vk_control_buffer; + struct vkd3d_device_memory_allocation control_device_allocation; + VkDescriptorBufferInfo control_descriptor; + unsigned int num_cookies; pthread_t ring_thread; @@ -92,7 +100,12 @@ static void vkd3d_descriptor_debug_init_once(void) if (vkd3d_config_flags & VKD3D_CONFIG_FLAG_DESCRIPTOR_QA_CHECKS) { INFO("Enabling descriptor QA checks!\n"); - descriptor_debug_active_qa_checks = true; + descriptor_debug_active_descriptor_checks = true; + } + else if (vkd3d_config_flags & VKD3D_CONFIG_FLAG_INSTRUCTION_QA_CHECKS) + { + INFO("Enabling instruction-level QA checks!\n"); + descriptor_debug_active_instruction_checks = true; } } @@ -106,9 +119,14 @@ bool vkd3d_descriptor_debug_active_log(void) return descriptor_debug_active_log; } -bool vkd3d_descriptor_debug_active_qa_checks(void) +bool vkd3d_descriptor_debug_active_instruction_qa_checks(void) +{ + return descriptor_debug_active_instruction_checks; +} + +bool vkd3d_descriptor_debug_active_descriptor_qa_checks(void) { - return descriptor_debug_active_qa_checks; + return descriptor_debug_active_descriptor_checks; } VkDeviceSize vkd3d_descriptor_debug_heap_info_size(unsigned int num_descriptors) @@ -120,12 +138,13 @@ VkDeviceSize vkd3d_descriptor_debug_heap_info_size(unsigned int num_descriptors) 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) + if (!global_info || !descriptor_debug_active_descriptor_checks || + !global_info->active || !global_info->payload_data) return; if (cookie < global_info->num_cookies) { - vkd3d_atomic_uint32_or(&global_info->data->live_status_table[cookie / 32], + vkd3d_atomic_uint32_or(&global_info->payload_data->live_status_table[cookie / 32], 1u << (cookie & 31), vkd3d_memory_order_relaxed); } else @@ -135,16 +154,62 @@ static void vkd3d_descriptor_debug_set_live_status_bit( 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) + if (!global_info || !descriptor_debug_active_descriptor_checks || + !global_info->active || !global_info->payload_data) return; if (cookie < global_info->num_cookies) { - vkd3d_atomic_uint32_and(&global_info->data->live_status_table[cookie / 32], + vkd3d_atomic_uint32_and(&global_info->payload_data->live_status_table[cookie / 32], ~(1u << (cookie & 31)), vkd3d_memory_order_relaxed); } } +static void *vkd3d_descriptor_debug_qa_check_instruction(void *userdata) +{ + struct vkd3d_descriptor_qa_global_info *global_info = userdata; + const struct vkd3d_instruction_qa_payload_data *payload_data; + uint32_t control_words = global_info->num_cookies / 16; + bool active = true; + uint32_t i; + + payload_data = (const struct vkd3d_instruction_qa_payload_data *)global_info->payload_data; + + while (active) + { + /* Don't spin endlessly, this thread is kicked after a successful fence wait. */ + pthread_mutex_lock(&global_info->ring_lock); + if (global_info->active) + pthread_cond_wait(&global_info->ring_cond, &global_info->ring_lock); + active = global_info->active; + pthread_mutex_unlock(&global_info->ring_lock); + + for (i = 0; i < control_words; i++) + { + uint32_t word, payload_index; + word = vkd3d_atomic_uint32_load_explicit(&global_info->control_data[i], vkd3d_memory_order_acquire); + /* The upper 16 bits mark that there is valid data. */ + word &= 0xffff0000u; + + if (word) + { + while (word) + { + payload_index = i * 16 + (vkd3d_bitmask_iter32(&word) - 16); + ERR("QA: non-normal value || shader %016"PRIx64", inst %u, value #%x.\n", + payload_data[payload_index].hash, + payload_data[payload_index].instruction, + payload_data[payload_index].value); + } + + vkd3d_atomic_uint32_store_explicit(&global_info->control_data[i], 0, vkd3d_memory_order_release); + } + } + } + + return NULL; +} + static void vkd3d_descriptor_debug_qa_check_report_fault( struct vkd3d_descriptor_qa_global_info *global_info); @@ -162,14 +227,14 @@ static void *vkd3d_descriptor_debug_qa_check_entry(void *userdata) active = global_info->active; pthread_mutex_unlock(&global_info->ring_lock); - if (global_info->data->fault_type != 0) + if (global_info->payload_data->fault_type != 0) { vkd3d_descriptor_debug_qa_check_report_fault(global_info); - ERR("Num failed checks: %u\n", global_info->data->fault_atomic); + ERR("Num failed checks: %u\n", global_info->payload_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); + vkd3d_atomic_uint32_store_explicit(&global_info->payload_data->fault_type, 0, vkd3d_memory_order_relaxed); + vkd3d_atomic_uint32_store_explicit(&global_info->payload_data->fault_atomic, 0, vkd3d_memory_order_release); } } @@ -182,16 +247,138 @@ void vkd3d_descriptor_debug_kick_qa_check(struct vkd3d_descriptor_qa_global_info pthread_cond_signal(&global_info->ring_cond); } -const VkDescriptorBufferInfo *vkd3d_descriptor_debug_get_global_info_descriptor( +const VkDescriptorBufferInfo *vkd3d_descriptor_debug_get_payload_info_descriptor( struct vkd3d_descriptor_qa_global_info *global_info) { if (global_info) - return &global_info->descriptor; + return &global_info->payload_descriptor; else return NULL; } -HRESULT vkd3d_descriptor_debug_alloc_global_info( +const VkDescriptorBufferInfo *vkd3d_descriptor_debug_get_control_info_descriptor( + struct vkd3d_descriptor_qa_global_info *global_info) +{ + if (global_info) + return &global_info->control_descriptor; + else + return NULL; +} + +static HRESULT vkd3d_descriptor_debug_alloc_global_info_instructions( + struct vkd3d_descriptor_qa_global_info **out_global_info, + struct d3d12_device *device) +{ + const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; + struct vkd3d_descriptor_qa_global_info *global_info; + const uint32_t num_payloads = 4096; + D3D12_RESOURCE_DESC1 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(struct vkd3d_instruction_qa_payload_data) * num_payloads; + 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; + + /* Create the payload buffer. */ + if (FAILED(hr = vkd3d_create_buffer(device, &heap_info, heap_flags, &buffer_desc, + "qa-payload", &global_info->vk_payload_buffer))) + { + vkd3d_descriptor_debug_free_global_info(global_info, device); + return hr; + } + + if (FAILED(hr = vkd3d_allocate_internal_buffer_memory(device, global_info->vk_payload_buffer, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &global_info->payload_device_allocation))) + { + vkd3d_descriptor_debug_free_global_info(global_info, device); + return hr; + } + + if ((vr = VK_CALL(vkMapMemory(device->vk_device, global_info->payload_device_allocation.vk_memory, + 0, VK_WHOLE_SIZE, 0, (void**)&global_info->payload_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->payload_data, 0, buffer_desc.Width); + + global_info->payload_descriptor.buffer = global_info->vk_payload_buffer; + global_info->payload_descriptor.offset = 0; + global_info->payload_descriptor.range = buffer_desc.Width; + + /* Create the atomic buffer. Keep it device local to keep GPU performance high. + * We'll eat the insanely slow readback cost on CPU. */ + heap_info.Type = D3D12_HEAP_TYPE_DEFAULT; + buffer_desc.Width = (num_payloads / 16) * sizeof(uint32_t); + + if (FAILED(hr = vkd3d_create_buffer(device, &heap_info, heap_flags, &buffer_desc, + "qa-control", &global_info->vk_control_buffer))) + { + vkd3d_descriptor_debug_free_global_info(global_info, device); + return hr; + } + + if (FAILED(hr = vkd3d_allocate_internal_buffer_memory(device, global_info->vk_control_buffer, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &global_info->control_device_allocation))) + { + vkd3d_descriptor_debug_free_global_info(global_info, device); + return hr; + } + + if ((vr = VK_CALL(vkMapMemory(device->vk_device, global_info->control_device_allocation.vk_memory, + 0, VK_WHOLE_SIZE, 0, (void**)&global_info->control_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->control_data, 0, buffer_desc.Width); + + global_info->control_descriptor.buffer = global_info->vk_control_buffer; + global_info->control_descriptor.offset = 0; + global_info->control_descriptor.range = buffer_desc.Width; + + global_info->num_cookies = num_payloads; + + 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_instruction, global_info) != 0) + { + vkd3d_descriptor_debug_free_global_info(global_info, device); + return E_OUTOFMEMORY; + } + + *out_global_info = global_info; + return S_OK; +} + +static HRESULT vkd3d_descriptor_debug_alloc_global_info_descriptors( struct vkd3d_descriptor_qa_global_info **out_global_info, unsigned int num_cookies, struct d3d12_device *device) { @@ -224,36 +411,37 @@ HRESULT vkd3d_descriptor_debug_alloc_global_info( heap_flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS; - if (FAILED(hr = vkd3d_create_buffer(device, &heap_info, heap_flags, &buffer_desc, "qa-buffer", &global_info->vk_buffer))) + if (FAILED(hr = vkd3d_create_buffer(device, &heap_info, heap_flags, &buffer_desc, + "qa-buffer", &global_info->vk_payload_buffer))) { vkd3d_descriptor_debug_free_global_info(global_info, device); return hr; } - if (FAILED(hr = vkd3d_allocate_internal_buffer_memory(device, global_info->vk_buffer, + if (FAILED(hr = vkd3d_allocate_internal_buffer_memory(device, global_info->vk_payload_buffer, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &global_info->device_allocation))) + &global_info->payload_device_allocation))) { vkd3d_descriptor_debug_free_global_info(global_info, device); return hr; } - if ((vr = VK_CALL(vkMapMemory(device->vk_device, global_info->device_allocation.vk_memory, - 0, VK_WHOLE_SIZE, 0, (void**)&global_info->data)))) + if ((vr = VK_CALL(vkMapMemory(device->vk_device, global_info->payload_device_allocation.vk_memory, + 0, VK_WHOLE_SIZE, 0, (void**)&global_info->payload_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); + memset(global_info->payload_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->payload_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->payload_descriptor.buffer = global_info->vk_payload_buffer; + global_info->payload_descriptor.offset = 0; + global_info->payload_descriptor.range = buffer_desc.Width; global_info->num_cookies = num_cookies; pthread_mutex_init(&global_info->ring_lock, NULL); @@ -269,6 +457,18 @@ HRESULT vkd3d_descriptor_debug_alloc_global_info( return S_OK; } +HRESULT vkd3d_descriptor_debug_alloc_global_info( + struct vkd3d_descriptor_qa_global_info **out_global_info, unsigned int num_cookies, + struct d3d12_device *device) +{ + if (descriptor_debug_active_descriptor_checks) + return vkd3d_descriptor_debug_alloc_global_info_descriptors(out_global_info, num_cookies, device); + else if (descriptor_debug_active_instruction_checks) + return vkd3d_descriptor_debug_alloc_global_info_instructions(out_global_info, device); + else + return E_INVALIDARG; +} + void vkd3d_descriptor_debug_free_global_info( struct vkd3d_descriptor_qa_global_info *global_info, struct d3d12_device *device) @@ -289,8 +489,11 @@ void vkd3d_descriptor_debug_free_global_info( pthread_cond_destroy(&global_info->ring_cond); } - vkd3d_free_device_memory(device, &global_info->device_allocation); - VK_CALL(vkDestroyBuffer(device->vk_device, global_info->vk_buffer, NULL)); + vkd3d_free_device_memory(device, &global_info->control_device_allocation); + VK_CALL(vkDestroyBuffer(device->vk_device, global_info->vk_control_buffer, NULL)); + + vkd3d_free_device_memory(device, &global_info->payload_device_allocation); + VK_CALL(vkDestroyBuffer(device->vk_device, global_info->vk_payload_buffer, NULL)); vkd3d_free(global_info); } @@ -314,24 +517,24 @@ static void vkd3d_descriptor_debug_qa_check_report_fault( { DECL_BUFFER(); - if (global_info->data->fault_type & VKD3D_DESCRIPTOR_FAULT_TYPE_HEAP_OF_OF_RANGE) + if (global_info->payload_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) + if (global_info->payload_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) + if (global_info->payload_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("CBV_SRV_UAV heap cookie: %u\n", global_info->payload_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); + global_info->payload_data->failed_hash, global_info->payload_data->failed_instruction); + APPEND_SNPRINTF("Accessed resource/view cookie: %u\n", global_info->payload_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)); + global_info->payload_data->failed_descriptor_type_mask, + debug_descriptor_type(global_info->payload_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); + global_info->payload_data->actual_descriptor_type_mask, + debug_descriptor_type(global_info->payload_data->actual_descriptor_type_mask)); + APPEND_SNPRINTF("Failed heap index: %u\n", global_info->payload_data->failed_offset); ERR("\n============\n%s==========\n", buffer); if (!vkd3d_descriptor_debug_active_log()) return; diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 86c0a237ec..b545aacc0f 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -974,6 +974,7 @@ static const struct vkd3d_debug_option vkd3d_config_options[] = {"no_staggered_submit", VKD3D_CONFIG_FLAG_NO_STAGGERED_SUBMIT}, {"clear_uav_sync", VKD3D_CONFIG_FLAG_CLEAR_UAV_SYNC}, {"force_dynamic_msaa", VKD3D_CONFIG_FLAG_FORCE_DYNAMIC_MSAA}, + {"instruction_qa_checks", VKD3D_CONFIG_FLAG_INSTRUCTION_QA_CHECKS}, }; static void vkd3d_config_flags_init_once(void) @@ -8697,6 +8698,10 @@ static void vkd3d_compute_shader_interface_key(struct d3d12_device *device) key = hash_fnv1_iterate_u32(key, device->device_info.properties2.properties.driverVersion); } + /* QA checks don't necessarily modify bindless flags, so have to check them separately. */ + hash_fnv1_iterate_u32(key, vkd3d_descriptor_debug_active_instruction_qa_checks()); + hash_fnv1_iterate_u32(key, vkd3d_descriptor_debug_active_descriptor_qa_checks()); + device->shader_interface_key = key; } @@ -8709,7 +8714,7 @@ static void d3d12_device_replace_vtable(struct d3d12_device *device) { /* Don't bother replacing the vtable unless we have to. */ - if (vkd3d_descriptor_debug_active_qa_checks()) + if (vkd3d_descriptor_debug_active_descriptor_qa_checks()) return; #ifdef VKD3D_ENABLE_PROFILING @@ -8914,7 +8919,7 @@ static HRESULT d3d12_device_init(struct d3d12_device *device, } #endif - if (vkd3d_descriptor_debug_active_qa_checks()) + if (vkd3d_descriptor_debug_active_instruction_qa_checks() || vkd3d_descriptor_debug_active_descriptor_qa_checks()) { if (FAILED(hr = vkd3d_descriptor_debug_alloc_global_info(&device->descriptor_qa_global_info, VKD3D_DESCRIPTOR_DEBUG_DEFAULT_NUM_COOKIES, device))) diff --git a/libs/vkd3d/raytracing_pipeline.c b/libs/vkd3d/raytracing_pipeline.c index 70d0e5b986..7dfbcf3abb 100644 --- a/libs/vkd3d/raytracing_pipeline.c +++ b/libs/vkd3d/raytracing_pipeline.c @@ -2207,8 +2207,8 @@ static HRESULT d3d12_state_object_compile_pipeline_variant(struct d3d12_state_ob shader_interface_info.push_constant_ubo_binding = &per_entry_global_signature->push_constant_ubo_binding; shader_interface_info.offset_buffer_binding = &per_entry_global_signature->offset_buffer_binding; #ifdef VKD3D_ENABLE_DESCRIPTOR_QA - shader_interface_info.descriptor_qa_global_binding = &per_entry_global_signature->descriptor_qa_global_info; - shader_interface_info.descriptor_qa_heap_binding = &per_entry_global_signature->descriptor_qa_heap_binding; + shader_interface_info.descriptor_qa_payload_binding = &per_entry_global_signature->descriptor_qa_payload_binding; + shader_interface_info.descriptor_qa_control_binding = &per_entry_global_signature->descriptor_qa_control_binding; #endif } else @@ -2254,6 +2254,16 @@ static HRESULT d3d12_state_object_compile_pipeline_variant(struct d3d12_state_ob /* Promote state which might only be active in local root signature. */ shader_interface_info.flags |= d3d12_root_signature_get_shader_interface_flags(local_signature, VKD3D_PIPELINE_TYPE_RAY_TRACING); + + if (!per_entry_global_signature) + { + /* We won't have any root signature with push descriptors. + * This is a potential hole, but ray tracing shaders without a global root + * signature is questionable at best. + * The outer raygen shader will usually be the one with true side effects. */ + shader_interface_info.flags &= ~VKD3D_SHADER_INTERFACE_INSTRUCTION_QA_BUFFER; + } + if (local_signature->raygen.flags & (VKD3D_ROOT_SIGNATURE_USE_SSBO_OFFSET_BUFFER | VKD3D_ROOT_SIGNATURE_USE_TYPED_OFFSET_BUFFER)) shader_interface_info.offset_buffer_binding = &local_signature->offset_buffer_binding; } diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 3fc0dd2dbe..28df5568c7 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -7432,7 +7432,7 @@ 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() && + if (vkd3d_descriptor_debug_active_descriptor_qa_checks() && descriptor_heap->desc.Type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) { vk_pool_size->descriptorCount += VKD3D_DESCRIPTOR_DEBUG_NUM_PAD_DESCRIPTORS; @@ -7587,7 +7587,8 @@ 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) + if (vkd3d_descriptor_debug_active_descriptor_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; @@ -7661,13 +7662,13 @@ static HRESULT d3d12_descriptor_heap_init_data_buffer(struct d3d12_descriptor_he if (desc->Type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV && !d3d12_device_use_embedded_mutable_descriptors(device)) { raw_va_buffer_size = align(desc->NumDescriptors * sizeof(VkDeviceAddress), alignment); - if (vkd3d_descriptor_debug_active_qa_checks()) + if (vkd3d_descriptor_debug_active_descriptor_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()) + if (vkd3d_descriptor_debug_active_descriptor_qa_checks()) descriptor_heap_info_size = align(vkd3d_descriptor_debug_heap_info_size(desc->NumDescriptors), alignment); } @@ -7815,12 +7816,12 @@ static void d3d12_descriptor_heap_update_extra_bindings(struct d3d12_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); + case VKD3D_BINDLESS_SET_EXTRA_FEEDBACK_PAYLOAD_INFO_BUFFER: + *vk_buffer = *vkd3d_descriptor_debug_get_payload_info_descriptor(device->descriptor_qa_global_info); assert(!d3d12_device_use_embedded_mutable_descriptors(device)); break; - case VKD3D_BINDLESS_SET_EXTRA_DESCRIPTOR_HEAP_INFO_BUFFER: + case VKD3D_BINDLESS_SET_EXTRA_FEEDBACK_CONTROL_INFO_BUFFER: *vk_buffer = descriptor_heap->descriptor_heap_info.descriptor; assert(!d3d12_device_use_embedded_mutable_descriptors(device)); break; @@ -8263,7 +8264,7 @@ bool d3d12_descriptor_heap_require_padding_descriptors(void) uint32_t quirks; unsigned int i; - if (vkd3d_descriptor_debug_active_qa_checks()) + if (vkd3d_descriptor_debug_active_descriptor_qa_checks()) return true; /* If we use descriptor heap robustness, reserve a dummy descriptor we can use diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index cc1bf793ab..e1a38920b5 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -547,6 +547,9 @@ static HRESULT d3d12_root_signature_info_from_desc(struct d3d12_root_signature_i info->push_descriptor_count += info->hoist_descriptor_count; info->binding_count += info->hoist_descriptor_count; info->binding_count += desc->NumStaticSamplers; + + if (vkd3d_descriptor_debug_active_instruction_qa_checks()) + info->push_descriptor_count += 2; } info->parameter_count = desc->NumParameters + info->hoist_descriptor_count; @@ -914,14 +917,14 @@ static void d3d12_root_signature_init_extra_bindings(struct d3d12_root_signature } #ifdef VKD3D_ENABLE_DESCRIPTOR_QA - if (vkd3d_descriptor_debug_active_qa_checks()) + if (vkd3d_descriptor_debug_active_descriptor_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_SET_EXTRA_FEEDBACK_CONTROL_INFO_BUFFER, + &root_signature->descriptor_qa_control_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); + VKD3D_BINDLESS_SET_EXTRA_FEEDBACK_PAYLOAD_INFO_BUFFER, + &root_signature->descriptor_qa_payload_binding); } #endif } @@ -1124,6 +1127,33 @@ static HRESULT d3d12_root_signature_init_root_descriptors(struct d3d12_root_sign context->vk_binding += 1; } +#ifdef VKD3D_ENABLE_DESCRIPTOR_QA + if (vkd3d_descriptor_debug_active_instruction_qa_checks()) + { + vk_binding = &vk_binding_info[j++]; + vk_binding->binding = context->vk_binding; + vk_binding->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + vk_binding->descriptorCount = 1; + vk_binding->stageFlags = VK_SHADER_STAGE_ALL; + vk_binding->pImmutableSamplers = NULL; + + root_signature->descriptor_qa_control_binding.set = context->vk_set; + root_signature->descriptor_qa_control_binding.binding = context->vk_binding; + context->vk_binding += 1; + + vk_binding = &vk_binding_info[j++]; + vk_binding->binding = context->vk_binding; + vk_binding->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + vk_binding->descriptorCount = 1; + vk_binding->stageFlags = VK_SHADER_STAGE_ALL; + vk_binding->pImmutableSamplers = NULL; + + root_signature->descriptor_qa_payload_binding.set = context->vk_set; + root_signature->descriptor_qa_payload_binding.binding = context->vk_binding; + context->vk_binding += 1; + } +#endif + /* This should never happen. Min requirement for push descriptors is 32 and we can always fit into that limit. */ if (j > root_signature->device->device_info.push_descriptor_properties.maxPushDescriptors) { @@ -1677,8 +1707,10 @@ unsigned int d3d12_root_signature_get_shader_interface_flags(const struct d3d12_ if (d3d12_device_use_embedded_mutable_descriptors(root_signature->device)) flags |= VKD3D_SHADER_INTERFACE_RAW_VA_ALIAS_DESCRIPTOR_BUFFER; - if (vkd3d_descriptor_debug_active_qa_checks()) + if (vkd3d_descriptor_debug_active_descriptor_qa_checks()) flags |= VKD3D_SHADER_INTERFACE_DESCRIPTOR_QA_BUFFER; + if (vkd3d_descriptor_debug_active_instruction_qa_checks()) + flags |= VKD3D_SHADER_INTERFACE_INSTRUCTION_QA_BUFFER; return flags; } @@ -2469,8 +2501,8 @@ static void d3d12_pipeline_state_init_shader_interface(struct d3d12_pipeline_sta } #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; + shader_interface->descriptor_qa_payload_binding = &root_signature->descriptor_qa_payload_binding; + shader_interface->descriptor_qa_control_binding = &root_signature->descriptor_qa_control_binding; #endif } @@ -6035,7 +6067,7 @@ 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()) + if (vkd3d_descriptor_debug_active_descriptor_qa_checks()) return 1000000 + VKD3D_DESCRIPTOR_DEBUG_NUM_PAD_DESCRIPTORS; return 1000000; @@ -6473,7 +6505,7 @@ bool vkd3d_bindless_supports_embedded_mutable_type(struct d3d12_device *device, /* If we're using descriptor QA, we need more complex CPU VA decode to decode heap, offsets, types, etc, * so the fast path is not feasible. */ - if (vkd3d_descriptor_debug_active_qa_checks()) + if (vkd3d_descriptor_debug_active_descriptor_qa_checks()) return false; /* We don't want to keep metadata around for shader visible heap. @@ -6878,10 +6910,10 @@ 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()) + if (vkd3d_descriptor_debug_active_descriptor_qa_checks()) { - extra_bindings |= VKD3D_BINDLESS_SET_EXTRA_GLOBAL_HEAP_INFO_BUFFER | - VKD3D_BINDLESS_SET_EXTRA_DESCRIPTOR_HEAP_INFO_BUFFER; + extra_bindings |= VKD3D_BINDLESS_SET_EXTRA_FEEDBACK_PAYLOAD_INFO_BUFFER | + VKD3D_BINDLESS_SET_EXTRA_FEEDBACK_CONTROL_INFO_BUFFER; } if (FAILED(hr = vkd3d_bindless_state_add_binding(bindless_state, device, diff --git a/libs/vkd3d/vkd3d_descriptor_debug.h b/libs/vkd3d/vkd3d_descriptor_debug.h index 866323a494..17d1f7640f 100644 --- a/libs/vkd3d/vkd3d_descriptor_debug.h +++ b/libs/vkd3d/vkd3d_descriptor_debug.h @@ -38,12 +38,15 @@ void vkd3d_descriptor_debug_free_global_info( void vkd3d_descriptor_debug_kick_qa_check(struct vkd3d_descriptor_qa_global_info *global_info); -const VkDescriptorBufferInfo *vkd3d_descriptor_debug_get_global_info_descriptor( +const VkDescriptorBufferInfo *vkd3d_descriptor_debug_get_payload_info_descriptor( + struct vkd3d_descriptor_qa_global_info *global_info); +const VkDescriptorBufferInfo *vkd3d_descriptor_debug_get_control_info_descriptor( struct vkd3d_descriptor_qa_global_info *global_info); void vkd3d_descriptor_debug_init(void); bool vkd3d_descriptor_debug_active_log(void); -bool vkd3d_descriptor_debug_active_qa_checks(void); +bool vkd3d_descriptor_debug_active_instruction_qa_checks(void); +bool vkd3d_descriptor_debug_active_descriptor_qa_checks(void); void vkd3d_descriptor_debug_register_heap( struct vkd3d_descriptor_qa_heap_buffer_data *heap, uint64_t cookie, @@ -79,10 +82,12 @@ VkDeviceSize vkd3d_descriptor_debug_heap_info_size(unsigned int num_descriptors) #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_get_payload_info_descriptor(global_info) ((const VkDescriptorBufferInfo *)NULL) +#define vkd3d_descriptor_debug_get_control_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_active_instruction_qa_checks() (false) +#define vkd3d_descriptor_debug_active_descriptor_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) diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index dbbe842260..29d45374c2 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -1781,8 +1781,8 @@ struct d3d12_root_signature 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; + struct vkd3d_shader_descriptor_binding descriptor_qa_payload_binding; + struct vkd3d_shader_descriptor_binding descriptor_qa_control_binding; #endif VkDescriptorSetLayout set_layouts[VKD3D_MAX_DESCRIPTOR_SETS]; @@ -3764,10 +3764,10 @@ enum vkd3d_bindless_set_flag VKD3D_BINDLESS_SET_MUTABLE_RAW = (1u << 8), VKD3D_BINDLESS_SET_MUTABLE_TYPED = (1u << 9), - 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_RAW_VA_AUX_BUFFER = (1u << 24), + VKD3D_BINDLESS_SET_EXTRA_OFFSET_BUFFER = (1u << 25), + VKD3D_BINDLESS_SET_EXTRA_FEEDBACK_PAYLOAD_INFO_BUFFER = (1u << 26), + VKD3D_BINDLESS_SET_EXTRA_FEEDBACK_CONTROL_INFO_BUFFER = (1u << 27), VKD3D_BINDLESS_SET_EXTRA_MASK = 0xff000000u };