Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- include/vkd3d_shader.h | 110 +++++++++++++++++--------------------- libs/vkd3d-shader/spirv.c | 21 ++++---- libs/vkd3d/state.c | 68 ++++++++++++++--------- 3 files changed, 101 insertions(+), 98 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 4a51b3f4..deffef19 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -249,6 +249,8 @@ enum vkd3d_shader_parameter_name { VKD3D_SHADER_PARAMETER_NAME_UNKNOWN, VKD3D_SHADER_PARAMETER_NAME_RASTERIZER_SAMPLE_COUNT, + VKD3D_SHADER_PARAMETER_NAME_DESCRIPTOR_OFFSETS, + VKD3D_SHADER_PARAMETER_NAME_UAV_COUNTER_OFFSETS,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARAMETER_NAME), }; @@ -266,6 +268,52 @@ struct vkd3d_shader_parameter_specialization_constant uint32_t id; };
+struct vkd3d_shader_parameter_descriptor_offsets +{ + /** + * 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, or the structure may be omitted from the + * parameter list, in which case the corresponding offsets are specified + * to be 0. + * + * If the parameter is specified under name + * VKD3D_SHADER_PARAMETER_NAME_UAV_COUNTER_OFFSETS, 'offsets' points 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 described above. UAV counter arrays are not supported in + * this version of vkd3d-shader, and therefore this field must be NULL, or + * the parameter omitted. + */ + const unsigned int *offsets; +}; + struct vkd3d_shader_parameter { enum vkd3d_shader_parameter_name name; @@ -275,6 +322,7 @@ struct vkd3d_shader_parameter { struct vkd3d_shader_parameter_immediate_constant immediate_constant; struct vkd3d_shader_parameter_specialization_constant specialization_constant; + struct vkd3d_shader_parameter_descriptor_offsets descriptor_offsets; } u; };
@@ -458,68 +506,6 @@ 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 522225d9..9f71c6e0 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -2235,7 +2235,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; + const unsigned int *binding_offsets; struct vkd3d_push_constant_buffer_binding *push_constants; const struct vkd3d_shader_spirv_target_info *spirv_target_info;
@@ -2289,6 +2289,9 @@ static const char *vkd3d_dxbc_compiler_get_entry_point_name(const struct vkd3d_d return info && info->entry_point ? info->entry_point : "main"; }
+static const struct vkd3d_shader_parameter *vkd3d_dxbc_compiler_get_shader_parameter( + struct vkd3d_dxbc_compiler *compiler, enum vkd3d_shader_parameter_name name); + struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader_version *shader_version, const struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info, const struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info, @@ -2297,8 +2300,8 @@ 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; + const struct vkd3d_shader_parameter *parameter; struct vkd3d_dxbc_compiler *compiler; unsigned int max_element_count; unsigned int i; @@ -2391,15 +2394,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); - } }
+ if ((parameter = vkd3d_dxbc_compiler_get_shader_parameter(compiler, VKD3D_SHADER_PARAMETER_NAME_DESCRIPTOR_OFFSETS))) + compiler->binding_offsets = parameter->u.descriptor_offsets.offsets; + if ((parameter = vkd3d_dxbc_compiler_get_shader_parameter(compiler, VKD3D_SHADER_PARAMETER_NAME_UAV_COUNTER_OFFSETS))) + WARN("Ignoring UAV counter offsets %p.\n", parameter->u.descriptor_offsets.offsets); + compiler->scan_descriptor_info = scan_descriptor_info;
vkd3d_string_buffer_cache_init(&compiler->string_buffers); @@ -2559,7 +2560,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; + const unsigned int *binding_offsets = compiler->binding_offsets; enum vkd3d_shader_descriptor_type descriptor_type; enum vkd3d_shader_binding_flag resource_type_flag; struct vkd3d_shader_descriptor_binding binding; diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index cb3f99ad..8f788dba 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -1880,13 +1880,29 @@ static HRESULT d3d12_pipeline_state_init_uav_counters(struct d3d12_pipeline_stat return S_OK; }
+static void spirv_target_info_append_descriptor_offsets(struct vkd3d_shader_spirv_target_info *target_info, + const struct d3d12_root_signature *root_signature) +{ + struct vkd3d_shader_parameter *parameter; + + if (!root_signature->descriptor_offsets) + return; + + parameter = (struct vkd3d_shader_parameter *)&target_info->parameters[target_info->parameter_count]; + parameter->name = VKD3D_SHADER_PARAMETER_NAME_DESCRIPTOR_OFFSETS; + parameter->type = VKD3D_SHADER_PARAMETER_TYPE_UNKNOWN; + parameter->data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_UNKNOWN; + parameter->u.descriptor_offsets.offsets = root_signature->descriptor_offsets; + ++target_info->parameter_count; +} + static HRESULT d3d12_pipeline_state_init_compute(struct d3d12_pipeline_state *state, struct d3d12_device *device, const D3D12_COMPUTE_PIPELINE_STATE_DESC *desc) { 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; + struct vkd3d_shader_parameter shader_parameters[1]; const struct d3d12_root_signature *root_signature; struct vkd3d_shader_spirv_target_info target_info; VkPipelineLayout vk_pipeline_layout; @@ -1925,15 +1941,11 @@ static HRESULT d3d12_pipeline_state_init_compute(struct d3d12_pipeline_state *st target_info.environment = VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_0; target_info.extensions = device->vk_info.shader_extensions; target_info.extension_count = device->vk_info.shader_extension_count; + target_info.parameters = shader_parameters; + target_info.parameter_count = 0;
- if (root_signature->descriptor_offsets) - { - offset_info.type = VKD3D_SHADER_STRUCTURE_TYPE_DESCRIPTOR_OFFSET_INFO; - offset_info.next = NULL; - offset_info.binding_offsets = root_signature->descriptor_offsets; - offset_info.uav_counter_offsets = NULL; - vkd3d_prepend_struct(&target_info, &offset_info); - } + spirv_target_info_append_descriptor_offsets(&target_info, root_signature); + assert(target_info.parameter_count <= ARRAY_SIZE(shader_parameters));
shader_interface.type = VKD3D_SHADER_STRUCTURE_TYPE_INTERFACE_INFO; shader_interface.next = &target_info; @@ -2437,13 +2449,14 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s VkVertexInputBindingDivisorDescriptionEXT *binding_divisor; const struct vkd3d_vulkan_info *vk_info = &device->vk_info; uint32_t instance_divisors[D3D12_VS_INPUT_REGISTER_COUNT]; + struct vkd3d_shader_spirv_target_info *stage_target_info; uint32_t aligned_offsets[D3D12_VS_INPUT_REGISTER_COUNT]; - struct vkd3d_shader_parameter ps_shader_parameters[1]; + struct vkd3d_shader_parameter ps_shader_parameters[2]; 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; + struct vkd3d_shader_parameter shader_parameters[1]; + struct vkd3d_shader_spirv_target_info target_info; const struct d3d12_root_signature *root_signature; struct vkd3d_shader_signature input_signature; bool have_attachment, is_dsv_format_unknown; @@ -2624,11 +2637,24 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s ps_target_info.extensions = vk_info->shader_extensions; ps_target_info.extension_count = vk_info->shader_extension_count; ps_target_info.parameters = ps_shader_parameters; - ps_target_info.parameter_count = ARRAY_SIZE(ps_shader_parameters); + ps_target_info.parameter_count = 1; ps_target_info.dual_source_blending = is_dual_source_blending(&desc->BlendState.RenderTarget[0]); ps_target_info.output_swizzles = ps_output_swizzle; ps_target_info.output_swizzle_count = rt_count;
+ memset(&target_info, 0, sizeof(target_info)); + target_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SPIRV_TARGET_INFO; + target_info.environment = VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_0; + target_info.extensions = vk_info->shader_extensions; + target_info.extension_count = vk_info->shader_extension_count; + target_info.parameters = shader_parameters; + target_info.parameter_count = 0; + + spirv_target_info_append_descriptor_offsets(&target_info, root_signature); + assert(target_info.parameter_count <= ARRAY_SIZE(shader_parameters)); + spirv_target_info_append_descriptor_offsets(&ps_target_info, root_signature); + assert(ps_target_info.parameter_count <= ARRAY_SIZE(ps_shader_parameters)); + if (ps_target_info.dual_source_blending && rt_count > 1) { WARN("Only one render target is allowed when dual source blending is used.\n"); @@ -2692,15 +2718,6 @@ 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.binding_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 = @@ -2730,7 +2747,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
shader_interface.uav_counters = NULL; shader_interface.uav_counter_count = 0; - target_info = NULL; + stage_target_info = &target_info; switch (shader_stages[i].stage) { case VK_SHADER_STAGE_VERTEX_BIT: @@ -2757,7 +2774,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s case VK_SHADER_STAGE_FRAGMENT_BIT: shader_interface.uav_counters = state->uav_counters.bindings; shader_interface.uav_counter_count = state->uav_counters.binding_count; - target_info = &ps_target_info; + stage_target_info = &ps_target_info; break;
default: @@ -2768,8 +2785,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s shader_interface.next = NULL; if (shader_stages[i].stage == xfb_stage) vkd3d_prepend_struct(&shader_interface, &xfb_info); - if (target_info) - vkd3d_prepend_struct(&shader_interface, target_info); + vkd3d_prepend_struct(&shader_interface, stage_target_info);
if (FAILED(hr = create_shader_stage(device, &graphics->stages[graphics->stage_count], shader_stages[i].stage, b, &shader_interface)))