[PATCH vkd3d 3/5] vkd3d-shader/spirv: Send descriptor offsets via a shader parameter.

Conor McCarthy cmccarthy at codeweavers.com
Tue Nov 23 08:41:35 CST 2021


Signed-off-by: Conor McCarthy <cmccarthy at 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)))
-- 
2.33.0




More information about the wine-devel mailing list