Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- include/vkd3d_shader.h | 38 ++++++++++++++++++++++++++++++++++++++ libs/vkd3d-shader/spirv.c | 12 +++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 37b5936d..77cc3751 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_descriptor_offset_info structure. + * \since 1.3 + */ + VKD3D_SHADER_STRUCTURE_TYPE_DESCRIPTOR_OFFSET_INFO,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_STRUCTURE_TYPE), }; @@ -452,6 +457,39 @@ struct vkd3d_shader_transform_feedback_info unsigned int buffer_stride_count; };
+/* Extends vkd3d_shader_interface_info. */ +struct vkd3d_shader_descriptor_offset_info +{ + /** Must be set to VKD3D_SHADER_STRUCTURE_TYPE_DESCRIPTOR_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 which define the location of each vkd3d + * shader resource descriptor binding within a Vulkan descriptor binding. + * This array correlates exactly to the 'bindings' array in struct + * vkd3d_shader_interface_info. Multiple vkd3d bindings may be merged into + * a single Vulkan binding, and these offsets will be used to address the + * correct location in a merged binding. This value may be NULL, but if + * merged bindings are not used (i.e. all offsets are zero), struct + * vkd3d_shader_descriptor_offset_info may be omitted. The 'count' field in + * struct vkd3d_shader_descriptor_binding begins at the offset location. + * Use of merged Vulkan bindings requires EXT_descriptor_indexing. Merged + * bindings are not supported for combined samplers. + */ + const unsigned int *descriptor_offsets; + + /** + * Pointer to an array of offsets into UAV counter descriptor bindings. + * These correlate exactly to the 'uav_counters' array in struct + * vkd3d_shader_interface_info, and will be used in the same way as + * \ref descriptor_offsets above. UAV counter arrays are not supported in + * this version of vkd3d-shader, so this value must be NULL. + */ + const unsigned int *uav_counter_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..d04b1101 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_descriptor_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_descriptor_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,13 @@ 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, DESCRIPTOR_OFFSET_INFO))) + { + compiler->offset_info = *offset_info; + if (offset_info->uav_counter_offsets) + WARN("Ignoring UAV counter offsets %p.\n", offset_info->uav_counter_offsets); + } }
compiler->scan_descriptor_info = scan_descriptor_info; @@ -2546,6 +2555,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 *descriptor_offsets = compiler->offset_info.descriptor_offsets; enum vkd3d_shader_descriptor_type descriptor_type; enum vkd3d_shader_binding_flag resource_type_flag; struct vkd3d_shader_descriptor_binding binding; @@ -2626,7 +2636,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 - (descriptor_offsets ? descriptor_offsets[i] : 0); return current->binding; } if (shader_interface->binding_count)
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- include/vkd3d_shader.h | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 77cc3751..8345daf8 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -391,6 +391,15 @@ struct vkd3d_shader_push_constant_buffer unsigned int size; };
+/** A chained structure for use when adding new input chain elements. */ +struct vkd3d_shader_base_in_structure +{ + /** Must be set to a value from enum vkd3d_shader_structure_type. */ + enum vkd3d_shader_structure_type type; + /** Optional pointer to a structure containing further parameters. */ + const void *next; +}; + /** * A chained structure describing the interface between a compiled shader and * the target environment.
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d/state.c | 8 +++++--- libs/vkd3d/vkd3d_private.h | 9 +++++++++ 2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index 701af891..8c514bd4 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -2676,11 +2676,13 @@ 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; + if (shader_stages[i].stage == xfb_stage) + { + vkd3d_prepend_struct(&shader_interface, &xfb_info); + } if (target_info) { - target_info->next = shader_interface.next; - shader_interface.next = target_info; + vkd3d_prepend_struct(&shader_interface, target_info); }
if (FAILED(hr = create_shader_stage(device, &graphics->stages[graphics->stage_count], diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index f8474caa..d5fb0753 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -1395,4 +1395,13 @@ static inline void vk_prepend_struct(void *header, void *structure) vk_header->pNext = vk_structure; }
+static inline void vkd3d_prepend_struct(void *header, void *structure) +{ + struct vkd3d_shader_base_in_structure *vkd3d_header = header, *vkd3d_structure = structure; + + assert(!vkd3d_structure->next); + vkd3d_structure->next = vkd3d_header->next; + vkd3d_header->next = vkd3d_structure; +} + #endif /* __VKD3D_PRIVATE_H */
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d/state.c | 30 ++++++++++++++++++++++++------ libs/vkd3d/vkd3d_private.h | 1 + tests/d3d12.c | 1 - 3 files changed, 25 insertions(+), 7 deletions(-)
diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index 8c514bd4..b4476f9e 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->descriptor_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 descriptor_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->descriptor_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 = descriptor_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 descriptor_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, + descriptor_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, + descriptor_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->descriptor_offsets = vkd3d_calloc(root_signature->binding_count, + sizeof(*root_signature->descriptor_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_descriptor_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,15 @@ 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->descriptor_offsets) + { + offset_info.type = VKD3D_SHADER_STRUCTURE_TYPE_DESCRIPTOR_OFFSET_INFO; + offset_info.next = NULL; + offset_info.descriptor_offsets = root_signature->descriptor_offsets; + offset_info.uav_counter_offsets = NULL; + vkd3d_prepend_struct(&target_info, &offset_info); + } + 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 d5fb0753..f6980957 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 *descriptor_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 38fab13c..86b17cea 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 && i > 63) 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 | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index b4476f9e..4f4e79b1 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -2390,6 +2390,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_descriptor_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; @@ -2630,6 +2631,15 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s shader_interface.combined_samplers = NULL; shader_interface.combined_sampler_count = 0;
+ if (root_signature->descriptor_offsets) + { + offset_info.type = VKD3D_SHADER_STRUCTURE_TYPE_DESCRIPTOR_OFFSET_INFO; + offset_info.next = NULL; + offset_info.descriptor_offsets = root_signature->descriptor_offsets; + offset_info.uav_counter_offsets = NULL; + vkd3d_prepend_struct(&shader_interface, &offset_info); + } + for (i = 0; i < ARRAY_SIZE(shader_stages); ++i) { struct vkd3d_shader_scan_descriptor_info shader_info =