Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- include/vkd3d_shader.h | 22 ++++++++++++++++++++++ libs/vkd3d-shader/spirv.c | 8 +++++++- 2 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 37b5936d..8d813d85 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -64,6 +64,11 @@ enum vkd3d_shader_structure_type * \since 1.3 */ VKD3D_SHADER_STRUCTURE_TYPE_PREPROCESS_INFO, + /** + * The structure is a vkd3d_shader_binding_offset_info structure. + * \since 1.3 + */ + VKD3D_SHADER_STRUCTURE_TYPE_BINDING_OFFSET_INFO,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_STRUCTURE_TYPE), }; @@ -452,6 +457,23 @@ struct vkd3d_shader_transform_feedback_info unsigned int buffer_stride_count; };
+/* Extends vkd3d_shader_interface_info. */ +struct vkd3d_shader_binding_offset_info +{ + /** Must be set to VKD3D_SHADER_STRUCTURE_TYPE_BINDING_OFFSET_INFO. */ + enum vkd3d_shader_structure_type type; + /** Optional pointer to a structure containing further parameters. */ + const void *next; + + /** + * Pointer to an array of offsets into shader resource descriptor bindings. + * These correlate 1:1 to the 'bindings' array in struct + * vkd3d_shader_interface_info, and will be added to the register index to + * address the correct location in a merged binding. + */ + const unsigned int *binding_offsets; +}; + /** The format of a shader to be compiled or scanned. */ enum vkd3d_shader_source_type { diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index ebaf1631..fab92059 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -2231,6 +2231,7 @@ struct vkd3d_dxbc_compiler size_t control_flow_info_size;
struct vkd3d_shader_interface_info shader_interface; + struct vkd3d_shader_binding_offset_info offset_info; struct vkd3d_push_constant_buffer_binding *push_constants; const struct vkd3d_shader_spirv_target_info *spirv_target_info;
@@ -2292,6 +2293,7 @@ struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader const struct vkd3d_shader_signature *patch_constant_signature = &shader_desc->patch_constant_signature; const struct vkd3d_shader_signature *output_signature = &shader_desc->output_signature; const struct vkd3d_shader_interface_info *shader_interface; + const struct vkd3d_shader_binding_offset_info *offset_info; const struct vkd3d_shader_spirv_target_info *target_info; struct vkd3d_dxbc_compiler *compiler; unsigned int max_element_count; @@ -2385,6 +2387,9 @@ struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader for (i = 0; i < shader_interface->push_constant_buffer_count; ++i) compiler->push_constants[i].pc = shader_interface->push_constant_buffers[i]; } + + if ((offset_info = vkd3d_find_struct(shader_interface->next, BINDING_OFFSET_INFO))) + compiler->offset_info = *offset_info; }
compiler->scan_descriptor_info = scan_descriptor_info; @@ -2546,6 +2551,7 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor { const struct vkd3d_shader_interface_info *shader_interface = &compiler->shader_interface; unsigned int register_last = (range->last == ~0u) ? range->first : range->last; + const unsigned int *binding_offsets = compiler->offset_info.binding_offsets; enum vkd3d_shader_descriptor_type descriptor_type; enum vkd3d_shader_binding_flag resource_type_flag; struct vkd3d_shader_descriptor_binding binding; @@ -2626,7 +2632,7 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor || current->binding.count <= register_last - current->register_index) continue;
- *binding_base_idx = current->register_index; + *binding_base_idx = current->register_index - (binding_offsets ? binding_offsets[i] : 0); return current->binding; } if (shader_interface->binding_count)
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- Needs to go on top of the final shader non-uniform patch for the tests to work. --- libs/vkd3d/state.c | 29 +++++++++++++++++++++++------ libs/vkd3d/vkd3d_private.h | 1 + tests/d3d12.c | 1 - 3 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index 78b0c717..123761f2 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -91,6 +91,7 @@ static void d3d12_root_signature_cleanup(struct d3d12_root_signature *root_signa
if (root_signature->descriptor_mapping) vkd3d_free(root_signature->descriptor_mapping); + vkd3d_free(root_signature->binding_offsets); if (root_signature->root_constants) vkd3d_free(root_signature->root_constants);
@@ -700,10 +701,11 @@ static HRESULT d3d12_root_signature_init_descriptor_array_binding(struct d3d12_r }
static void d3d12_root_signature_map_vk_unbounded_binding(struct d3d12_root_signature *root_signature, - const struct d3d12_root_descriptor_table_range *range, bool buffer_descriptor, + const struct d3d12_root_descriptor_table_range *range, unsigned int binding_offset, bool buffer_descriptor, enum vkd3d_shader_visibility shader_visibility, struct vkd3d_descriptor_set_context *context) { - struct vkd3d_shader_resource_binding *mapping = &root_signature->descriptor_mapping[context->descriptor_index++]; + struct vkd3d_shader_resource_binding *mapping = &root_signature->descriptor_mapping[context->descriptor_index]; + unsigned int *offset = &root_signature->binding_offsets[context->descriptor_index++];
mapping->type = range->type; mapping->register_space = range->register_space; @@ -714,18 +716,21 @@ static void d3d12_root_signature_map_vk_unbounded_binding(struct d3d12_root_sign || range->type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV) && !buffer_descriptor); mapping->binding.binding = range->binding; mapping->binding.count = range->vk_binding_count; + *offset = binding_offset; }
static void d3d12_root_signature_map_descriptor_unbounded_binding(struct d3d12_root_signature *root_signature, - const struct d3d12_root_descriptor_table_range *range, + const struct d3d12_root_descriptor_table_range *range, unsigned int binding_offset, enum vkd3d_shader_visibility shader_visibility, struct vkd3d_descriptor_set_context *context) { bool is_buffer = range->type == VKD3D_SHADER_DESCRIPTOR_TYPE_CBV;
if (range->type == VKD3D_SHADER_DESCRIPTOR_TYPE_SRV || range->type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV) - d3d12_root_signature_map_vk_unbounded_binding(root_signature, range, true, shader_visibility, context); + d3d12_root_signature_map_vk_unbounded_binding(root_signature, range, + binding_offset, true, shader_visibility, context);
- d3d12_root_signature_map_vk_unbounded_binding(root_signature, range, is_buffer, shader_visibility, context); + d3d12_root_signature_map_vk_unbounded_binding(root_signature, range, + binding_offset, is_buffer, shader_visibility, context); }
static int compare_register_range(const void *a, const void *b) @@ -869,7 +874,7 @@ static HRESULT d3d12_root_signature_init_root_descriptor_tables(struct d3d12_roo range->binding = base_range->binding; range->vk_binding_count = base_range->vk_binding_count - rel_offset; d3d12_root_signature_map_descriptor_unbounded_binding(root_signature, range, - shader_visibility, context); + rel_offset, shader_visibility, context); continue; } else if (range->descriptor_count == UINT_MAX) @@ -1152,6 +1157,9 @@ static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signa if (!(root_signature->descriptor_mapping = vkd3d_calloc(root_signature->binding_count, sizeof(*root_signature->descriptor_mapping)))) goto fail; + if (!(root_signature->binding_offsets = vkd3d_calloc(root_signature->binding_count, + sizeof(*root_signature->binding_offsets)))) + goto fail; root_signature->root_constant_count = info.root_constant_count; if (!(root_signature->root_constants = vkd3d_calloc(root_signature->root_constant_count, sizeof(*root_signature->root_constants)))) @@ -1865,6 +1873,7 @@ static HRESULT d3d12_pipeline_state_init_compute(struct d3d12_pipeline_state *st const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; struct vkd3d_shader_scan_descriptor_info shader_info; struct vkd3d_shader_interface_info shader_interface; + struct vkd3d_shader_binding_offset_info offset_info; const struct d3d12_root_signature *root_signature; struct vkd3d_shader_spirv_target_info target_info; VkPipelineLayout vk_pipeline_layout; @@ -1904,6 +1913,14 @@ static HRESULT d3d12_pipeline_state_init_compute(struct d3d12_pipeline_state *st target_info.extensions = device->vk_info.shader_extensions; target_info.extension_count = device->vk_info.shader_extension_count;
+ if (root_signature->binding_offsets) + { + target_info.next = &offset_info; + offset_info.type = VKD3D_SHADER_STRUCTURE_TYPE_BINDING_OFFSET_INFO; + offset_info.next = NULL; + offset_info.binding_offsets = root_signature->binding_offsets; + } + shader_interface.type = VKD3D_SHADER_STRUCTURE_TYPE_INTERFACE_INFO; shader_interface.next = &target_info; shader_interface.bindings = root_signature->descriptor_mapping; diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index f8474caa..46e4a485 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -736,6 +736,7 @@ struct d3d12_root_signature
unsigned int binding_count; struct vkd3d_shader_resource_binding *descriptor_mapping; + unsigned int *binding_offsets;
unsigned int root_constant_count; struct vkd3d_shader_push_constant_buffer *root_constants; diff --git a/tests/d3d12.c b/tests/d3d12.c index cc06b137..27393eec 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -34999,7 +34999,6 @@ static void test_unbounded_resource_arrays(void) D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE); get_buffer_readback_with_command_list(output_buffers[i], DXGI_FORMAT_R32_UINT, &rb, queue, command_list); /* Buffers at index >= 64 are aliased. */ - todo_if(i != 74) check_readback_data_uint(&rb, NULL, (i < 64 ? 63 - i : 127 - i) ^ 0x35, 0); release_resource_readback(&rb); reset_command_list(command_list, context.allocator);
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d/state.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index 123761f2..6b088fff 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -2388,6 +2388,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s struct vkd3d_shader_transform_feedback_info xfb_info; struct vkd3d_shader_spirv_target_info ps_target_info; struct vkd3d_shader_interface_info shader_interface; + struct vkd3d_shader_binding_offset_info offset_info; struct vkd3d_shader_spirv_target_info *target_info; const struct d3d12_root_signature *root_signature; struct vkd3d_shader_signature input_signature; @@ -2397,6 +2398,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s const struct vkd3d_format *format; unsigned int instance_divisor; VkVertexInputRate input_rate; + const void **chain_next; unsigned int i, j; size_t rt_count; uint32_t mask; @@ -2627,6 +2629,16 @@ 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.combined_samplers = NULL; shader_interface.combined_sampler_count = 0; + chain_next = &shader_interface.next; + + if (root_signature->binding_offsets) + { + shader_interface.next = &offset_info; + offset_info.type = VKD3D_SHADER_STRUCTURE_TYPE_BINDING_OFFSET_INFO; + offset_info.next = NULL; + offset_info.binding_offsets = root_signature->binding_offsets; + chain_next = &offset_info.next; + }
for (i = 0; i < ARRAY_SIZE(shader_stages); ++i) { @@ -2692,11 +2704,11 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s goto fail; }
- shader_interface.next = shader_stages[i].stage == xfb_stage ? &xfb_info : NULL; + *chain_next = shader_stages[i].stage == xfb_stage ? &xfb_info : NULL; if (target_info) { - target_info->next = shader_interface.next; - shader_interface.next = target_info; + target_info->next = *chain_next; + *chain_next = target_info; }
if (FAILED(hr = create_shader_stage(device, &graphics->stages[graphics->stage_count],
On Mon, 11 Oct 2021 at 16:23, Conor McCarthy cmccarthy@codeweavers.com wrote:
@@ -2627,6 +2629,16 @@ 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.combined_samplers = NULL; shader_interface.combined_sampler_count = 0;
- chain_next = &shader_interface.next;
- if (root_signature->binding_offsets)
- {
shader_interface.next = &offset_info;
offset_info.type = VKD3D_SHADER_STRUCTURE_TYPE_BINDING_OFFSET_INFO;
offset_info.next = NULL;
offset_info.binding_offsets = root_signature->binding_offsets;
chain_next = &offset_info.next;
- }
It may be worth introducing a vkd3d equivalent of vk_prepend_struct() for this kind of thing.
On Mon, 11 Oct 2021 at 16:23, Conor McCarthy cmccarthy@codeweavers.com wrote:
+/* Extends vkd3d_shader_interface_info. */ +struct vkd3d_shader_binding_offset_info +{
- /** Must be set to VKD3D_SHADER_STRUCTURE_TYPE_BINDING_OFFSET_INFO. */
- enum vkd3d_shader_structure_type type;
- /** Optional pointer to a structure containing further parameters. */
- const void *next;
- /**
* Pointer to an array of offsets into shader resource descriptor bindings.
* These correlate 1:1 to the 'bindings' array in struct
* vkd3d_shader_interface_info, and will be added to the register index to
* address the correct location in a merged binding.
*/
- const unsigned int *binding_offsets;
+};
What about UAV counter bindings and/or combined sampler bindings? Should we support offsets for those? Is the "binding_offsets" field allowed to be NULL? Specifying this in terms of the register index works, but is perhaps not the most intuitive way to specify this. The other way to look at it is as the start offset in the descriptor array specified by the vkd3d_shader_descriptor_binding structure. That would make this more of a "descriptor offset" than a "binding offset", but that's somewhat true already; this doesn't index the "bindings" array. How does this interact with the "count" field in the vkd3d_shader_descriptor_binding structure? Does "count" start counting at the offset or at zero?