Skip to content

Commit

Permalink
vkd3d: Hook up instruction QA checks.
Browse files Browse the repository at this point in the history
Unified global/heap binding to the more generic control/payload
structure, to be able to support more kinds of QA instrumentation.

Control is intended to be device-local information, and payload is
host-visible information.

Rather than add more heap bindings, we need to use push descriptors
here. Not every shader uses heap bindings,
e.g., a shader can rely solely on root descriptors.

Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
  • Loading branch information
HansKristian-Work committed Sep 24, 2024
1 parent 89a561f commit c9f9d2f
Show file tree
Hide file tree
Showing 13 changed files with 433 additions and 93 deletions.
7 changes: 7 additions & 0 deletions include/private/vkd3d_descriptor_qa_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
1 change: 1 addition & 0 deletions include/vkd3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
9 changes: 5 additions & 4 deletions include/vkd3d_shader.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
56 changes: 48 additions & 8 deletions libs/vkd3d-shader/dxil.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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)
Expand Down Expand Up @@ -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)
{
Expand All @@ -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

{
Expand Down
8 changes: 4 additions & 4 deletions libs/vkd3d-shader/spirv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");

Expand Down Expand Up @@ -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;
Expand Down
35 changes: 35 additions & 0 deletions libs/vkd3d/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
Loading

0 comments on commit c9f9d2f

Please sign in to comment.