[PATCH vkd3d 1/4] vkd3d-shader/spirv: Use runtime descriptor arrays.

Conor McCarthy cmccarthy at codeweavers.com
Wed Nov 10 01:03:14 CST 2021


Runtime descriptor arrays should be used for descriptor bindings with
a variable count.

Support for SpvCapabilityRuntimeDescriptorArrayEXT is required by the
Vulkan spec as part of descriptor indexing support.

The current implementation depends on a separate array declaration for
each range because binding_base_idx is stored in the array data. This
occurs in practice because binding.count is always different. Use of
runtime arrays eliminates the count from the key, so binding_base_idx
must be separated from the array data.

Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
 libs/vkd3d-shader/spirv.c | 70 ++++++++++++++++++++++-----------------
 1 file changed, 39 insertions(+), 31 deletions(-)

diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c
index 698c3054..dbe741ab 100644
--- a/libs/vkd3d-shader/spirv.c
+++ b/libs/vkd3d-shader/spirv.c
@@ -1972,6 +1972,14 @@ struct vkd3d_symbol_register_data
     bool is_dynamically_indexed; /* If member_idx is a variable ID instead of a constant. */
 };
 
+struct vkd3d_symbol;
+
+struct vkd3d_descriptor_array_symbol
+{
+    const struct vkd3d_symbol *symbol;
+    unsigned int binding_base_idx;
+};
+
 struct vkd3d_symbol_resource_data
 {
     struct vkd3d_shader_register_range range;
@@ -1992,7 +2000,6 @@ struct vkd3d_symbol_descriptor_array_data
 {
     SpvStorageClass storage_class;
     uint32_t contained_type_id;
-    unsigned int binding_base_idx;
 };
 
 struct vkd3d_symbol
@@ -2018,8 +2025,8 @@ struct vkd3d_symbol
     } key;
 
     uint32_t id;
-    /* The array declaration which this symbol maps to, or NULL. */
-    const struct vkd3d_symbol *descriptor_array;
+    /* descriptor_array.symbol is the array declaration which this symbol maps to, or NULL. */
+    struct vkd3d_descriptor_array_symbol descriptor_array;
 
     union
     {
@@ -2064,7 +2071,8 @@ static void vkd3d_symbol_set_register_info(struct vkd3d_symbol *symbol,
         enum vkd3d_shader_component_type component_type, DWORD write_mask)
 {
     symbol->id = val_id;
-    symbol->descriptor_array = NULL;
+    symbol->descriptor_array.symbol = NULL;
+    symbol->descriptor_array.binding_base_idx = 0;
     symbol->info.reg.storage_class = storage_class;
     symbol->info.reg.member_idx = 0;
     symbol->info.reg.component_type = component_type;
@@ -3135,7 +3143,7 @@ static uint32_t vkd3d_dxbc_compiler_emit_register_addressing(struct vkd3d_dxbc_c
 struct vkd3d_shader_register_info
 {
     uint32_t id;
-    const struct vkd3d_symbol *descriptor_array;
+    struct vkd3d_descriptor_array_symbol descriptor_array;
     SpvStorageClass storage_class;
     enum vkd3d_shader_component_type component_type;
     unsigned int write_mask;
@@ -3158,7 +3166,8 @@ static bool vkd3d_dxbc_compiler_get_register_info(const struct vkd3d_dxbc_compil
         assert(reg->idx[0].offset < compiler->temp_count);
         register_info->id = compiler->temp_id + reg->idx[0].offset;
         register_info->storage_class = SpvStorageClassFunction;
-        register_info->descriptor_array = NULL;
+        register_info->descriptor_array.symbol = NULL;
+        register_info->descriptor_array.binding_base_idx = 0;
         register_info->member_idx = 0;
         register_info->component_type = VKD3D_SHADER_COMPONENT_FLOAT;
         register_info->write_mask = VKD3DSP_WRITEMASK_ALL;
@@ -3243,7 +3252,7 @@ static bool vkd3d_dxbc_compiler_enable_descriptor_indexing(struct vkd3d_dxbc_com
 }
 
 static uint32_t vkd3d_dxbc_compiler_get_descriptor_index(struct vkd3d_dxbc_compiler *compiler,
-        const struct vkd3d_shader_register *reg, unsigned int binding_base_idx,
+        const struct vkd3d_shader_register *reg, const struct vkd3d_descriptor_array_symbol *array_symbol,
         enum vkd3d_shader_resource_type resource_type)
 {
     struct vkd3d_shader_register_index index = reg->idx[1];
@@ -3260,7 +3269,7 @@ static uint32_t vkd3d_dxbc_compiler_get_descriptor_index(struct vkd3d_dxbc_compi
         }
     }
 
-    index.offset -= binding_base_idx;
+    index.offset -= array_symbol->binding_base_idx;
     index_id = vkd3d_dxbc_compiler_emit_register_addressing(compiler, &index);
 
     return index_id;
@@ -3277,10 +3286,9 @@ static void vkd3d_dxbc_compiler_emit_dereference_register(struct vkd3d_dxbc_comp
     if (reg->type == VKD3DSPR_CONSTBUFFER)
     {
         assert(!reg->idx[0].rel_addr);
-        if (register_info->descriptor_array)
+        if (register_info->descriptor_array.symbol)
             indexes[index_count++] = vkd3d_dxbc_compiler_get_descriptor_index(compiler, reg,
-                    register_info->descriptor_array->info.descriptor_array.binding_base_idx,
-                    VKD3D_SHADER_RESOURCE_BUFFER);
+                    &register_info->descriptor_array, VKD3D_SHADER_RESOURCE_BUFFER);
         indexes[index_count++] = vkd3d_dxbc_compiler_get_constant_uint(compiler, register_info->member_idx);
         indexes[index_count++] = vkd3d_dxbc_compiler_emit_register_addressing(compiler, &reg->idx[2]);
     }
@@ -5543,17 +5551,16 @@ static void vkd3d_dxbc_compiler_emit_push_constant_buffers(struct vkd3d_dxbc_com
 static uint32_t vkd3d_dxbc_compiler_build_descriptor_variable(struct vkd3d_dxbc_compiler *compiler,
         SpvStorageClass storage_class, uint32_t type_id, const struct vkd3d_shader_register *reg,
         const struct vkd3d_shader_register_range *range, enum vkd3d_shader_resource_type resource_type,
-        const struct vkd3d_symbol **array_symbol)
+        struct vkd3d_descriptor_array_symbol *array_symbol)
 {
     struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
     struct vkd3d_shader_descriptor_binding binding;
     uint32_t array_type_id, ptr_type_id, var_id;
-    unsigned int binding_base_idx;
     struct vkd3d_symbol symbol;
     struct rb_entry *entry;
 
     binding = vkd3d_dxbc_compiler_get_descriptor_binding(compiler, reg, range,
-            resource_type, false, &binding_base_idx);
+            resource_type, false, &array_symbol->binding_base_idx);
 
     if (binding.count == 1 && range->last != ~0u)
     {
@@ -5564,12 +5571,12 @@ static uint32_t vkd3d_dxbc_compiler_build_descriptor_variable(struct vkd3d_dxbc_
         vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, var_id, &binding);
         vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg);
 
-        *array_symbol = NULL;
+        array_symbol->symbol = NULL;
         return var_id;
     }
 
-    array_type_id = vkd3d_spirv_get_op_type_array(builder, type_id,
-            vkd3d_dxbc_compiler_get_constant_uint(compiler, binding.count));
+    array_type_id = vkd3d_spirv_get_op_type_runtime_array(builder, type_id);
+    vkd3d_spirv_enable_capability(builder, SpvCapabilityRuntimeDescriptorArrayEXT);
     ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, array_type_id);
 
     /* Declare one array variable per Vulkan binding, and use it for
@@ -5581,8 +5588,8 @@ static uint32_t vkd3d_dxbc_compiler_build_descriptor_variable(struct vkd3d_dxbc_
     symbol.key.descriptor_array.binding = binding.binding;
     if ((entry = rb_get(&compiler->symbol_table, &symbol)))
     {
-        *array_symbol = RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry);
-        return (*array_symbol)->id;
+        array_symbol->symbol = RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry);
+        return array_symbol->symbol->id;
     }
 
     var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
@@ -5591,11 +5598,11 @@ static uint32_t vkd3d_dxbc_compiler_build_descriptor_variable(struct vkd3d_dxbc_
     vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg);
 
     symbol.id = var_id;
-    symbol.descriptor_array = NULL;
+    symbol.descriptor_array.symbol = NULL;
+    symbol.descriptor_array.binding_base_idx = 0;
     symbol.info.descriptor_array.storage_class = storage_class;
     symbol.info.descriptor_array.contained_type_id = type_id;
-    symbol.info.descriptor_array.binding_base_idx = binding_base_idx;
-    *array_symbol = vkd3d_dxbc_compiler_put_symbol(compiler, &symbol);
+    array_symbol->symbol = vkd3d_dxbc_compiler_put_symbol(compiler, &symbol);
 
     return var_id;
 }
@@ -5609,7 +5616,7 @@ static void vkd3d_dxbc_compiler_emit_dcl_constant_buffer(struct vkd3d_dxbc_compi
     const SpvStorageClass storage_class = SpvStorageClassUniform;
     const struct vkd3d_shader_register *reg = &cb->src.reg;
     struct vkd3d_push_constant_buffer_binding *push_cb;
-    const struct vkd3d_symbol *array_symbol;
+    struct vkd3d_descriptor_array_symbol array_symbol;
     struct vkd3d_symbol reg_symbol;
 
     assert(!(instruction->flags & ~VKD3DSI_INDEXED_DYNAMIC));
@@ -5690,7 +5697,7 @@ static void vkd3d_dxbc_compiler_emit_dcl_sampler(struct vkd3d_dxbc_compiler *com
     const SpvStorageClass storage_class = SpvStorageClassUniformConstant;
     struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
     const struct vkd3d_shader_register *reg = &sampler->src.reg;
-    const struct vkd3d_symbol *array_symbol;
+    struct vkd3d_descriptor_array_symbol array_symbol;
     struct vkd3d_symbol reg_symbol;
     uint32_t type_id, var_id;
 
@@ -5887,8 +5894,8 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp
     SpvStorageClass storage_class = SpvStorageClassUniformConstant;
     const struct vkd3d_shader_register *reg = &resource->reg.reg;
     const struct vkd3d_spirv_resource_type *resource_type_info;
+    struct vkd3d_descriptor_array_symbol array_symbol;
     enum vkd3d_shader_component_type sampled_type;
-    const struct vkd3d_symbol *array_symbol;
     struct vkd3d_symbol resource_symbol;
     bool is_uav;
 
@@ -8022,13 +8029,14 @@ static void vkd3d_dxbc_compiler_prepare_image(struct vkd3d_dxbc_compiler *compil
     if (!symbol)
         symbol = vkd3d_dxbc_compiler_find_resource(compiler, resource_reg);
 
-    if (symbol->descriptor_array)
+    if (symbol->descriptor_array.symbol)
     {
-        const struct vkd3d_symbol_descriptor_array_data *array_data = &symbol->descriptor_array->info.descriptor_array;
+        const struct vkd3d_symbol_descriptor_array_data *array_data
+                = &symbol->descriptor_array.symbol->info.descriptor_array;
         uint32_t ptr_type_id, index_id;
 
         index_id = vkd3d_dxbc_compiler_get_descriptor_index(compiler, resource_reg,
-                array_data->binding_base_idx, symbol->info.resource.resource_type_info->resource_type);
+                &symbol->descriptor_array, symbol->info.resource.resource_type_info->resource_type);
 
         ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, array_data->storage_class,
                 array_data->contained_type_id);
@@ -8081,14 +8089,14 @@ static void vkd3d_dxbc_compiler_prepare_image(struct vkd3d_dxbc_compiler *compil
         if (!vkd3d_dxbc_compiler_get_register_info(compiler, sampler_reg, &register_info))
             ERR("Failed to get sampler register info.\n");
         sampler_var_id = register_info.id;
-        if (register_info.descriptor_array)
+        if (register_info.descriptor_array.symbol)
         {
             const struct vkd3d_symbol_descriptor_array_data *array_data
-                    = &register_info.descriptor_array->info.descriptor_array;
+                    = &register_info.descriptor_array.symbol->info.descriptor_array;
             uint32_t ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder,
                     register_info.storage_class, array_data->contained_type_id);
             uint32_t array_idx = vkd3d_dxbc_compiler_get_descriptor_index(compiler,
-                    sampler_reg, array_data->binding_base_idx, VKD3D_SHADER_RESOURCE_NONE);
+                    sampler_reg, &register_info.descriptor_array, VKD3D_SHADER_RESOURCE_NONE);
             sampler_var_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, register_info.id, &array_idx, 1);
         }
 
-- 
2.32.0




More information about the wine-devel mailing list