From: Conor McCarthy cmccarthy@codeweavers.com
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d-shader/spirv.c | 22 ++++++++++------------ tests/d3d12.c | 1 + 2 files changed, 11 insertions(+), 12 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index bd231124..6576aca4 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -2463,9 +2463,10 @@ static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_dxbc_compiler_error(struct vkd3d_dxbc_ 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; enum vkd3d_shader_descriptor_type descriptor_type; enum vkd3d_shader_binding_flag resource_type_flag; struct vkd3d_shader_descriptor_binding binding; @@ -2519,6 +2520,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) @@ -2541,18 +2543,11 @@ 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); - } - + *binding_base_idx = current->register_index; return current->binding; } if (shader_interface->binding_count) @@ -2566,6 +2561,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++; @@ -2586,8 +2582,10 @@ 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); }
diff --git a/tests/d3d12.c b/tests/d3d12.c index 3892c1db..a84a8e28 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -34103,6 +34103,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)
From: Conor McCarthy cmccarthy@codeweavers.com
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d-shader/spirv.c | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 6576aca4..991ff82f 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -2212,6 +2212,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) @@ -2334,6 +2336,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; @@ -2460,6 +2464,26 @@ 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); + char range_string[24]; + + if (!buffer) + return NULL; + + if (range->last != ~0u) + sprintf(range_string, "[%u:%u]", range->first, range->last); + else + sprintf(range_string, "[%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_string, compiler->shader_type); + + 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 +2576,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); } }
@@ -9470,5 +9495,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 Mon, 19 Jul 2021 at 09:22, Conor McCarthy conor.mccarthy6@bigpond.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);
- char range_string[24];
- if (!buffer)
return NULL;
- if (range->last != ~0u)
sprintf(range_string, "[%u:%u]", range->first, range->last);
- else
sprintf(range_string, "[%u:*]", range->first);
One of the major advantages of string buffers is not having to sprintf() to fixed size stack buffers.
From: Conor McCarthy cmccarthy@codeweavers.com
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, 127 insertions(+), 11 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 991ff82f..95b7383b 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 @@ -1918,6 +1919,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; @@ -1946,6 +1954,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; @@ -1956,6 +1971,7 @@ struct vkd3d_symbol VKD3D_SYMBOL_RESOURCE, VKD3D_SYMBOL_SAMPLER, VKD3D_SYMBOL_COMBINED_SAMPLER, + VKD3D_SYMBOL_DESCRIPTOR_ARRAY, } type;
union @@ -1964,14 +1980,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; };
@@ -2009,6 +2030,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; @@ -2614,7 +2636,7 @@ static void vkd3d_dxbc_compiler_emit_descriptor_binding_for_reg(struct vkd3d_dxb 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; @@ -2624,7 +2646,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, @@ -3015,6 +3039,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; @@ -3037,6 +3062,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; @@ -3056,6 +3082,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; @@ -3082,17 +3109,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]); } @@ -5286,15 +5336,85 @@ 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, + bool is_uav_counter, const struct vkd3d_symbol **array_symbol) +{ + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + struct vkd3d_shader_descriptor_binding binding; + struct vkd3d_symbol *array_symbol_entry; + unsigned int binding_base_idx; + struct vkd3d_symbol symbol; + struct rb_entry *entry; + uint32_t ptr_type_id; + bool array_variable; + + binding = vkd3d_dxbc_compiler_get_descriptor_binding(compiler, reg, range, + resource_type, is_uav_counter, &binding_base_idx); + + array_variable = binding.count != 1 || range->last == ~0u; + /* TODO: UAV counter descriptor arrays. */ + array_variable &= !is_uav_counter; + + if (array_variable) + { + symbol.info.descriptor_array.contained_type_id = type_id; + 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, type_id); + + if (!array_variable) + { + uint32_t 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; + } + + /* Declare one array variable per Vulkan binding, and use it for all array declarations + * which map to it. In this case ptr_type_id must point to an array type. */ + 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_entry = RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry); + *array_symbol = array_symbol_entry; + return array_symbol_entry->id; + } + + symbol.id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, + ptr_type_id, storage_class, 0); + vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, symbol.id, &binding); + vkd3d_dxbc_compiler_emit_register_debug_name(builder, symbol.id, reg); + + symbol.descriptor_array = NULL; + symbol.info.descriptor_array.storage_class = storage_class; + symbol.info.descriptor_array.binding_base_idx = binding_base_idx; + *array_symbol = vkd3d_dxbc_compiler_put_symbol(compiler, &symbol); + + return symbol.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)); @@ -5325,18 +5445,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, false, &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 c5d1372a..f62d2d48 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,
On Mon, 19 Jul 2021 at 09:22, Conor McCarthy conor.mccarthy6@bigpond.com wrote:
+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,
bool is_uav_counter, const struct vkd3d_symbol **array_symbol)
+{
The "is_uav_counter" parameter is always false. (At least, until patch 6/6 in this series.)
- if (array_variable)
- {
symbol.info.descriptor_array.contained_type_id = type_id;
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, type_id);
- if (!array_variable)
- {
uint32_t 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;
- }
"type_id" stores different things depending on whether "array_variable" is true or not, and I don't think it's making the code any clearer. It may be clearer to introduce a separate variable for the array type id. I.e., like this:
if (!array_variable) { ptr_type_id = vkd3d_spirv_build_op_variable(..., type_id); ... return var_id; }
array_type_id = vkd3d_spirv_get_op_type_array(...); ptr_type_id = vkd3d_spirv_build_op_variable(..., array_type_id);
... return var_id;
- /* Declare one array variable per Vulkan binding, and use it for all array declarations
* which map to it. In this case ptr_type_id must point to an array type. */
- 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_entry = RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry);
*array_symbol = array_symbol_entry;
return array_symbol_entry->id;
- }
*array_symbol = RB_ENTRY_VALUE(...); return (*array_symbol)->id;
right?
From: Conor McCarthy cmccarthy@codeweavers.com
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d-shader/spirv.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 95b7383b..07e79111 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -5495,8 +5495,9 @@ 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; - uint32_t type_id, ptr_type_id, var_id; + const struct vkd3d_symbol *array_symbol; struct vkd3d_symbol reg_symbol; + uint32_t type_id, var_id;
vkd3d_symbol_make_sampler(®_symbol, reg); reg_symbol.info.sampler.range = sampler->range; @@ -5506,18 +5507,13 @@ static void vkd3d_dxbc_compiler_emit_dcl_sampler(struct vkd3d_dxbc_compiler *com return;
type_id = vkd3d_spirv_get_op_type_sampler(builder); - 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, - &sampler->range, VKD3D_SHADER_RESOURCE_NONE, 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, + &sampler->range, VKD3D_SHADER_RESOURCE_NONE, false, &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); }
@@ -7815,10 +7811,24 @@ static void vkd3d_dxbc_compiler_prepare_image(struct vkd3d_dxbc_compiler *compil
if (sampled) { + struct vkd3d_shader_register_info register_info; + assert(image->image_id); assert(sampler_reg);
- sampler_var_id = vkd3d_dxbc_compiler_get_register_id(compiler, sampler_reg); + if (!vkd3d_dxbc_compiler_get_register_info(compiler, sampler_reg, ®ister_info)) + ERR("Failed to get sampler register info.\n"); + sampler_var_id = register_info.id; + if (register_info.descriptor_array) + { + const struct vkd3d_symbol_descriptor_array_data *array_data + = ®ister_info.descriptor_array->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); + sampler_var_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, register_info.id, &array_idx, 1); + }
sampler_id = vkd3d_spirv_build_op_load(builder, vkd3d_spirv_get_op_type_sampler(builder), sampler_var_id, SpvMemoryAccessMaskNone);
From: Conor McCarthy cmccarthy@codeweavers.com
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- include/vkd3d_shader.h | 3 ++- libs/vkd3d-shader/spirv.c | 4 +++- libs/vkd3d-shader/vkd3d_shader_main.c | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 03225d37..77758a2b 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -1137,7 +1137,8 @@ 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 07e79111..98714faa 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -5559,13 +5559,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;
On Mon, 19 Jul 2021 at 09:22, Conor McCarthy conor.mccarthy6@bigpond.com wrote:
@@ -1137,7 +1137,8 @@ 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.
unsigned int count;** For an unbounded array this value is ~0u. */
};
You have an extra "*" there.
From: Conor McCarthy cmccarthy@codeweavers.com
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- include/vkd3d_shader.h | 6 ++- libs/vkd3d-shader/spirv.c | 77 ++++++++++++++++++++------------------- 2 files changed, 43 insertions(+), 40 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 77758a2b..4593fcec 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -208,8 +208,10 @@ 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. Descriptor arrays are supported in + * this version of vkd3d-shader for all descriptor types except UAV + * counters and combined resource/sampler descriptors. For such bindings + * this value must be 1. Dynamic array indexing is not supported. */ unsigned int count; }; diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 98714faa..f00b5cd8 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -2624,18 +2624,6 @@ static void vkd3d_dxbc_compiler_emit_descriptor_binding(struct vkd3d_dxbc_compil vkd3d_spirv_build_op_decorate1(builder, variable_id, SpvDecorationBinding, binding->binding); }
-static void vkd3d_dxbc_compiler_emit_descriptor_binding_for_reg(struct vkd3d_dxbc_compiler *compiler, - uint32_t variable_id, const struct vkd3d_shader_register *reg, const struct vkd3d_shader_register_range *range, - 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_base_idx); - vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, variable_id, &binding); -} - static const struct vkd3d_symbol *vkd3d_dxbc_compiler_put_symbol(struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_symbol *symbol) { @@ -5687,12 +5675,13 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp const struct vkd3d_shader_resource *resource, enum vkd3d_shader_resource_type resource_type, enum vkd3d_data_type resource_data_type, unsigned int structure_stride, bool raw) { - uint32_t counter_type_id, type_id, ptr_type_id, var_id, counter_var_id = 0; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; SpvStorageClass storage_class = SpvStorageClassUniformConstant; + uint32_t counter_type_id, type_id, var_id, counter_var_id = 0; 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;
@@ -5735,17 +5724,12 @@ 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, false, &array_symbol);
if (is_uav) { + const struct vkd3d_symbol *counter_array_symbol; const struct vkd3d_shader_descriptor_info *d;
d = vkd3d_dxbc_compiler_get_descriptor_info(compiler, @@ -5758,41 +5742,41 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp { assert(structure_stride); /* counters are valid only for structured buffers */
- counter_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); if (vkd3d_dxbc_compiler_is_opengl_target(compiler)) { + counter_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); vkd3d_spirv_enable_capability(builder, SpvCapabilityAtomicStorage); storage_class = SpvStorageClassAtomicCounter; - ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, counter_type_id); } else if (compiler->ssbo_uavs) { - uint32_t length_id, array_type_id, struct_id; + uint32_t length_id, array_type_id;
length_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, 1); - array_type_id = vkd3d_spirv_build_op_type_array(builder, counter_type_id, length_id); + array_type_id = vkd3d_spirv_build_op_type_array(builder, vkd3d_spirv_get_type_id(builder, + VKD3D_SHADER_COMPONENT_UINT, 1), length_id); vkd3d_spirv_build_op_decorate1(builder, array_type_id, SpvDecorationArrayStride, 4);
- struct_id = vkd3d_spirv_build_op_type_struct(builder, &array_type_id, 1); - vkd3d_spirv_build_op_decorate(builder, struct_id, SpvDecorationBufferBlock, NULL, 0); - vkd3d_spirv_build_op_member_decorate1(builder, struct_id, 0, SpvDecorationOffset, 0); + counter_type_id = vkd3d_spirv_build_op_type_struct(builder, &array_type_id, 1); + vkd3d_spirv_build_op_decorate(builder, counter_type_id, SpvDecorationBufferBlock, NULL, 0); + vkd3d_spirv_build_op_member_decorate1(builder, counter_type_id, 0, SpvDecorationOffset, 0);
storage_class = SpvStorageClassUniform; - ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, struct_id); + } + else + { + counter_type_id = type_id; }
- counter_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, - counter_var_id, reg, &resource->range, resource_type, true); - - vkd3d_spirv_build_op_name(builder, counter_var_id, "u%u_counter", reg->idx[0].offset); + /* TODO: UAV counter descriptor arrays. */ + counter_var_id = vkd3d_dxbc_compiler_build_descriptor_variable(compiler, storage_class, + counter_type_id, reg, &resource->range, resource_type, true, &counter_array_symbol); } }
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; @@ -7787,9 +7771,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;
On Mon, 19 Jul 2021 at 09:22, Conor McCarthy conor.mccarthy6@bigpond.com wrote:
-static void vkd3d_dxbc_compiler_emit_descriptor_binding_for_reg(struct vkd3d_dxbc_compiler *compiler,
uint32_t variable_id, const struct vkd3d_shader_register *reg, const struct vkd3d_shader_register_range *range,
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_base_idx);
- vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, variable_id, &binding);
-}
[...]
@@ -5758,41 +5742,41 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp { assert(structure_stride); /* counters are valid only for structured buffers */
counter_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); if (vkd3d_dxbc_compiler_is_opengl_target(compiler)) {
counter_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); vkd3d_spirv_enable_capability(builder, SpvCapabilityAtomicStorage); storage_class = SpvStorageClassAtomicCounter;
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, counter_type_id); } else if (compiler->ssbo_uavs) {
uint32_t length_id, array_type_id, struct_id;
uint32_t length_id, array_type_id; length_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, 1);
array_type_id = vkd3d_spirv_build_op_type_array(builder, counter_type_id, length_id);
array_type_id = vkd3d_spirv_build_op_type_array(builder, vkd3d_spirv_get_type_id(builder,
VKD3D_SHADER_COMPONENT_UINT, 1), length_id); vkd3d_spirv_build_op_decorate1(builder, array_type_id, SpvDecorationArrayStride, 4);
struct_id = vkd3d_spirv_build_op_type_struct(builder, &array_type_id, 1);
vkd3d_spirv_build_op_decorate(builder, struct_id, SpvDecorationBufferBlock, NULL, 0);
vkd3d_spirv_build_op_member_decorate1(builder, struct_id, 0, SpvDecorationOffset, 0);
counter_type_id = vkd3d_spirv_build_op_type_struct(builder, &array_type_id, 1);
vkd3d_spirv_build_op_decorate(builder, counter_type_id, SpvDecorationBufferBlock, NULL, 0);
vkd3d_spirv_build_op_member_decorate1(builder, counter_type_id, 0, SpvDecorationOffset, 0); storage_class = SpvStorageClassUniform;
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, struct_id);
}
else
{
counter_type_id = type_id; }
counter_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,
counter_var_id, reg, &resource->range, resource_type, true);
vkd3d_spirv_build_op_name(builder, counter_var_id, "u%u_counter", reg->idx[0].offset);
/* TODO: UAV counter descriptor arrays. */
counter_var_id = vkd3d_dxbc_compiler_build_descriptor_variable(compiler, storage_class,
}counter_type_id, reg, &resource->range, resource_type, true, &counter_array_symbol); }
Most of this seems like a separate change from the rest of the patch.
On Mon, 19 Jul 2021 at 09:22, Conor McCarthy conor.mccarthy6@bigpond.com wrote:
@@ -2586,8 +2582,10 @@ 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. */
Why introduce the "binding_base_idx" parameter in this patch if we're going to ignore it?