diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 37b5936d..3ba84a52 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), }; @@ -208,8 +213,9 @@ struct vkd3d_shader_descriptor_binding /** The binding index of the descriptor. */ unsigned int binding; /** - * The size of this descriptor array. Descriptor arrays are not supported in - * this version of vkd3d-shader, and therefore this value must be 1. + * The size of this descriptor array. If an offset is specified for this + * binding by the vkd3d_shader_descriptor_offset_info structure, counting + * starts at that offset. */ unsigned int count; }; @@ -452,6 +458,68 @@ struct vkd3d_shader_transform_feedback_info unsigned int buffer_stride_count; }; +/** + * A chained structure containing descriptor offsets. + * + * This structure is optional. + * + * This structure extends vkd3d_shader_interface_info. + * + * This structure contains only input parameters. + * + * \since 1.3 + */ +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 into the descriptor arrays referenced by + * the 'bindings' array in struct vkd3d_shader_interface_info. This allows + * mapping multiple shader resource arrays to a single binding point in + * the target environment. + * + * For example, to map Direct3D constant buffer registers 'cb0[0:3]' and + * 'cb1[6:7]' to descriptors 8-12 and 4-5 in the Vulkan descriptor array in + * descriptor set 3 and with binding 2, set the following values in the + * 'bindings' array in struct vkd3d_shader_interface_info: + * + * \code + * type = VKD3D_SHADER_DESCRIPTOR_TYPE_CBV + * register_space = 0 + * register_index = 0 + * binding.set = 3 + * binding.binding = 2 + * binding.count = 4 + * + * type = VKD3D_SHADER_DESCRIPTOR_TYPE_CBV + * register_space = 0 + * register_index = 6 + * binding.set = 3 + * binding.binding = 2 + * binding.count = 2 + * \endcode + * + * and then pass \c {8, \c 4} as \a binding_offsets here. + * + * This field may be NULL, in which case the corresponding offsets are + * specified to be 0. + */ + const unsigned int *binding_offsets; + + /** + * Pointer to an array of offsets into the descriptor arrays referenced by + * the 'uav_counters' array in struct vkd3d_shader_interface_info. This + * works the same way as \ref binding_offsets above. UAV counter arrays are + * not supported in this version of vkd3d-shader, and therefore this field + * must either be NULL or specify 0 offsets. + */ + 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 f9124fc4..6cf438d9 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 *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 +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 - (binding_offsets ? binding_offsets[i] : 0); return current->binding; } if (shader_interface->binding_count)