[PATCH vkd3d 2/5] vkd3d-shader: Introduce a descriptor array symbol type to struct vkd3d_symbol.
Conor McCarthy
cmccarthy at codeweavers.com
Fri Jul 9 00:46:50 CDT 2021
Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
libs/vkd3d-shader/spirv.c | 145 +++++++++++++++++++++--
libs/vkd3d-shader/vkd3d_shader_private.h | 1 +
2 files changed, 136 insertions(+), 10 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c
index 61f0d903..25936849 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;
@@ -2610,7 +2632,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;
@@ -2620,7 +2642,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,
@@ -3011,6 +3035,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;
@@ -3033,6 +3058,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;
@@ -3052,6 +3078,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;
@@ -3078,17 +3105,42 @@ 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, unsigned int binding_base_idx,
+ enum vkd3d_shader_resource_type resource_type)
+{
+ 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_resource_index(compiler, reg,
+ register_info->descriptor_array->info.descriptor_array.binding_base_idx,
+ 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, ®->idx[2]);
}
@@ -5282,16 +5334,91 @@ static void vkd3d_dxbc_compiler_emit_push_constant_buffers(struct vkd3d_dxbc_com
}
}
+static uint32_t vkd3d_dxbc_compiler_get_resource_variable(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_symbol_descriptor_array_data *array_data, uint32_t ptr_type_id,
+ const struct vkd3d_shader_register *reg, const struct vkd3d_shader_descriptor_binding *binding,
+ const struct vkd3d_symbol **array_symbol)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+
+ if (array_data->contained_type_id)
+ {
+ struct vkd3d_symbol *array_symbol_entry;
+ struct vkd3d_symbol symbol;
+ 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. */
+ 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, array_data->storage_class, 0);
+ symbol.descriptor_array = NULL;
+ vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, symbol.id, binding);
+ vkd3d_dxbc_compiler_emit_register_debug_name(builder, symbol.id, reg);
+
+ symbol.info.descriptor_array = *array_data;
+ *array_symbol = vkd3d_dxbc_compiler_put_symbol(compiler, &symbol);
+
+ return symbol.id;
+ }
+ else
+ {
+ uint32_t var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
+ ptr_type_id, array_data->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;
+ }
+}
+
+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, unsigned int binding_base_idx,
+ bool array_variable, const struct vkd3d_symbol **array_symbol)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ struct vkd3d_symbol_descriptor_array_data array_data;
+ uint32_t ptr_type_id;
+
+ array_data.storage_class = storage_class;
+ array_data.contained_type_id = 0;
+ array_data.binding_base_idx = binding_base_idx;
+ if (array_variable)
+ {
+ array_data.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, array_data.storage_class, type_id);
+
+ return vkd3d_dxbc_compiler_get_resource_variable(compiler, &array_data, ptr_type_id, reg, binding, array_symbol);
+}
+
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;
+ struct vkd3d_shader_descriptor_binding binding;
+ const struct vkd3d_symbol *array_symbol;
struct vkd3d_symbol reg_symbol;
+ unsigned int binding_base_idx;
assert(!(instruction->flags & ~VKD3DSI_INDEXED_DYNAMIC));
@@ -5321,18 +5448,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->range, VKD3D_SHADER_RESOURCE_BUFFER, false);
+ binding = vkd3d_dxbc_compiler_get_descriptor_binding(compiler, reg, &cb->range,
+ VKD3D_SHADER_RESOURCE_BUFFER, false, &binding_base_idx);
- 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, binding_base_idx, binding.count != 1 || cb->range.last == ~0u, &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,
--
2.31.1
More information about the wine-devel
mailing list