Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d-shader/spirv.c | 13 +++---------- tests/d3d12.c | 1 + 2 files changed, 4 insertions(+), 10 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 33e664cf..3a486d50 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -2468,6 +2468,7 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor bool is_uav_counter) { const struct vkd3d_shader_interface_info *shader_interface = &compiler->shader_interface; + unsigned int register_last = (range->last == ~0u) ? range->first : range->last; enum vkd3d_shader_descriptor_type descriptor_type; enum vkd3d_shader_binding_flag resource_type_flag; struct vkd3d_shader_descriptor_binding binding; @@ -2543,18 +2544,10 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor continue;
if (current->type != descriptor_type || current->register_space != range->space - || current->register_index != range->first) + || current->register_index > range->first + || current->binding.count <= register_last - current->register_index) continue;
- if (current->binding.count != 1) - { - FIXME("Descriptor arrays are not supported.\n"); - vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_DESCRIPTOR_BINDING, - "Descriptor binding for type %#x, space %u, register %u, " - "shader type %#x has unsupported ‘count’ %u.", - descriptor_type, range->space, range->first, compiler->shader_type, current->binding.count); - } - return current->binding; } if (shader_interface->binding_count) diff --git a/tests/d3d12.c b/tests/d3d12.c index 3a1a72a8..ab29e405 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -34624,6 +34624,7 @@ static void test_resource_arrays(void) get_cpu_descriptor_handle(&context, heap, ARRAY_SIZE(input_buffers) + i)); }
+ todo context.pipeline_state = create_compute_pipeline_state(device, context.root_signature, shader_bytecode(cs_code, sizeof(cs_code))); if (!context.pipeline_state)
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d-shader/spirv.c | 40 +++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 3a486d50..fe839adf 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -2214,6 +2214,8 @@ struct vkd3d_dxbc_compiler struct vkd3d_shader_spec_constant *spec_constants; size_t spec_constants_size; enum vkd3d_shader_compile_option_formatting_flags formatting; + + struct vkd3d_string_buffer_cache string_buffers; };
static bool is_control_point_phase(const struct vkd3d_shader_phase *phase) @@ -2336,6 +2338,8 @@ struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader
compiler->scan_descriptor_info = scan_descriptor_info;
+ vkd3d_string_buffer_cache_init(&compiler->string_buffers); + vkd3d_dxbc_compiler_emit_initial_declarations(compiler);
return compiler; @@ -2462,6 +2466,31 @@ static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_dxbc_compiler_error(struct vkd3d_dxbc_ compiler->failed = true; }
+static struct vkd3d_string_buffer *vkd3d_dxbc_compiler_binding_error(struct vkd3d_dxbc_compiler *compiler, + enum vkd3d_shader_descriptor_type descriptor_type, const struct vkd3d_shader_register_range *range) +{ + struct vkd3d_string_buffer *buffer = vkd3d_string_buffer_get(&compiler->string_buffers); + struct vkd3d_string_buffer *range_buffer = vkd3d_string_buffer_get(&compiler->string_buffers); + + if (!buffer || !range_buffer) + { + vkd3d_string_buffer_release(&compiler->string_buffers, buffer); + vkd3d_string_buffer_release(&compiler->string_buffers, range_buffer); + return NULL; + } + + if (range->last != ~0u) + vkd3d_string_buffer_printf(range_buffer, "[%u:%u]", range->first, range->last); + else + vkd3d_string_buffer_printf(range_buffer, "[%u:*]", range->first); + + vkd3d_string_buffer_printf(buffer, "Could not find descriptor binding for type %#x, space %u, registers %s, " + "shader type %#x.\n", descriptor_type, range->space, range_buffer->buffer, compiler->shader_type); + + vkd3d_string_buffer_release(&compiler->string_buffers, range_buffer); + return buffer; +} + static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor_binding( struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_register *reg, const struct vkd3d_shader_register_range *range, enum vkd3d_shader_resource_type resource_type, @@ -2552,11 +2581,12 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor } if (shader_interface->binding_count) { - FIXME("Could not find binding for type %#x, space %u, register %u, shader type %#x.\n", - descriptor_type, range->space, range->first, compiler->shader_type); + struct vkd3d_string_buffer *buffer = vkd3d_dxbc_compiler_binding_error(compiler, descriptor_type, range); + if (buffer) + FIXME(buffer->buffer); vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_BINDING_NOT_FOUND, - "Could not find descriptor binding for type %#x, space %u, register %u, shader type %#x.", - descriptor_type, range->space, range->first, compiler->shader_type); + buffer ? buffer->buffer : ""); + vkd3d_string_buffer_release(&compiler->string_buffers, buffer); } }
@@ -9479,5 +9509,7 @@ void vkd3d_dxbc_compiler_destroy(struct vkd3d_dxbc_compiler *compiler) vkd3d_free(compiler->shader_phases); vkd3d_free(compiler->spec_constants);
+ vkd3d_string_buffer_cache_cleanup(&compiler->string_buffers); + vkd3d_free(compiler); }
On Fri, 23 Jul 2021 at 15:03, Conor McCarthy cmccarthy@codeweavers.com wrote:
+static struct vkd3d_string_buffer *vkd3d_dxbc_compiler_binding_error(struct vkd3d_dxbc_compiler *compiler,
enum vkd3d_shader_descriptor_type descriptor_type, const struct vkd3d_shader_register_range *range)
+{
- struct vkd3d_string_buffer *buffer = vkd3d_string_buffer_get(&compiler->string_buffers);
- struct vkd3d_string_buffer *range_buffer = vkd3d_string_buffer_get(&compiler->string_buffers);
- if (!buffer || !range_buffer)
- {
vkd3d_string_buffer_release(&compiler->string_buffers, buffer);
vkd3d_string_buffer_release(&compiler->string_buffers, range_buffer);
return NULL;
- }
- if (range->last != ~0u)
vkd3d_string_buffer_printf(range_buffer, "[%u:%u]", range->first, range->last);
- else
vkd3d_string_buffer_printf(range_buffer, "[%u:*]", range->first);
- vkd3d_string_buffer_printf(buffer, "Could not find descriptor binding for type %#x, space %u, registers %s, "
"shader type %#x.\n", descriptor_type, range->space, range_buffer->buffer, compiler->shader_type);
- vkd3d_string_buffer_release(&compiler->string_buffers, range_buffer);
- return buffer;
+}
Compiler error messages don't need explicit newlines; adding the \n will introduce an extra empty line. Note that if we're going to have a helper for generating the error message, we may as well call vkd3d_dxbc_compiler_error() here as well.
@@ -2552,11 +2581,12 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor } if (shader_interface->binding_count) {
FIXME("Could not find binding for type %#x, space %u, register %u, shader type %#x.\n",
descriptor_type, range->space, range->first, compiler->shader_type);
struct vkd3d_string_buffer *buffer = vkd3d_dxbc_compiler_binding_error(compiler, descriptor_type, range);
if (buffer)
FIXME(buffer->buffer); vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_BINDING_NOT_FOUND,
"Could not find descriptor binding for type %#x, space %u, register %u, shader type %#x.",
descriptor_type, range->space, range->first, compiler->shader_type);
buffer ? buffer->buffer : "");
}vkd3d_string_buffer_release(&compiler->string_buffers, buffer); }
It should work out here in practice, but note that it's generally unsafe to pass arbitrary strings as format strings to printf() style functions. (E.g., consider what would happen when the contents of buffer->buffer would be "%s".)
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d-shader/spirv.c | 137 ++++++++++++++++++++--- libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 2 files changed, 125 insertions(+), 13 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index fe839adf..d4debc86 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -1,5 +1,6 @@ /* * Copyright 2017 Józef Kucia for CodeWeavers + * Copyright 2021 Conor McCarthy for Codeweavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -1920,6 +1921,13 @@ struct vkd3d_symbol_combined_sampler unsigned int sampler_index; };
+struct vkd3d_symbol_descriptor_array +{ + uint32_t ptr_type_id; + unsigned int set; + unsigned int binding; +}; + struct vkd3d_symbol_register_data { SpvStorageClass storage_class; @@ -1948,6 +1956,13 @@ struct vkd3d_symbol_sampler_data struct vkd3d_shader_register_range range; };
+struct vkd3d_symbol_descriptor_array_data +{ + SpvStorageClass storage_class; + uint32_t contained_type_id; + unsigned int binding_base_idx; +}; + struct vkd3d_symbol { struct rb_entry entry; @@ -1958,6 +1973,7 @@ struct vkd3d_symbol VKD3D_SYMBOL_RESOURCE, VKD3D_SYMBOL_SAMPLER, VKD3D_SYMBOL_COMBINED_SAMPLER, + VKD3D_SYMBOL_DESCRIPTOR_ARRAY, } type;
union @@ -1966,14 +1982,19 @@ struct vkd3d_symbol struct vkd3d_symbol_resource resource; struct vkd3d_symbol_sampler sampler; struct vkd3d_symbol_combined_sampler combined_sampler; + struct vkd3d_symbol_descriptor_array descriptor_array; } key;
uint32_t id; + /* The array declaration which this symbol maps to, or NULL. */ + const struct vkd3d_symbol *descriptor_array; + union { struct vkd3d_symbol_register_data reg; struct vkd3d_symbol_resource_data resource; struct vkd3d_symbol_sampler_data sampler; + struct vkd3d_symbol_descriptor_array_data descriptor_array; } info; };
@@ -2011,6 +2032,7 @@ 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->info.reg.storage_class = storage_class; symbol->info.reg.member_idx = 0; symbol->info.reg.component_type = component_type; @@ -2494,7 +2516,7 @@ static struct vkd3d_string_buffer *vkd3d_dxbc_compiler_binding_error(struct vkd3 static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor_binding( struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_register *reg, const struct vkd3d_shader_register_range *range, enum vkd3d_shader_resource_type resource_type, - bool is_uav_counter) + bool is_uav_counter, unsigned int *binding_base_idx) { const struct vkd3d_shader_interface_info *shader_interface = &compiler->shader_interface; unsigned int register_last = (range->last == ~0u) ? range->first : range->last; @@ -2551,6 +2573,7 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor range->first, range->space, current->binding.count); }
+ *binding_base_idx = current->register_index; return current->binding; } if (shader_interface->uav_counter_count) @@ -2577,6 +2600,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; return current->binding; } if (shader_interface->binding_count) @@ -2591,6 +2615,7 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor }
done: + *binding_base_idx = range->first; binding.set = 0; binding.count = 1; binding.binding = compiler->binding_idx++; @@ -2611,12 +2636,14 @@ static void vkd3d_dxbc_compiler_emit_descriptor_binding_for_reg(struct vkd3d_dxb enum vkd3d_shader_resource_type resource_type, bool is_uav_counter) { struct vkd3d_shader_descriptor_binding binding; + unsigned int binding_base_idx; /* Value not used. */
- binding = vkd3d_dxbc_compiler_get_descriptor_binding(compiler, reg, range, resource_type, is_uav_counter); + binding = vkd3d_dxbc_compiler_get_descriptor_binding(compiler, reg, range, resource_type, is_uav_counter, + &binding_base_idx); vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, variable_id, &binding); }
-static void vkd3d_dxbc_compiler_put_symbol(struct vkd3d_dxbc_compiler *compiler, +static const struct vkd3d_symbol *vkd3d_dxbc_compiler_put_symbol(struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_symbol *symbol) { struct vkd3d_symbol *s; @@ -2626,7 +2653,9 @@ static void vkd3d_dxbc_compiler_put_symbol(struct vkd3d_dxbc_compiler *compiler, { ERR("Failed to insert symbol entry (%s).\n", debug_vkd3d_symbol(symbol)); vkd3d_free(s); + return NULL; } + return s; }
static uint32_t vkd3d_dxbc_compiler_get_constant(struct vkd3d_dxbc_compiler *compiler, @@ -3017,6 +3046,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; SpvStorageClass storage_class; enum vkd3d_shader_component_type component_type; unsigned int write_mask; @@ -3039,6 +3069,7 @@ 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->member_idx = 0; register_info->component_type = VKD3D_SHADER_COMPONENT_FLOAT; register_info->write_mask = VKD3DSP_WRITEMASK_ALL; @@ -3058,6 +3089,7 @@ static bool vkd3d_dxbc_compiler_get_register_info(const struct vkd3d_dxbc_compil
symbol = RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry); register_info->id = symbol->id; + register_info->descriptor_array = symbol->descriptor_array; register_info->storage_class = symbol->info.reg.storage_class; register_info->member_idx = symbol->info.reg.member_idx; register_info->component_type = symbol->info.reg.component_type; @@ -3084,17 +3116,40 @@ static bool register_is_descriptor(const struct vkd3d_shader_register *reg) } }
+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) +{ + struct vkd3d_shader_register_index index = reg->idx[1]; + uint32_t index_id; + + if (index.rel_addr) + { + FIXME("Descriptor dynamic indexing is not supported.\n"); + vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_IDX_UNSUPPORTED, + "Cannot dynamically index a descriptor array of type %#x, id %u. " + "Dynamic indexing is not supported.", reg->type, reg->idx[0].offset); + } + + index.offset -= binding_base_idx; + index_id = vkd3d_dxbc_compiler_emit_register_addressing(compiler, &index); + + return index_id; +} + static void vkd3d_dxbc_compiler_emit_dereference_register(struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_register *reg, struct vkd3d_shader_register_info *register_info) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; unsigned int component_count, index_count = 0; uint32_t type_id, ptr_type_id; - uint32_t indexes[2]; + uint32_t indexes[3];
if (reg->type == VKD3DSPR_CONSTBUFFER) { assert(!reg->idx[0].rel_addr); + if (register_info->descriptor_array) + indexes[index_count++] = vkd3d_dxbc_compiler_get_descriptor_index(compiler, reg, + register_info->descriptor_array->info.descriptor_array.binding_base_idx); indexes[index_count++] = vkd3d_dxbc_compiler_get_constant_uint(compiler, register_info->member_idx); indexes[index_count++] = vkd3d_dxbc_compiler_emit_register_addressing(compiler, ®->idx[2]); } @@ -5298,15 +5353,76 @@ 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_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); + + if (binding.count == 1 && range->last != ~0u) + { + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); + var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, + ptr_type_id, storage_class, 0); + + vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, var_id, &binding); + vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg); + + *array_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)); + 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 + * all array declarations which map to it. */ + symbol.type = VKD3D_SYMBOL_DESCRIPTOR_ARRAY; + memset(&symbol.key, 0, sizeof(symbol.key)); + symbol.key.descriptor_array.ptr_type_id = ptr_type_id; + symbol.key.descriptor_array.set = binding.set; + 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; + } + + var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, + ptr_type_id, storage_class, 0); + vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, var_id, &binding); + vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg); + + symbol.id = var_id; + symbol.descriptor_array = NULL; + 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); + + return var_id; +} + static void vkd3d_dxbc_compiler_emit_dcl_constant_buffer(struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { - uint32_t vec4_id, array_type_id, length_id, struct_id, pointer_type_id, var_id; const struct vkd3d_shader_constant_buffer *cb = &instruction->declaration.cb; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t vec4_id, array_type_id, length_id, struct_id, var_id; 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_symbol reg_symbol;
assert(!(instruction->flags & ~VKD3DSI_INDEXED_DYNAMIC)); @@ -5337,18 +5453,13 @@ static void vkd3d_dxbc_compiler_emit_dcl_constant_buffer(struct vkd3d_dxbc_compi vkd3d_spirv_build_op_member_decorate1(builder, struct_id, 0, SpvDecorationOffset, 0); vkd3d_spirv_build_op_name(builder, struct_id, "cb%u_struct", cb->size);
- pointer_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, struct_id); - var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, - pointer_type_id, storage_class, 0); - - vkd3d_dxbc_compiler_emit_descriptor_binding_for_reg(compiler, - var_id, reg, &cb->range, VKD3D_SHADER_RESOURCE_BUFFER, false); - - vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg); + var_id = vkd3d_dxbc_compiler_build_descriptor_variable(compiler, storage_class, struct_id, + reg, &cb->range, VKD3D_SHADER_RESOURCE_BUFFER, &array_symbol);
vkd3d_symbol_make_register(®_symbol, reg); vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class, VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL); + reg_symbol.descriptor_array = array_symbol; vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol); }
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index f5d22c5c..b247acc0 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -74,6 +74,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_BINDING_NOT_FOUND = 2000, VKD3D_SHADER_ERROR_SPV_INVALID_REGISTER_TYPE = 2001, VKD3D_SHADER_ERROR_SPV_INVALID_DESCRIPTOR_BINDING = 2002, + VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_IDX_UNSUPPORTED = 2003,
VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY = 3000, VKD3D_SHADER_ERROR_RS_INVALID_VERSION = 3001,
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- include/vkd3d_shader.h | 5 ++++- libs/vkd3d-shader/spirv.c | 4 +++- libs/vkd3d-shader/vkd3d_shader_main.c | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 0e011343..6cdbaf1e 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -1137,7 +1137,10 @@ struct vkd3d_shader_descriptor_info * \ref vkd3d_shader_descriptor_info_flag. */ unsigned int flags; - /** Size of this descriptor array, or 1 if a single descriptor. */ + /** + * Size of this descriptor array, or 1 if a single descriptor. + * For an unbounded array this value is ~0u. + */ unsigned int count; };
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index d4debc86..ac88e283 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -5571,13 +5571,15 @@ static const struct vkd3d_shader_descriptor_info *vkd3d_dxbc_compiler_get_descri const struct vkd3d_shader_register_range *range) { const struct vkd3d_shader_scan_descriptor_info *descriptor_info = compiler->scan_descriptor_info; + unsigned int register_last = (range->last == ~0u) ? range->first : range->last; const struct vkd3d_shader_descriptor_info *d; unsigned int i;
for (i = 0; i < descriptor_info->descriptor_count; ++i) { d = &descriptor_info->descriptors[i]; - if (d->type == type && d->register_space == range->space && d->register_index == range->first) + if (d->type == type && d->register_space == range->space && d->register_index <= range->first + && (d->count == ~0u || d->count > register_last - d->register_index)) return d; }
diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 54654f3f..1a566a7b 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -601,7 +601,7 @@ static bool vkd3d_shader_scan_add_descriptor(struct vkd3d_shader_scan_context *c d->resource_type = resource_type; d->resource_data_type = resource_data_type; d->flags = flags; - d->count = 1; + d->count = (range->last == ~0u) ? ~0u : range->last - range->first + 1; ++info->descriptor_count;
return true;
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d-shader/spirv.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index ac88e283..e2b01b14 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -5705,6 +5705,7 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp const struct vkd3d_shader_register *reg = &resource->reg.reg; const struct vkd3d_spirv_resource_type *resource_type_info; enum vkd3d_shader_component_type sampled_type; + const struct vkd3d_symbol *array_symbol; struct vkd3d_symbol resource_symbol; bool is_uav;
@@ -5747,14 +5748,8 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp resource_type_info, sampled_type, structure_stride || raw, 0); }
- ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); - var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, - ptr_type_id, storage_class, 0); - - vkd3d_dxbc_compiler_emit_descriptor_binding_for_reg(compiler, var_id, reg, - &resource->range, resource_type, false); - - vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg); + var_id = vkd3d_dxbc_compiler_build_descriptor_variable(compiler, storage_class, type_id, reg, + &resource->range, resource_type, &array_symbol);
if (is_uav) { @@ -5792,6 +5787,10 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp storage_class = SpvStorageClassUniform; ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, struct_id); } + else + { + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); + }
counter_var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, ptr_type_id, storage_class, 0); @@ -5805,6 +5804,7 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp
vkd3d_symbol_make_resource(&resource_symbol, reg); resource_symbol.id = var_id; + resource_symbol.descriptor_array = array_symbol; resource_symbol.info.resource.range = resource->range; resource_symbol.info.resource.sampled_type = sampled_type; resource_symbol.info.resource.type_id = type_id; @@ -7800,9 +7800,26 @@ static void vkd3d_dxbc_compiler_prepare_image(struct vkd3d_dxbc_compiler *compil if (!symbol) symbol = vkd3d_dxbc_compiler_find_resource(compiler, resource_reg);
- image->id = symbol->id; + if (symbol->descriptor_array) + { + const struct vkd3d_symbol_descriptor_array_data *array_data = &symbol->descriptor_array->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); + + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, array_data->storage_class, + array_data->contained_type_id); + image->image_type_id = array_data->contained_type_id; + + image->id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, symbol->id, &index_id, 1); + } + else + { + image->id = symbol->id; + image->image_type_id = symbol->info.resource.type_id; + } image->sampled_type = symbol->info.resource.sampled_type; - image->image_type_id = symbol->info.resource.type_id; image->resource_type_info = symbol->info.resource.resource_type_info; image->structure_stride = symbol->info.resource.structure_stride; image->raw = symbol->info.resource.raw;
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com