[PATCH vkd3d 2/6] vkd3d-shader: Emit SPIR-V for array bindings.
Conor McCarthy
cmccarthy at codeweavers.com
Wed May 26 03:10:51 CDT 2021
Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
libs/vkd3d-shader/spirv.c | 294 +++++++++++++++++++++++++++++++++-----
1 file changed, 257 insertions(+), 37 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c
index 0342efa3..b99615f4 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
@@ -335,6 +336,7 @@ struct vkd3d_spirv_builder
uint64_t capability_mask;
uint64_t capability_draw_parameters : 1;
uint64_t capability_demote_to_helper_invocation : 1;
+ uint64_t capability_descriptor_indexing : 1;
uint32_t ext_instr_set_glsl_450;
uint32_t invocation_count;
SpvExecutionModel execution_model;
@@ -391,6 +393,11 @@ static void vkd3d_spirv_enable_capability(struct vkd3d_spirv_builder *builder,
}
}
+static void vkd3d_spirv_enable_descriptor_indexing(struct vkd3d_spirv_builder *builder)
+{
+ builder->capability_descriptor_indexing = 1;
+}
+
static uint32_t vkd3d_spirv_get_glsl_std450_instr_set(struct vkd3d_spirv_builder *builder)
{
if (!builder->ext_instr_set_glsl_450)
@@ -1808,6 +1815,8 @@ static bool vkd3d_spirv_compile_module(struct vkd3d_spirv_builder *builder,
vkd3d_spirv_build_op_extension(&stream, "SPV_KHR_shader_draw_parameters");
if (builder->capability_demote_to_helper_invocation)
vkd3d_spirv_build_op_extension(&stream, "SPV_EXT_demote_to_helper_invocation");
+ if (builder->capability_descriptor_indexing || builder->capability_non_uniform)
+ vkd3d_spirv_build_op_extension(&stream, "SPV_EXT_descriptor_indexing");
if (builder->ext_instr_set_glsl_450)
vkd3d_spirv_build_op_ext_inst_import(&stream, builder->ext_instr_set_glsl_450, "GLSL.std.450");
@@ -1921,6 +1930,7 @@ struct vkd3d_symbol_combined_sampler
struct vkd3d_symbol_register_data
{
SpvStorageClass storage_class;
+ int binding_offset; /* Offset within a merged array binding. */
uint32_t member_idx;
enum vkd3d_shader_component_type component_type;
unsigned int write_mask;
@@ -1934,8 +1944,11 @@ struct vkd3d_symbol_resource_data
{
unsigned int register_space;
unsigned int register_index;
+ int binding_offset; /* Offset within a merged array binding. */
+ SpvStorageClass storage_class;
enum vkd3d_shader_component_type sampled_type;
uint32_t type_id;
+ uint32_t contained_type_id;
const struct vkd3d_spirv_resource_type *resource_type_info;
unsigned int structure_stride;
bool raw;
@@ -1977,6 +1990,35 @@ struct vkd3d_symbol
} info;
};
+struct vkd3d_array_variable_key
+{
+ uint32_t ptr_type_id;
+ unsigned int set;
+ unsigned int binding;
+};
+
+struct vkd3d_array_variable
+{
+ struct rb_entry entry;
+ struct vkd3d_array_variable_key key;
+ uint32_t id;
+};
+
+static int vkd3d_array_variable_compare(const void *key, const struct rb_entry *entry)
+{
+ const struct vkd3d_array_variable *a = key;
+ const struct vkd3d_array_variable *b = RB_ENTRY_VALUE(entry, const struct vkd3d_array_variable, entry);
+
+ return memcmp(&a->key, &b->key, sizeof(a->key));
+}
+
+static void vkd3d_array_variable_free(struct rb_entry *entry, void *context)
+{
+ struct vkd3d_array_variable *s = RB_ENTRY_VALUE(entry, struct vkd3d_array_variable, entry);
+
+ vkd3d_free(s);
+}
+
static int vkd3d_symbol_compare(const void *key, const struct rb_entry *entry)
{
const struct vkd3d_symbol *a = key;
@@ -2012,6 +2054,7 @@ static void vkd3d_symbol_set_register_info(struct vkd3d_symbol *symbol,
{
symbol->id = val_id;
symbol->info.reg.storage_class = storage_class;
+ symbol->info.reg.binding_offset = VKD3D_SHADER_SINGLE_BINDING;
symbol->info.reg.member_idx = 0;
symbol->info.reg.component_type = component_type;
symbol->info.reg.write_mask = write_mask;
@@ -2172,11 +2215,13 @@ struct vkd3d_dxbc_compiler
bool ssbo_uavs;
struct rb_tree symbol_table;
+ struct rb_tree array_var_table;
uint32_t temp_id;
unsigned int temp_count;
struct vkd3d_hull_shader_variables hs;
uint32_t sample_positions_id;
+ struct vkd3d_shader_version shader_version;
enum vkd3d_shader_type shader_type;
unsigned int branch_id;
@@ -2224,6 +2269,11 @@ struct vkd3d_dxbc_compiler
enum vkd3d_shader_compile_option_formatting_flags formatting;
};
+static bool shader_is_sm_5_1(const struct vkd3d_dxbc_compiler *compiler)
+{
+ return (((unsigned int)compiler->shader_version.major << 8) + compiler->shader_version.minor) >= 0x501;
+}
+
static bool is_control_point_phase(const struct vkd3d_shader_phase *phase)
{
return phase && phase->type == VKD3DSIH_HS_CONTROL_POINT_PHASE;
@@ -2317,7 +2367,9 @@ struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader
}
rb_init(&compiler->symbol_table, vkd3d_symbol_compare);
+ rb_init(&compiler->array_var_table, vkd3d_array_variable_compare);
+ compiler->shader_version = *shader_version;
compiler->shader_type = shader_version->type;
compiler->input_signature = &shader_desc->input_signature;
@@ -2572,14 +2624,8 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor
|| current->register_index + current->binding.count <= register_last)
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, register_space, reg_idx, compiler->shader_type, current->binding.count);
- }
+ if (current->binding.offset != VKD3D_SHADER_SINGLE_BINDING || !bounded)
+ vkd3d_spirv_enable_descriptor_indexing(&compiler->spirv_builder);
return current->binding;
}
@@ -2815,6 +2861,42 @@ static void vkd3d_dxbc_compiler_emit_register_debug_name(struct vkd3d_spirv_buil
vkd3d_spirv_build_op_name(builder, id, "%s", debug_name);
}
+static bool vkd3d_dxbc_compiler_get_range_binding_debug_name(char *buffer, unsigned int buffer_size,
+ const struct vkd3d_shader_register *reg, const struct vkd3d_shader_descriptor_binding *binding)
+{
+ char count[8] = "*";
+ if (binding->count < 0x10000)
+ snprintf(count, ARRAY_SIZE(count), "%u", binding->count);
+ switch (reg->type)
+ {
+ case VKD3DSPR_RESOURCE:
+ snprintf(buffer, buffer_size, "t%u_%s", binding->offset, count);
+ break;
+ case VKD3DSPR_UAV:
+ snprintf(buffer, buffer_size, "u%u_%s", binding->offset, count);
+ break;
+ case VKD3DSPR_SAMPLER:
+ snprintf(buffer, buffer_size, "s%u_%s", binding->offset, count);
+ break;
+ case VKD3DSPR_CONSTBUFFER:
+ snprintf(buffer, buffer_size, "cb%u_%s_%u", binding->offset, count, reg->idx[1].offset);
+ break;
+ default:
+ FIXME("Unhandled register %#x.\n", reg->type);
+ return false;
+ }
+
+ return true;
+}
+
+static void vkd3d_dxbc_compiler_emit_range_binding_debug_name(struct vkd3d_spirv_builder *builder,
+ uint32_t id, const struct vkd3d_shader_register *reg, const struct vkd3d_shader_descriptor_binding *binding)
+{
+ char debug_name[256];
+ if (vkd3d_dxbc_compiler_get_range_binding_debug_name(debug_name, ARRAY_SIZE(debug_name), reg, binding))
+ vkd3d_spirv_build_op_name(builder, id, "%s", debug_name);
+}
+
static uint32_t vkd3d_dxbc_compiler_emit_variable(struct vkd3d_dxbc_compiler *compiler,
struct vkd3d_spirv_stream *stream, SpvStorageClass storage_class,
enum vkd3d_shader_component_type component_type, unsigned int component_count)
@@ -2845,6 +2927,66 @@ static uint32_t vkd3d_dxbc_compiler_emit_array_variable(struct vkd3d_dxbc_compil
return vkd3d_spirv_build_op_variable(builder, stream, ptr_type_id, storage_class, 0);
}
+static uint32_t vkd3d_dxbc_compiler_get_resource_variable(struct vkd3d_dxbc_compiler *compiler,
+ SpvStorageClass storage_class, uint32_t ptr_type_id, const struct vkd3d_shader_register *reg,
+ const struct vkd3d_shader_descriptor_binding *binding, bool unbounded)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+
+ if (binding->offset != VKD3D_SHADER_SINGLE_BINDING || unbounded)
+ {
+ struct vkd3d_array_variable *array_var_entry;
+ struct vkd3d_array_variable array_var;
+ struct rb_entry *entry;
+
+ /* 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. */
+ array_var.key.ptr_type_id = ptr_type_id;
+ array_var.key.set = binding->set;
+ array_var.key.binding = binding->binding;
+ if ((entry = rb_get(&compiler->array_var_table, &array_var)))
+ {
+ array_var_entry = RB_ENTRY_VALUE(entry, struct vkd3d_array_variable, entry);
+ return array_var_entry->id;
+ }
+
+ array_var.id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
+ ptr_type_id, storage_class, 0);
+ vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, array_var.id, binding);
+ vkd3d_dxbc_compiler_emit_range_binding_debug_name(builder, array_var.id, reg, binding);
+
+ array_var_entry = vkd3d_malloc(sizeof(*array_var_entry));
+ memcpy(array_var_entry, &array_var, sizeof(*array_var_entry));
+ rb_put(&compiler->array_var_table, array_var_entry, &array_var_entry->entry);
+
+ return array_var.id;
+ }
+ else
+ {
+ 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);
+ return var_id;
+ }
+}
+
+static uint32_t vkd3d_dxbc_compiler_build_resource_variable(struct vkd3d_dxbc_compiler *compiler,
+ SpvStorageClass storage_class, uint32_t type_id, const struct vkd3d_shader_register *reg,
+ const struct vkd3d_shader_descriptor_binding *binding, bool unbounded)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t ptr_type_id;
+
+ if (binding->offset != VKD3D_SHADER_SINGLE_BINDING || unbounded)
+ 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);
+
+ return vkd3d_dxbc_compiler_get_resource_variable(compiler, storage_class,
+ ptr_type_id, reg, binding, unbounded);
+}
+
static const struct vkd3d_shader_parameter *vkd3d_dxbc_compiler_get_shader_parameter(
struct vkd3d_dxbc_compiler *compiler, enum vkd3d_shader_parameter_name name)
{
@@ -3028,6 +3170,7 @@ struct vkd3d_shader_register_info
SpvStorageClass storage_class;
enum vkd3d_shader_component_type component_type;
unsigned int write_mask;
+ int binding_offset;
uint32_t member_idx;
unsigned int structure_stride;
bool is_aggregate;
@@ -3047,6 +3190,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->binding_offset = VKD3D_SHADER_SINGLE_BINDING;
register_info->member_idx = 0;
register_info->component_type = VKD3D_SHADER_COMPONENT_FLOAT;
register_info->write_mask = VKD3DSP_WRITEMASK_ALL;
@@ -3067,6 +3211,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->storage_class = symbol->info.reg.storage_class;
+ register_info->binding_offset = symbol->info.reg.binding_offset;
register_info->member_idx = symbol->info.reg.member_idx;
register_info->component_type = symbol->info.reg.component_type;
register_info->write_mask = symbol->info.reg.write_mask;
@@ -3092,17 +3237,38 @@ static bool register_is_descriptor(const struct vkd3d_shader_register *reg)
}
}
+static uint32_t vkd3d_dxbc_compiler_get_resource_index(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_register *reg, int binding_offset)
+{
+ uint32_t index_id;
+
+ if (shader_is_sm_5_1(compiler))
+ {
+ struct vkd3d_shader_register_index index = reg->idx[1];
+ index.offset += binding_offset;
+ index_id = vkd3d_dxbc_compiler_emit_register_addressing(compiler, &index);
+ }
+ else
+ {
+ index_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, reg->idx[0].offset + binding_offset);
+ }
+
+ 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->binding_offset != VKD3D_SHADER_SINGLE_BINDING)
+ indexes[index_count++] = vkd3d_dxbc_compiler_get_resource_index(compiler, reg, register_info->binding_offset);
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]);
}
@@ -5299,12 +5465,13 @@ static void vkd3d_dxbc_compiler_emit_push_constant_buffers(struct vkd3d_dxbc_com
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;
+ uint32_t vec4_id, array_type_id, length_id, struct_id, var_id;
const struct vkd3d_shader_constant_buffer *cb = &instruction->declaration.cb;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const SpvStorageClass storage_class = SpvStorageClassUniform;
const struct vkd3d_shader_register *reg = &cb->src.reg;
struct vkd3d_push_constant_buffer_binding *push_cb;
+ struct vkd3d_shader_descriptor_binding binding;
struct vkd3d_symbol reg_symbol;
assert(!(instruction->flags & ~VKD3DSI_INDEXED_DYNAMIC));
@@ -5335,18 +5502,16 @@ 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->register_space, cb->register_index, VKD3D_SHADER_RESOURCE_BUFFER, false);
+ binding = vkd3d_dxbc_compiler_get_descriptor_binding(compiler, reg, cb->register_space,
+ cb->register_first, cb->register_last, VKD3D_SHADER_RESOURCE_BUFFER, false);
- vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg);
+ var_id = vkd3d_dxbc_compiler_build_resource_variable(compiler, storage_class, struct_id,
+ reg, &binding, cb->register_last == ~0u);
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.info.reg.binding_offset = binding.offset;
vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol);
}
@@ -5390,7 +5555,8 @@ 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;
+ struct vkd3d_shader_descriptor_binding binding;
+ uint32_t type_id, var_id;
struct vkd3d_symbol reg_symbol;
vkd3d_symbol_make_sampler(®_symbol, reg);
@@ -5401,19 +5567,17 @@ static void vkd3d_dxbc_compiler_emit_dcl_sampler(struct vkd3d_dxbc_compiler *com
if (vkd3d_dxbc_compiler_has_combined_sampler(compiler, NULL, sampler))
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->register_space, sampler->register_index, VKD3D_SHADER_RESOURCE_NONE, false);
+ binding = vkd3d_dxbc_compiler_get_descriptor_binding(compiler, reg, sampler->register_space,
+ sampler->register_first, sampler->register_last, VKD3D_SHADER_RESOURCE_NONE, false);
- vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg);
+ type_id = vkd3d_spirv_get_op_type_sampler(builder);
+ var_id = vkd3d_dxbc_compiler_build_resource_variable(compiler, storage_class,
+ type_id, reg, &binding, sampler->register_last == ~0u);
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.info.reg.binding_offset = binding.offset;
vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol);
}
@@ -5567,8 +5731,11 @@ static void vkd3d_dxbc_compiler_emit_combined_sampler_declarations(struct vkd3d_
symbol.id = var_id;
symbol.info.resource.register_space = resource_space;
symbol.info.resource.register_index = resource_index;
+ symbol.info.resource.binding_offset = current->binding.offset;
+ symbol.info.resource.storage_class = storage_class;
symbol.info.resource.sampled_type = sampled_type;
symbol.info.resource.type_id = image_type_id;
+ symbol.info.resource.contained_type_id = 0;
symbol.info.resource.resource_type_info = resource_type_info;
symbol.info.resource.structure_stride = structure_stride;
symbol.info.resource.raw = raw;
@@ -5592,6 +5759,7 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp
struct vkd3d_shader_descriptor_binding binding;
enum vkd3d_shader_component_type sampled_type;
struct vkd3d_symbol resource_symbol;
+ uint32_t contained_type_id = 0;
bool is_uav;
is_uav = reg->type == VKD3DSPR_UAV;
@@ -5611,6 +5779,9 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp
return;
}
+ binding = vkd3d_dxbc_compiler_get_descriptor_binding(compiler, reg, register_space,
+ register_first, register_last, resource_type, false);
+
if (compiler->ssbo_uavs && is_uav && resource_type == VKD3D_SHADER_RESOURCE_BUFFER)
{
uint32_t array_type_id, struct_id;
@@ -5631,16 +5802,19 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp
{
type_id = vkd3d_dxbc_compiler_get_image_type_id(compiler, reg, register_space,
register_first, resource_type_info, sampled_type, structure_stride || raw, 0);
+
+ if (binding.offset != VKD3D_SHADER_SINGLE_BINDING || register_last == ~0u)
+ {
+ 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);
- 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,
- register_space, register_index, resource_type, false);
- vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg);
+ var_id = vkd3d_dxbc_compiler_get_resource_variable(compiler, storage_class,
+ ptr_type_id, reg, &binding, register_last == ~0u);
if (is_uav)
{
@@ -5678,6 +5852,11 @@ 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 if (contained_type_id)
+ {
+ /* TODO: UAV counter arrays. */
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, contained_type_id);
+ }
counter_var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
ptr_type_id, storage_class, 0);
@@ -5694,8 +5873,11 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp
resource_symbol.id = var_id;
resource_symbol.info.resource.register_space = register_space;
resource_symbol.info.resource.register_index = register_first;
+ resource_symbol.info.resource.binding_offset = binding.offset;
+ resource_symbol.info.resource.storage_class = storage_class;
resource_symbol.info.resource.sampled_type = sampled_type;
resource_symbol.info.resource.type_id = type_id;
+ resource_symbol.info.resource.contained_type_id = contained_type_id;
resource_symbol.info.resource.resource_type_info = resource_type_info;
resource_symbol.info.resource.structure_stride = structure_stride;
resource_symbol.info.resource.raw = raw;
@@ -7687,9 +7869,27 @@ 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->info.resource.binding_offset != VKD3D_SHADER_SINGLE_BINDING)
+ {
+ uint32_t ptr_type_id, index_id;
+
+ index_id = vkd3d_dxbc_compiler_get_resource_index(compiler,
+ resource_reg, symbol->info.resource.binding_offset);
+
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder,
+ symbol->info.resource.storage_class,
+ symbol->info.resource.contained_type_id);
+ image->image_type_id = symbol->info.resource.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;
@@ -7704,8 +7904,15 @@ static void vkd3d_dxbc_compiler_prepare_image(struct vkd3d_dxbc_compiler *compil
return;
}
- image->image_id = load ? vkd3d_spirv_build_op_load(builder,
- image->image_type_id, image->id, SpvMemoryAccessMaskNone) : 0;
+ if (load)
+ {
+ image->image_id = vkd3d_spirv_build_op_load(builder,
+ image->image_type_id, image->id, SpvMemoryAccessMaskNone);
+ }
+ else
+ {
+ image->image_id = 0;
+ }
image->image_type_id = vkd3d_dxbc_compiler_get_image_type_id(compiler, resource_reg,
symbol->info.resource.register_space, symbol->info.resource.register_index, image->resource_type_info,
@@ -7713,10 +7920,22 @@ 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.binding_offset != VKD3D_SHADER_SINGLE_BINDING)
+ {
+ uint32_t ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder,
+ register_info.storage_class, vkd3d_spirv_get_op_type_sampler(builder));
+ uint32_t array_idx = vkd3d_dxbc_compiler_get_resource_index(compiler,
+ sampler_reg, register_info.binding_offset);
+ 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);
@@ -9504,6 +9723,7 @@ void vkd3d_dxbc_compiler_destroy(struct vkd3d_dxbc_compiler *compiler)
vkd3d_spirv_builder_free(&compiler->spirv_builder);
rb_destroy(&compiler->symbol_table, vkd3d_symbol_free, NULL);
+ rb_destroy(&compiler->array_var_table, vkd3d_array_variable_free, NULL);
vkd3d_free(compiler->shader_phases);
vkd3d_free(compiler->spec_constants);
--
2.31.1
More information about the wine-devel
mailing list