Goes atop !471. The last six commits belong to this MR.
-- v2: vkd3d-shader/dxil: Emit constant global arrays as immediate constant buffers. vkd3d-shader: Add a register index to struct vkd3d_shader_immediate_constant_buffer. vkd3d-shader/spirv: Support declared component type and count in immediate constant buffers. vkd3d-shader/spirv: Support constant initialisers in indexable temps. vkd3d-shader/dxil: Support null constant arrays. vkd3d-shader/spirv: Support declared component type and count in indexable temps. vkd3d-shader/dxil: Implement the DXIL LOAD instruction. vkd3d-shader/dxil: Implement the DXIL GEP instruction. vkd3d-shader/dxil: Support global variable initialisers. vkd3d-shader/dxil: Introduce a value type for immediate constant buffers. vkd3d-shader/dxil: Implement default address space global variables.
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/vkd3d_shader_private.h | 1 - 1 file changed, 1 deletion(-)
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index bff494539..cfd47dd37 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -799,7 +799,6 @@ struct vkd3d_shader_immediate_constant_buffer
struct vkd3d_shader_indexable_temp { - struct list entry; unsigned int register_idx; unsigned int register_size; unsigned int component_count;
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/d3d_asm.c | 2 + libs/vkd3d-shader/dxil.c | 189 ++++++++++++++++++++++- libs/vkd3d-shader/tpf.c | 2 + libs/vkd3d-shader/vkd3d_shader_private.h | 2 + 4 files changed, 194 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d-shader/d3d_asm.c index 442c1e414..f6d511e7c 100644 --- a/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d-shader/d3d_asm.c @@ -1679,6 +1679,8 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, ins->declaration.indexable_temp.register_idx, compiler->colours.reset); shader_print_subscript(compiler, ins->declaration.indexable_temp.register_size, NULL); shader_print_uint_literal(compiler, ", ", ins->declaration.indexable_temp.component_count, ""); + if (ins->declaration.indexable_temp.alignment) + shader_print_uint_literal(compiler, ", align ", ins->declaration.indexable_temp.alignment, ""); break;
case VKD3DSIH_DCL_INPUT_PS: diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index ca7e0e723..bb23aa868 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -25,6 +25,10 @@
#define BITCODE_MAGIC VKD3D_MAKE_TAG('B', 'C', 0xc0, 0xde) #define DXIL_OP_MAX_OPERANDS 17 +static const uint64_t MAX_ALIGNMENT_EXPONENT = 29; +static const uint64_t GLOBALVAR_FLAG_IS_CONSTANT = 1; +static const uint64_t GLOBALVAR_FLAG_EXPLICIT_TYPE = 2; +static const unsigned int GLOBALVAR_ADDRESS_SPACE_SHIFT = 2; static const unsigned int SHADER_DESCRIPTOR_TYPE_COUNT = 4;
static const unsigned int dx_max_thread_group_size[3] = {1024, 1024, 64}; @@ -157,6 +161,13 @@ enum bitcode_value_symtab_code VST_CODE_BBENTRY = 2, };
+enum bitcode_linkage +{ + LINKAGE_EXTERNAL = 0, + LINKAGE_APPENDING = 2, + LINKAGE_INTERNAL = 3, +}; + enum dxil_component_type { COMPONENT_TYPE_INVALID = 0, @@ -567,6 +578,8 @@ struct sm6_parser size_t descriptor_capacity; size_t descriptor_count;
+ unsigned int indexable_temp_count; + struct sm6_value *values; size_t value_count; size_t value_capacity; @@ -2555,6 +2568,17 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const return VKD3D_OK; }
+static bool bitcode_parse_alignment(uint64_t encoded_alignment, unsigned int *alignment) +{ + if (encoded_alignment > MAX_ALIGNMENT_EXPONENT + 1) + { + *alignment = 0; + return false; + } + *alignment = (1u << encoded_alignment) >> 1; + return true; +} + static struct vkd3d_shader_instruction *sm6_parser_require_space(struct sm6_parser *sm6, size_t extra) { if (!shader_instruction_array_reserve(&sm6->p.instructions, sm6->p.instructions.count + extra)) @@ -2576,6 +2600,168 @@ static struct vkd3d_shader_instruction *sm6_parser_add_instruction(struct sm6_pa return ins; }
+static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const struct sm6_type *elem_type, + unsigned int count, unsigned int alignment, struct sm6_value *dst) +{ + enum vkd3d_data_type data_type = vkd3d_data_type_from_sm6_type(elem_type); + struct vkd3d_shader_instruction *ins; + + ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_INDEXABLE_TEMP); + ins->declaration.indexable_temp.register_idx = sm6->indexable_temp_count++; + ins->declaration.indexable_temp.register_size = count; + ins->declaration.indexable_temp.alignment = alignment; + ins->declaration.indexable_temp.data_type = data_type; + ins->declaration.indexable_temp.component_count = 1; + + register_init_with_id(&dst->u.reg, VKD3DSPR_IDXTEMP, data_type, ins->declaration.indexable_temp.register_idx); +} + +static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_record *record) +{ + const struct sm6_type *type, *scalar_type; + unsigned int alignment, count; + uint64_t address_space, init; + struct sm6_value *dst; + bool is_constant; + + if (!dxil_record_validate_operand_min_count(record, 6, sm6)) + return false; + + if (!(type = sm6_parser_get_type(sm6, record->operands[0]))) + return false; + if (sm6_type_is_array(type)) + { + if (!sm6_type_is_scalar(type->u.array.elem_type)) + { + FIXME("Unsupported nested type class %u.\n", type->u.array.elem_type->class); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Global array variables with nested type class %u are not supported.", + type->u.array.elem_type->class); + return false; + } + count = type->u.array.count; + scalar_type = type->u.array.elem_type; + } + else if (sm6_type_is_scalar(type)) + { + count = 1; + scalar_type = type; + } + else + { + FIXME("Unsupported type class %u.\n", type->class); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Global variables of type class %u are not supported.", type->class); + return false; + } + + is_constant = record->operands[1] & GLOBALVAR_FLAG_IS_CONSTANT; + + if (record->operands[1] & GLOBALVAR_FLAG_EXPLICIT_TYPE) + { + address_space = record->operands[1] >> GLOBALVAR_ADDRESS_SPACE_SHIFT; + + if (!(type = sm6_type_get_pointer_to_type(type, address_space, sm6))) + { + WARN("Failed to get pointer type for type class %u, address space %"PRIu64".\n", + type->class, address_space); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, + "Module does not define a pointer type for a global variable."); + return false; + } + } + else + { + if (!sm6_type_is_pointer(type)) + { + WARN("Type is not a pointer.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "The type of a global variable is not a pointer."); + return false; + } + address_space = type->u.pointer.addr_space; + } + + if ((init = record->operands[2])) + { + if (init - 1 >= sm6->value_capacity) + { + WARN("Invalid value index %"PRIu64" for initialiser.", init - 1); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Global variable initialiser value index %"PRIu64" is invalid.", init - 1); + return false; + } + } + + /* LINKAGE_EXTERNAL is common but not relevant here. */ + if (record->operands[3] != LINKAGE_EXTERNAL && record->operands[3] != LINKAGE_INTERNAL) + WARN("Ignoring linkage %"PRIu64".\n", record->operands[3]); + + if (!bitcode_parse_alignment(record->operands[4], &alignment)) + WARN("Invalid alignment %"PRIu64".\n", record->operands[4]); + + if (record->operands[5]) + WARN("Ignoring section code %"PRIu64".\n", record->operands[5]); + + if (!sm6_parser_get_global_symbol_name(sm6, sm6->value_count)) + WARN("Missing symbol name for global variable at index %zu.\n", sm6->value_count); + /* TODO: store global symbol names in struct vkd3d_shader_desc? */ + + if (record->operand_count > 6 && record->operands[6]) + WARN("Ignoring visibility %"PRIu64".\n", record->operands[6]); + if (record->operand_count > 7 && record->operands[7]) + WARN("Ignoring thread local mode %"PRIu64".\n", record->operands[7]); + /* record->operands[8] contains unnamed_addr, a flag indicating the address + * is not important, only the content is. This info is not relevant. */ + if (record->operand_count > 9 && record->operands[9]) + WARN("Ignoring external_init %"PRIu64".\n", record->operands[9]); + if (record->operand_count > 10 && record->operands[10]) + WARN("Ignoring dll storage class %"PRIu64".\n", record->operands[10]); + if (record->operand_count > 11 && record->operands[11]) + WARN("Ignoring comdat %"PRIu64".\n", record->operands[11]); + + dst = sm6_parser_get_current_value(sm6); + dst->type = type; + dst->value_type = VALUE_TYPE_REG; + + if (init) + { + FIXME("Unsupported initialiser.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Global variable initialisers are not supported."); + return false; + } + else if (is_constant) + { + WARN("Constant array has no initialiser.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "A constant global variable has no initialiser."); + return false; + } + + if (address_space == ADDRESS_SPACE_DEFAULT) + { + sm6_parser_declare_indexable_temp(sm6, scalar_type, count, alignment, dst); + } + else if (address_space == ADDRESS_SPACE_GROUPSHARED) + { + FIXME("Unsupported TGSM.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "TGSM global variables are not supported."); + return false; + } + else + { + FIXME("Unhandled address space %"PRIu64".\n", address_space); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Global variables with address space %"PRIu64" are not supported.", address_space); + return false; + } + + ++sm6->value_count; + return true; +} + static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) { const struct dxil_block *block = &sm6->root_block; @@ -2603,7 +2789,8 @@ static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) break;
case MODULE_CODE_GLOBALVAR: - FIXME("Global variables are not implemented yet.\n"); + if (!sm6_parser_declare_global(sm6, record)) + return VKD3D_ERROR_INVALID_SHADER; break;
case MODULE_CODE_VERSION: diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index 594438a26..61d14e30d 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -1113,6 +1113,8 @@ static void shader_sm4_read_dcl_indexable_temp(struct vkd3d_shader_instruction * { ins->declaration.indexable_temp.register_idx = *tokens++; ins->declaration.indexable_temp.register_size = *tokens++; + ins->declaration.indexable_temp.alignment = 0; + ins->declaration.indexable_temp.data_type = VKD3D_DATA_FLOAT; ins->declaration.indexable_temp.component_count = *tokens; }
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index cfd47dd37..d3d6f77f2 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -801,6 +801,8 @@ struct vkd3d_shader_indexable_temp { unsigned int register_idx; unsigned int register_size; + unsigned int alignment; + enum vkd3d_data_type data_type; unsigned int component_count; };
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 14 ++++++++------ libs/vkd3d-shader/vkd3d_shader_main.c | 8 ++++---- libs/vkd3d-shader/vkd3d_shader_private.h | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index bb23aa868..1929fcb48 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -404,6 +404,7 @@ enum sm6_value_type { VALUE_TYPE_FUNCTION, VALUE_TYPE_REG, + VALUE_TYPE_ICB, VALUE_TYPE_HANDLE, };
@@ -429,6 +430,7 @@ struct sm6_value { struct sm6_function_data function; struct vkd3d_shader_register reg; + const struct vkd3d_shader_immediate_constant_buffer *icb; struct sm6_handle_data handle; } u; }; @@ -1900,7 +1902,7 @@ static inline bool sm6_value_is_undef(const struct sm6_value *value)
static bool sm6_value_is_icb(const struct sm6_value *value) { - return sm6_value_is_register(value) && value->u.reg.type == VKD3DSPR_IMMCONSTBUFFER; + return value->value_type == VALUE_TYPE_ICB; }
static inline unsigned int sm6_value_get_constant_uint(const struct sm6_value *value) @@ -2360,7 +2362,7 @@ static inline double bitcast_uint64_to_double(uint64_t value) return u.double_value; }
-static enum vkd3d_result register_allocate_constant_array(struct vkd3d_shader_register *reg, const struct sm6_type *type, +static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, const struct sm6_type *type, const uint64_t *operands, struct sm6_parser *sm6) { struct vkd3d_shader_immediate_constant_buffer *icb; @@ -2395,7 +2397,7 @@ static enum vkd3d_result register_allocate_constant_array(struct vkd3d_shader_re "Out of memory allocating an immediate constant buffer of count %u.", count); return VKD3D_ERROR_OUT_OF_MEMORY; } - if ((reg->idx[0].offset = shader_instruction_array_add_icb(&sm6->p.instructions, icb)) == UINT_MAX) + if (!shader_instruction_array_add_icb(&sm6->p.instructions, icb)) { ERR("Failed to store icb object.\n"); vkd3d_free(icb); @@ -2404,8 +2406,8 @@ static enum vkd3d_result register_allocate_constant_array(struct vkd3d_shader_re return VKD3D_ERROR_OUT_OF_MEMORY; }
- reg->type = VKD3DSPR_IMMCONSTBUFFER; - reg->idx_count = 1; + dst->value_type = VALUE_TYPE_ICB; + dst->u.icb = icb;
icb->data_type = vkd3d_data_type_from_sm6_type(elem_type); icb->element_count = type->u.array.count; @@ -2544,7 +2546,7 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const if (!dxil_record_validate_operand_count(record, type->u.array.count, type->u.array.count, sm6)) return VKD3D_ERROR_INVALID_SHADER;
- if ((ret = register_allocate_constant_array(&dst->u.reg, type, record->operands, sm6)) < 0) + if ((ret = value_allocate_constant_array(dst, type, record->operands, sm6)) < 0) return ret;
break; diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 48af5d976..86e418a68 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -2022,14 +2022,14 @@ bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *ins return true; }
-unsigned int shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *instructions, +bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *instructions, struct vkd3d_shader_immediate_constant_buffer *icb) { if (!vkd3d_array_reserve((void **)&instructions->icbs, &instructions->icb_capacity, instructions->icb_count + 1, sizeof(*instructions->icbs))) - return UINT_MAX; - instructions->icbs[instructions->icb_count] = icb; - return instructions->icb_count++; + return false; + instructions->icbs[instructions->icb_count++] = icb; + return true; }
static struct vkd3d_shader_src_param *shader_instruction_array_clone_src_params( diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index d3d6f77f2..f8b53718a 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1204,7 +1204,7 @@ struct vkd3d_shader_instruction_array
bool shader_instruction_array_init(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve); bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve); -unsigned int shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *instructions, +bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *instructions, struct vkd3d_shader_immediate_constant_buffer *icb); bool shader_instruction_array_clone_instruction(struct vkd3d_shader_instruction_array *instructions, unsigned int dst, unsigned int src);
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 47 +++++++++++++++++++----- libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 2 files changed, 38 insertions(+), 10 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 1929fcb48..5990b6df5 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -2603,7 +2603,7 @@ static struct vkd3d_shader_instruction *sm6_parser_add_instruction(struct sm6_pa }
static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const struct sm6_type *elem_type, - unsigned int count, unsigned int alignment, struct sm6_value *dst) + unsigned int count, unsigned int alignment, unsigned int init, struct sm6_value *dst) { enum vkd3d_data_type data_type = vkd3d_data_type_from_sm6_type(elem_type); struct vkd3d_shader_instruction *ins; @@ -2614,6 +2614,8 @@ static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const stru ins->declaration.indexable_temp.alignment = alignment; ins->declaration.indexable_temp.data_type = data_type; ins->declaration.indexable_temp.component_count = 1; + /* The initialiser value index will be resolved later so forward references can be handled. */ + ins->declaration.indexable_temp.initialiser = (void *)(uintptr_t)init;
register_init_with_id(&dst->u.reg, VKD3DSPR_IDXTEMP, data_type, ins->declaration.indexable_temp.register_idx); } @@ -2726,14 +2728,7 @@ static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_ dst->type = type; dst->value_type = VALUE_TYPE_REG;
- if (init) - { - FIXME("Unsupported initialiser.\n"); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, - "Global variable initialisers are not supported."); - return false; - } - else if (is_constant) + if (is_constant && !init) { WARN("Constant array has no initialiser.\n"); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, @@ -2743,7 +2738,7 @@ static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_
if (address_space == ADDRESS_SPACE_DEFAULT) { - sm6_parser_declare_indexable_temp(sm6, scalar_type, count, alignment, dst); + sm6_parser_declare_indexable_temp(sm6, scalar_type, count, alignment, init, dst); } else if (address_space == ADDRESS_SPACE_GROUPSHARED) { @@ -2764,9 +2759,30 @@ static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_ return true; }
+static const struct vkd3d_shader_immediate_constant_buffer *resolve_forward_initialiser( + size_t index, struct sm6_parser *sm6) +{ + const struct sm6_value *value; + + assert(index); + --index; + if (!(value = sm6_parser_get_value_safe(sm6, index)) || !sm6_value_is_icb(value)) + { + WARN("Invalid initialiser index %zu.\n", index); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Global variable initialiser value index %zu is invalid.", index); + return NULL; + } + else + { + return value->u.icb; + } +} + static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) { const struct dxil_block *block = &sm6->root_block; + struct vkd3d_shader_instruction *ins; const struct dxil_record *record; enum vkd3d_result ret; uint64_t version; @@ -2819,6 +2835,17 @@ static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) return ret; }
+ /* Resolve initialiser forward references. */ + for (i = 0; i < sm6->p.instructions.count; ++i) + { + ins = &sm6->p.instructions.elements[i]; + if (ins->handler_idx == VKD3DSIH_DCL_INDEXABLE_TEMP && ins->declaration.indexable_temp.initialiser) + { + ins->declaration.indexable_temp.initialiser = resolve_forward_initialiser( + (uintptr_t)ins->declaration.indexable_temp.initialiser, sm6); + } + } + return VKD3D_OK; }
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index f8b53718a..9980827f9 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -804,6 +804,7 @@ struct vkd3d_shader_indexable_temp unsigned int alignment; enum vkd3d_data_type data_type; unsigned int component_count; + const struct vkd3d_shader_immediate_constant_buffer *initialiser; };
struct vkd3d_shader_register_index
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 115 +++++++++++++++++++++++ libs/vkd3d-shader/ir.c | 3 + libs/vkd3d-shader/vkd3d_shader_private.h | 2 + 3 files changed, 120 insertions(+)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 5990b6df5..46937e90e 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -1703,6 +1703,15 @@ static const struct sm6_type *sm6_type_get_element_type_at_index(const struct sm } }
+/* Call for aggregate or pointer types only. */ +static const struct sm6_type *sm6_type_get_element_or_pointee_type_at_index(const struct sm6_type *type, + uint64_t elem_idx) +{ + if (sm6_type_is_pointer(type) && !elem_idx) + return type->u.pointer.type; + return sm6_type_get_element_type_at_index(type, elem_idx); +} + /* Never returns null for elem_idx 0. */ static const struct sm6_type *sm6_type_get_scalar_type(const struct sm6_type *type, unsigned int elem_idx) { @@ -2195,6 +2204,18 @@ static bool sm6_value_validate_is_handle(const struct sm6_value *value, struct s return true; }
+static bool sm6_value_validate_is_pointer(const struct sm6_value *value, struct sm6_parser *sm6) +{ + if (!sm6_type_is_pointer(value->type)) + { + WARN("Operand result type class %u is not a pointer.\n", value->type->class); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "A pointer operand passed to a DXIL instruction is not a pointer."); + return false; + } + return true; +} + static bool sm6_value_validate_is_bool(const struct sm6_value *value, struct sm6_parser *sm6) { const struct sm6_type *type = value->type; @@ -3877,6 +3898,97 @@ static void sm6_parser_emit_extractval(struct sm6_parser *sm6, const struct dxil instruction_dst_param_init_ssa_scalar(ins, sm6); }
+static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record *record, + struct vkd3d_shader_instruction *ins, struct sm6_value *dst) +{ + const struct sm6_type *type, *pointee_type; + unsigned int i, elem_idx, operand_idx = 2; + enum bitcode_address_space addr_space; + const struct sm6_value *operands[2]; + const struct sm6_value *elem_value; + struct vkd3d_shader_register *reg; + const struct sm6_value *src; + bool is_in_bounds; + + if (!dxil_record_validate_operand_min_count(record, 5, sm6) + || !(type = sm6_parser_get_type(sm6, record->operands[1])) + || !(src = sm6_parser_get_value_by_ref(sm6, record, NULL, &operand_idx)) + || !sm6_value_validate_is_register(src, sm6) + || !sm6_value_validate_is_pointer(src, sm6) + || !dxil_record_validate_operand_min_count(record, operand_idx + 2, sm6)) + { + return; + } + + is_in_bounds = record->operands[0]; + + if ((pointee_type = src->type->u.pointer.type) != type) + { + WARN("Type mismatch, type %u width %u vs type %u width %u.\n", type->class, + type->u.width, pointee_type->class, pointee_type->u.width); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, + "Type mismatch in GEP operation arguments."); + } + addr_space = src->type->u.pointer.addr_space; + + for (type = src->type, i = 0; operand_idx < record->operand_count; ++i) + { + bool is_constant; + + if (i > 1) + { + FIXME("Multiple element indices are not implemented.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Multi-dimensional addressing in GEP instructions is not supported."); + return; + } + + if (!sm6_type_is_pointer(type) && !sm6_type_is_aggregate(type)) + { + WARN("Invalid GEP on type class %u.\n", type->class); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Source type of a GEP instruction is not a pointer or aggregate."); + return; + } + + if (!(elem_value = sm6_parser_get_value_by_ref(sm6, record, NULL, &operand_idx))) + return; + + is_constant = sm6_value_is_constant(elem_value); + elem_idx = is_constant ? sm6_value_get_constant_uint(elem_value) : 0; + + type = sm6_type_get_element_or_pointee_type_at_index(type, elem_idx); + + /* The first index is always a simple pointer dereference, i.e. zero. */ + if (!type || (!i && !is_constant)) + { + WARN("Invalid element index %u.\n", elem_idx); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Element index %u for a GEP instruction is out of bounds.", elem_idx); + return; + } + + operands[i] = elem_value; + } + + if (!(dst->type = sm6_type_get_pointer_to_type(type, addr_space, sm6))) + { + FIXME("Failed to get pointer type for type %u.\n", type->class); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, + "Module does not define a pointer type for a GEP instruction."); + return; + } + + reg = &dst->u.reg; + *reg = src->u.reg; + reg->idx[1].offset = 0; + register_index_address_init(®->idx[1], operands[1], sm6); + reg->idx[1].is_in_bounds = is_in_bounds; + reg->idx_count = 2; + + ins->handler_idx = VKD3DSIH_NOP; +} + static void sm6_parser_emit_ret(struct sm6_parser *sm6, const struct dxil_record *record, struct sm6_block *code_block, struct vkd3d_shader_instruction *ins) { @@ -4079,6 +4191,9 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const case FUNC_CODE_INST_EXTRACTVAL: sm6_parser_emit_extractval(sm6, record, ins, dst); break; + case FUNC_CODE_INST_GEP: + sm6_parser_emit_gep(sm6, record, ins, dst); + break; case FUNC_CODE_INST_RET: sm6_parser_emit_ret(sm6, record, code_block, ins); is_terminator = true; diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 2a3343994..ae1610483 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -295,10 +295,13 @@ void vsir_register_init(struct vkd3d_shader_register *reg, enum vkd3d_shader_reg reg->data_type = data_type; reg->idx[0].offset = ~0u; reg->idx[0].rel_addr = NULL; + reg->idx[0].is_in_bounds = false; reg->idx[1].offset = ~0u; reg->idx[1].rel_addr = NULL; + reg->idx[1].is_in_bounds = false; reg->idx[2].offset = ~0u; reg->idx[2].rel_addr = NULL; + reg->idx[2].is_in_bounds = false; reg->idx_count = idx_count; reg->dimension = VSIR_DIMENSION_SCALAR; } diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 9980827f9..68eef0b8d 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -811,6 +811,8 @@ struct vkd3d_shader_register_index { const struct vkd3d_shader_src_param *rel_addr; unsigned int offset; + /* address is known to fall within the object (for optimisation) */ + bool is_in_bounds; };
struct vkd3d_shader_register
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 65 +++++++++++++++++++ libs/vkd3d-shader/ir.c | 1 + libs/vkd3d-shader/vkd3d_shader_private.h | 2 + tests/hlsl/matrix-indexing.shader_test | 6 +- tests/hlsl/non-const-indexing.shader_test | 46 ++++++------- .../hlsl/vector-indexing-uniform.shader_test | 4 +- 6 files changed, 96 insertions(+), 28 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 46937e90e..9a527be7c 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -2216,6 +2216,18 @@ static bool sm6_value_validate_is_pointer(const struct sm6_value *value, struct return true; }
+static bool sm6_value_validate_is_numeric(const struct sm6_value *value, struct sm6_parser *sm6) +{ + if (!sm6_type_is_numeric(value->type)) + { + WARN("Operand result type class %u is not numeric.\n", value->type->class); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "A numeric operand passed to a DXIL instruction is not numeric."); + return false; + } + return true; +} + static bool sm6_value_validate_is_bool(const struct sm6_value *value, struct sm6_parser *sm6) { const struct sm6_type *type = value->type; @@ -3989,6 +4001,56 @@ static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record ins->handler_idx = VKD3DSIH_NOP; }
+static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_record *record, + struct vkd3d_shader_instruction *ins, struct sm6_value *dst) +{ + const struct sm6_type *elem_type = NULL, *pointee_type; + struct vkd3d_shader_src_param *src_param; + unsigned int alignment, i = 0; + const struct sm6_value *ptr; + uint64_t alignment_code; + + if (!(ptr = sm6_parser_get_value_by_ref(sm6, record, NULL, &i))) + return; + if (!sm6_value_validate_is_pointer(ptr, sm6) + || !dxil_record_validate_operand_count(record, i + 2, i + 3, sm6)) + return; + + if (record->operand_count > i + 2 && !(elem_type = sm6_parser_get_type(sm6, record->operands[i++]))) + return; + + if (!elem_type) + { + elem_type = ptr->type->u.pointer.type; + } + else if (elem_type != (pointee_type = ptr->type->u.pointer.type)) + { + WARN("Type mismatch.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, + "Type mismatch in pointer load arguments."); + } + + dst->type = elem_type; + + if (!sm6_value_validate_is_numeric(dst, sm6)) + return; + + alignment_code = record->operands[i++]; + if (!bitcode_parse_alignment(alignment_code, &alignment)) + WARN("Invalid alignment %"PRIu64".\n", alignment_code); + + if (record->operands[i]) + WARN("Ignoring volatile modifier.\n"); + + vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); + + src_param = instruction_src_params_alloc(ins, 1, sm6); + src_param_init_from_value(&src_param[0], ptr); + src_param->reg.alignment = alignment; + + instruction_dst_param_init_ssa_scalar(ins, sm6); +} + static void sm6_parser_emit_ret(struct sm6_parser *sm6, const struct dxil_record *record, struct sm6_block *code_block, struct vkd3d_shader_instruction *ins) { @@ -4194,6 +4256,9 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const case FUNC_CODE_INST_GEP: sm6_parser_emit_gep(sm6, record, ins, dst); break; + case FUNC_CODE_INST_LOAD: + sm6_parser_emit_load(sm6, record, ins, dst); + break; case FUNC_CODE_INST_RET: sm6_parser_emit_ret(sm6, record, code_block, ins); is_terminator = true; diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index ae1610483..f216c82f7 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -304,6 +304,7 @@ void vsir_register_init(struct vkd3d_shader_register *reg, enum vkd3d_shader_reg reg->idx[2].is_in_bounds = false; reg->idx_count = idx_count; reg->dimension = VSIR_DIMENSION_SCALAR; + reg->alignment = 0; }
void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 68eef0b8d..d21ecc513 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -824,6 +824,8 @@ struct vkd3d_shader_register struct vkd3d_shader_register_index idx[3]; unsigned int idx_count; enum vsir_dimension dimension; + /* known address alignment for optimisation, or zero */ + unsigned int alignment; union { DWORD immconst_uint[VKD3D_VEC4_SIZE]; diff --git a/tests/hlsl/matrix-indexing.shader_test b/tests/hlsl/matrix-indexing.shader_test index b8e6dec68..bc4a46d03 100644 --- a/tests/hlsl/matrix-indexing.shader_test +++ b/tests/hlsl/matrix-indexing.shader_test @@ -120,8 +120,8 @@ float4 main() : sv_target
[test] uniform 0 float 2 -todo(sm>=6) draw quad -probe all rgba (8, 9, 10, 11) +draw quad +todo(sm>=6) probe all rgba (8, 9, 10, 11)
[pixel shader] @@ -136,5 +136,5 @@ float4 main() : sv_target
[test] uniform 0 float 3 -todo(sm>=6) draw quad +draw quad todo(sm>=6) probe all rgba (12, 13, 14, 15) diff --git a/tests/hlsl/non-const-indexing.shader_test b/tests/hlsl/non-const-indexing.shader_test index 3a1e12acc..638107e79 100644 --- a/tests/hlsl/non-const-indexing.shader_test +++ b/tests/hlsl/non-const-indexing.shader_test @@ -36,17 +36,17 @@ float4 main() : SV_TARGET
[test] uniform 0 float 0 -todo(sm>=6) draw quad -probe all rgba (11.0, 11.0, 11.0, 11.0) +draw quad +todo(sm>=6) probe all rgba (11.0, 11.0, 11.0, 11.0) uniform 0 float 1 -todo(sm>=6) draw quad -probe all rgba (12.0, 12.0, 12.0, 12.0) +draw quad +todo(sm>=6) probe all rgba (12.0, 12.0, 12.0, 12.0) uniform 0 float 2 -todo(sm>=6) draw quad -probe all rgba (13.0, 13.0, 13.0, 13.0) +draw quad +todo(sm>=6) probe all rgba (13.0, 13.0, 13.0, 13.0) uniform 0 float 3 -todo(sm>=6) draw quad -probe all rgba (14.0, 14.0, 14.0, 14.0) +draw quad +todo(sm>=6) probe all rgba (14.0, 14.0, 14.0, 14.0)
[pixel shader] @@ -61,7 +61,7 @@ float4 main() : sv_target
[test] uniform 0 float 2.3 -todo(sm>=6) draw quad +draw quad todo(sm>=6) probe all rgba (3, 3, 3, 3)
@@ -77,17 +77,17 @@ float4 main() : SV_TARGET
[test] uniform 0 float 0 -todo(sm>=6) draw quad -probe all rgba (21.0, 1.0, 24.0, 0.0) +draw quad +todo(sm>=6) probe all rgba (21.0, 1.0, 24.0, 0.0) uniform 0 float 1 -todo(sm>=6) draw quad -probe all rgba (22.0, 0.0, 23.0, 1.0) +draw quad +todo(sm>=6) probe all rgba (22.0, 0.0, 23.0, 1.0) uniform 0 float 2 -todo(sm>=6) draw quad -probe all rgba (23.0, 1.0, 22.0, 0.0) +draw quad +todo(sm>=6) probe all rgba (23.0, 1.0, 22.0, 0.0) uniform 0 float 3 -todo(sm>=6) draw quad -probe all rgba (24.0, 0.0, 21.0, 1.0) +draw quad +todo(sm>=6) probe all rgba (24.0, 0.0, 21.0, 1.0)
[pixel shader] @@ -102,16 +102,16 @@ float4 main() : sv_target
[test] uniform 0 float4 0 0 0 0 -todo(sm>=6) draw quad +draw quad todo(sm>=6) probe all rgba (1.0, 2.0, 3.0, 4.0) uniform 0 float4 1 0 0 0 -todo(sm>=6) draw quad +draw quad todo(sm>=6) probe all rgba (5.0, 6.0, 7.0, 8.0) uniform 0 float4 0 1 0 0 -todo(sm>=6) draw quad +draw quad todo(sm>=6) probe all rgba (5.0, 6.0, 7.0, 8.0) uniform 0 float4 1 1 0 0 -todo(sm>=6) draw quad +draw quad todo(sm>=6) probe all rgba (9.0, 10.0, 11.0, 12.0)
@@ -130,8 +130,8 @@ float4 main() : sv_target
[test] uniform 0 float4 0 0 2.4 0 -todo(sm>=6) draw quad -probe all rgba (1.0, 120.0, 90.0, 4.0) +draw quad +todo(sm>=6) probe all rgba (1.0, 120.0, 90.0, 4.0)
% SM1 doesn't support relative addressing if it is used in a l-value. diff --git a/tests/hlsl/vector-indexing-uniform.shader_test b/tests/hlsl/vector-indexing-uniform.shader_test index 3501f3af7..d494d8626 100644 --- a/tests/hlsl/vector-indexing-uniform.shader_test +++ b/tests/hlsl/vector-indexing-uniform.shader_test @@ -12,5 +12,5 @@ float4 main() : SV_TARGET
[test] uniform 0 float 2 -todo(sm>=6) draw quad -probe all rgba (0.5, 0.3, 0.8, 0.2) +draw quad +todo(sm>=6) probe all rgba (0.5, 0.3, 0.8, 0.2)
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/spirv.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 05066720a..57200ff5c 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -5484,30 +5484,29 @@ static void spirv_compiler_emit_dcl_indexable_temp(struct spirv_compiler *compil { const struct vkd3d_shader_indexable_temp *temp = &instruction->declaration.indexable_temp; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + enum vkd3d_shader_component_type component_type; struct vkd3d_shader_register reg; struct vkd3d_symbol reg_symbol; size_t function_location; uint32_t id;
- if (temp->component_count != 4) - FIXME("Unhandled component count %u.\n", temp->component_count); - vsir_register_init(®, VKD3DSPR_IDXTEMP, VKD3D_DATA_FLOAT, 1); reg.idx[0].offset = temp->register_idx;
function_location = spirv_compiler_get_current_function_location(compiler); vkd3d_spirv_begin_function_stream_insertion(builder, function_location);
+ component_type = vkd3d_component_type_from_data_type(temp->data_type); id = spirv_compiler_emit_array_variable(compiler, &builder->function_stream, - SpvStorageClassFunction, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE, &temp->register_size, 1); + SpvStorageClassFunction, component_type, temp->component_count, &temp->register_size, 1);
spirv_compiler_emit_register_debug_name(builder, id, ®);
vkd3d_spirv_end_function_stream_insertion(builder);
vkd3d_symbol_make_register(®_symbol, ®); - vkd3d_symbol_set_register_info(®_symbol, id, - SpvStorageClassFunction, VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL); + vkd3d_symbol_set_register_info(®_symbol, id, SpvStorageClassFunction, + component_type, vkd3d_write_mask_from_component_count(temp->component_count)); spirv_compiler_put_symbol(compiler, ®_symbol); }
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 14 ++++++++------ libs/vkd3d-shader/tpf.c | 1 + libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 3 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 9a527be7c..26f99b386 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -2421,7 +2421,7 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co return VKD3D_ERROR_INVALID_SHADER; } size = max(size, sizeof(icb->data[0])); - count = type->u.array.count * size / sizeof(icb->data[0]); + count = operands ? type->u.array.count * size / sizeof(icb->data[0]) : 0;
if (!(icb = vkd3d_malloc(offsetof(struct vkd3d_shader_immediate_constant_buffer, data[count])))) { @@ -2445,6 +2445,10 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co icb->data_type = vkd3d_data_type_from_sm6_type(elem_type); icb->element_count = type->u.array.count; icb->component_count = 1; + icb->is_null = !operands; + + if (!operands) + return VKD3D_OK;
count = type->u.array.count; if (size > sizeof(icb->data[0])) @@ -2519,12 +2523,10 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const switch (record->code) { case CST_CODE_NULL: - if (sm6_type_is_array(type)) + if (sm6_type_is_array(type) + && (ret = value_allocate_constant_array(dst, type, NULL, sm6)) < 0) { - FIXME("Constant null arrays are not supported.\n"); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, - "Constant null arrays are not supported."); - return VKD3D_ERROR_INVALID_SHADER; + return ret; } /* For non-aggregates, register constant data is already zero-filled. */ break; diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index 61d14e30d..a34f9042b 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -795,6 +795,7 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ui icb->data_type = VKD3D_DATA_FLOAT; icb->component_count = VKD3D_VEC4_SIZE; icb->element_count = icb_size / VKD3D_VEC4_SIZE; + icb->is_null = false; memcpy(icb->data, tokens, sizeof(*tokens) * icb_size); shader_instruction_array_add_icb(&priv->p.instructions, icb); ins->declaration.icb = icb; diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index d21ecc513..dc6112b3f 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -794,6 +794,7 @@ struct vkd3d_shader_immediate_constant_buffer /* total count is element_count * component_count */ unsigned int element_count; unsigned int component_count; + bool is_null; uint32_t data[]; };
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/spirv.c | 81 ++++++++++++++++++- tests/hlsl/matrix-indexing.shader_test | 4 +- tests/hlsl/non-const-indexing.shader_test | 28 +++---- .../hlsl/vector-indexing-uniform.shader_test | 2 +- 4 files changed, 94 insertions(+), 21 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 57200ff5c..accc0f85a 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -1194,6 +1194,16 @@ static uint32_t vkd3d_spirv_get_op_constant64(struct vkd3d_spirv_builder *builde (const uint32_t *)&value, 2, vkd3d_spirv_build_op_constant64); }
+static uint32_t vkd3d_spirv_build_op_constant_null(struct vkd3d_spirv_builder *builder, uint32_t result_type) +{ + return vkd3d_spirv_build_op_tr(builder, &builder->global_stream, SpvOpConstantNull, result_type); +} + +static uint32_t vkd3d_spirv_get_op_constant_null(struct vkd3d_spirv_builder *builder, uint32_t result_type) +{ + return vkd3d_spirv_build_once1(builder, SpvOpConstantNull, result_type, vkd3d_spirv_build_op_constant_null); +} + static uint32_t vkd3d_spirv_build_op_constant_composite(struct vkd3d_spirv_builder *builder, uint32_t result_type, const uint32_t *constituents, unsigned int constituent_count) { @@ -3753,6 +3763,61 @@ static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler, return val_id; }
+static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compiler, + const struct vkd3d_shader_immediate_constant_buffer *icb) +{ + uint32_t *elements, elem_type_id, length_id, type_id, const_id; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + unsigned int i, element_count; + + element_count = icb->element_count; + + elem_type_id = vkd3d_spirv_get_type_id_for_data_type(builder, icb->data_type, 1); + length_id = spirv_compiler_get_constant_uint(compiler, element_count); + type_id = vkd3d_spirv_get_op_type_array(builder, elem_type_id, length_id); + + if (icb->is_null) + { + /* All values are null. Workgroup memory initialisers require OpConstantNull. */ + return vkd3d_spirv_get_op_constant_null(builder, type_id); + } + + if (!(elements = vkd3d_calloc(element_count, sizeof(*elements)))) + { + ERR("Failed to allocate %u elements.", element_count); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_OUT_OF_MEMORY, + "Failed to allocate %u constant array elements.", element_count); + return 0; + } + + switch (icb->data_type) + { + case VKD3D_DATA_FLOAT: + case VKD3D_DATA_INT: + case VKD3D_DATA_UINT: + for (i = 0; i < element_count; ++i) + elements[i] = vkd3d_spirv_get_op_constant(builder, elem_type_id, icb->data[i]); + break; + case VKD3D_DATA_DOUBLE: + case VKD3D_DATA_UINT64: + { + uint64_t *data = (uint64_t *)icb->data; + for (i = 0; i < element_count; ++i) + elements[i] = vkd3d_spirv_get_op_constant64(builder, elem_type_id, data[i]); + break; + } + default: + FIXME("Unhandled data type %u.\n", icb->data_type); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_TYPE, + "Immediate constant buffer data type %u is unhandled.", icb->data_type); + break; + } + + const_id = vkd3d_spirv_build_op_constant_composite(builder, type_id, elements, element_count); + vkd3d_free(elements); + return const_id; +} + static const struct ssa_register_info *spirv_compiler_get_ssa_register_info(const struct spirv_compiler *compiler, const struct vkd3d_shader_register *reg) { @@ -5484,11 +5549,14 @@ static void spirv_compiler_emit_dcl_indexable_temp(struct spirv_compiler *compil { const struct vkd3d_shader_indexable_temp *temp = &instruction->declaration.indexable_temp; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t id, type_id, length_id, ptr_type_id, init_id = 0; enum vkd3d_shader_component_type component_type; struct vkd3d_shader_register reg; struct vkd3d_symbol reg_symbol; + SpvStorageClass storage_class; size_t function_location; - uint32_t id; + + storage_class = SpvStorageClassFunction;
vsir_register_init(®, VKD3DSPR_IDXTEMP, VKD3D_DATA_FLOAT, 1); reg.idx[0].offset = temp->register_idx; @@ -5497,15 +5565,20 @@ static void spirv_compiler_emit_dcl_indexable_temp(struct spirv_compiler *compil vkd3d_spirv_begin_function_stream_insertion(builder, function_location);
component_type = vkd3d_component_type_from_data_type(temp->data_type); - id = spirv_compiler_emit_array_variable(compiler, &builder->function_stream, - SpvStorageClassFunction, component_type, temp->component_count, &temp->register_size, 1); + type_id = vkd3d_spirv_get_type_id(builder, component_type, temp->component_count); + length_id = spirv_compiler_get_constant_uint(compiler, temp->register_size); + type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); + if (temp->initialiser) + init_id = spirv_compiler_emit_constant_array(compiler, temp->initialiser); + id = vkd3d_spirv_build_op_variable(builder, &builder->function_stream, ptr_type_id, storage_class, init_id);
spirv_compiler_emit_register_debug_name(builder, id, ®);
vkd3d_spirv_end_function_stream_insertion(builder);
vkd3d_symbol_make_register(®_symbol, ®); - vkd3d_symbol_set_register_info(®_symbol, id, SpvStorageClassFunction, + vkd3d_symbol_set_register_info(®_symbol, id, storage_class, component_type, vkd3d_write_mask_from_component_count(temp->component_count)); spirv_compiler_put_symbol(compiler, ®_symbol); } diff --git a/tests/hlsl/matrix-indexing.shader_test b/tests/hlsl/matrix-indexing.shader_test index bc4a46d03..f44ba63ef 100644 --- a/tests/hlsl/matrix-indexing.shader_test +++ b/tests/hlsl/matrix-indexing.shader_test @@ -121,7 +121,7 @@ float4 main() : sv_target [test] uniform 0 float 2 draw quad -todo(sm>=6) probe all rgba (8, 9, 10, 11) +probe all rgba (8, 9, 10, 11)
[pixel shader] @@ -137,4 +137,4 @@ float4 main() : sv_target [test] uniform 0 float 3 draw quad -todo(sm>=6) probe all rgba (12, 13, 14, 15) +probe all rgba (12, 13, 14, 15) diff --git a/tests/hlsl/non-const-indexing.shader_test b/tests/hlsl/non-const-indexing.shader_test index 638107e79..5c8e1db4a 100644 --- a/tests/hlsl/non-const-indexing.shader_test +++ b/tests/hlsl/non-const-indexing.shader_test @@ -37,16 +37,16 @@ float4 main() : SV_TARGET [test] uniform 0 float 0 draw quad -todo(sm>=6) probe all rgba (11.0, 11.0, 11.0, 11.0) +probe all rgba (11.0, 11.0, 11.0, 11.0) uniform 0 float 1 draw quad -todo(sm>=6) probe all rgba (12.0, 12.0, 12.0, 12.0) +probe all rgba (12.0, 12.0, 12.0, 12.0) uniform 0 float 2 draw quad -todo(sm>=6) probe all rgba (13.0, 13.0, 13.0, 13.0) +probe all rgba (13.0, 13.0, 13.0, 13.0) uniform 0 float 3 draw quad -todo(sm>=6) probe all rgba (14.0, 14.0, 14.0, 14.0) +probe all rgba (14.0, 14.0, 14.0, 14.0)
[pixel shader] @@ -62,7 +62,7 @@ float4 main() : sv_target [test] uniform 0 float 2.3 draw quad -todo(sm>=6) probe all rgba (3, 3, 3, 3) +probe all rgba (3, 3, 3, 3)
[pixel shader] @@ -78,16 +78,16 @@ float4 main() : SV_TARGET [test] uniform 0 float 0 draw quad -todo(sm>=6) probe all rgba (21.0, 1.0, 24.0, 0.0) +probe all rgba (21.0, 1.0, 24.0, 0.0) uniform 0 float 1 draw quad -todo(sm>=6) probe all rgba (22.0, 0.0, 23.0, 1.0) +probe all rgba (22.0, 0.0, 23.0, 1.0) uniform 0 float 2 draw quad -todo(sm>=6) probe all rgba (23.0, 1.0, 22.0, 0.0) +probe all rgba (23.0, 1.0, 22.0, 0.0) uniform 0 float 3 draw quad -todo(sm>=6) probe all rgba (24.0, 0.0, 21.0, 1.0) +probe all rgba (24.0, 0.0, 21.0, 1.0)
[pixel shader] @@ -103,16 +103,16 @@ float4 main() : sv_target [test] uniform 0 float4 0 0 0 0 draw quad -todo(sm>=6) probe all rgba (1.0, 2.0, 3.0, 4.0) +probe all rgba (1.0, 2.0, 3.0, 4.0) uniform 0 float4 1 0 0 0 draw quad -todo(sm>=6) probe all rgba (5.0, 6.0, 7.0, 8.0) +probe all rgba (5.0, 6.0, 7.0, 8.0) uniform 0 float4 0 1 0 0 draw quad -todo(sm>=6) probe all rgba (5.0, 6.0, 7.0, 8.0) +probe all rgba (5.0, 6.0, 7.0, 8.0) uniform 0 float4 1 1 0 0 draw quad -todo(sm>=6) probe all rgba (9.0, 10.0, 11.0, 12.0) +probe all rgba (9.0, 10.0, 11.0, 12.0)
[pixel shader] @@ -131,7 +131,7 @@ float4 main() : sv_target [test] uniform 0 float4 0 0 2.4 0 draw quad -todo(sm>=6) probe all rgba (1.0, 120.0, 90.0, 4.0) +probe all rgba (1.0, 120.0, 90.0, 4.0)
% SM1 doesn't support relative addressing if it is used in a l-value. diff --git a/tests/hlsl/vector-indexing-uniform.shader_test b/tests/hlsl/vector-indexing-uniform.shader_test index d494d8626..e5ffbdd02 100644 --- a/tests/hlsl/vector-indexing-uniform.shader_test +++ b/tests/hlsl/vector-indexing-uniform.shader_test @@ -13,4 +13,4 @@ float4 main() : SV_TARGET [test] uniform 0 float 2 draw quad -todo(sm>=6) probe all rgba (0.5, 0.3, 0.8, 0.2) +probe all rgba (0.5, 0.3, 0.8, 0.2)
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/spirv.c | 42 ++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 23 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index accc0f85a..193924f67 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -3764,18 +3764,24 @@ static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler, }
static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compiler, - const struct vkd3d_shader_immediate_constant_buffer *icb) + const struct vkd3d_shader_immediate_constant_buffer *icb, uint32_t *type_id_out) { uint32_t *elements, elem_type_id, length_id, type_id, const_id; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - unsigned int i, element_count; + enum vkd3d_shader_component_type component_type; + unsigned int i, element_count, component_count;
element_count = icb->element_count;
- elem_type_id = vkd3d_spirv_get_type_id_for_data_type(builder, icb->data_type, 1); + component_type = vkd3d_component_type_from_data_type(icb->data_type); + component_count = icb->component_count; + elem_type_id = vkd3d_spirv_get_type_id_for_data_type(builder, icb->data_type, component_count); length_id = spirv_compiler_get_constant_uint(compiler, element_count); type_id = vkd3d_spirv_get_op_type_array(builder, elem_type_id, length_id);
+ if (type_id_out) + *type_id_out = type_id; + if (icb->is_null) { /* All values are null. Workgroup memory initialisers require OpConstantNull. */ @@ -3796,14 +3802,16 @@ static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compil case VKD3D_DATA_INT: case VKD3D_DATA_UINT: for (i = 0; i < element_count; ++i) - elements[i] = vkd3d_spirv_get_op_constant(builder, elem_type_id, icb->data[i]); + elements[i] = spirv_compiler_get_constant(compiler, component_type, component_count, + &icb->data[component_count * i]); break; case VKD3D_DATA_DOUBLE: case VKD3D_DATA_UINT64: { uint64_t *data = (uint64_t *)icb->data; for (i = 0; i < element_count; ++i) - elements[i] = vkd3d_spirv_get_op_constant64(builder, elem_type_id, data[i]); + elements[i] = spirv_compiler_get_constant64(compiler, component_type, component_count, + &data[component_count * i]); break; } default: @@ -3814,7 +3822,7 @@ static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compil }
const_id = vkd3d_spirv_build_op_constant_composite(builder, type_id, elements, element_count); - vkd3d_free(elements); + return const_id; }
@@ -5570,7 +5578,7 @@ static void spirv_compiler_emit_dcl_indexable_temp(struct spirv_compiler *compil type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id); ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); if (temp->initialiser) - init_id = spirv_compiler_emit_constant_array(compiler, temp->initialiser); + init_id = spirv_compiler_emit_constant_array(compiler, temp->initialiser, NULL); id = vkd3d_spirv_build_op_variable(builder, &builder->function_stream, ptr_type_id, storage_class, init_id);
spirv_compiler_emit_register_debug_name(builder, id, ®); @@ -5797,34 +5805,22 @@ static void spirv_compiler_emit_dcl_immediate_constant_buffer(struct spirv_compi const struct vkd3d_shader_instruction *instruction) { const struct vkd3d_shader_immediate_constant_buffer *icb = instruction->declaration.icb; - uint32_t *elements, length_id, type_id, const_id, ptr_type_id, icb_id; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id, const_id, ptr_type_id, icb_id; struct vkd3d_shader_register reg; struct vkd3d_symbol reg_symbol; - unsigned int i; - - assert(icb->data_type == VKD3D_DATA_FLOAT); - assert(icb->component_count == VKD3D_VEC4_SIZE);
- if (!(elements = vkd3d_calloc(icb->element_count, sizeof(*elements)))) - return; - for (i = 0; i < icb->element_count; ++i) - elements[i] = spirv_compiler_get_constant(compiler, - VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE, &icb->data[4 * i]); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE); - length_id = spirv_compiler_get_constant_uint(compiler, icb->element_count); - type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id); - const_id = vkd3d_spirv_build_op_constant_composite(builder, type_id, elements, icb->element_count); + const_id = spirv_compiler_emit_constant_array(compiler, icb, &type_id); ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPrivate, type_id); icb_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, ptr_type_id, SpvStorageClassPrivate, const_id); vkd3d_spirv_build_op_name(builder, icb_id, "icb"); - vkd3d_free(elements);
vsir_register_init(®, VKD3DSPR_IMMCONSTBUFFER, VKD3D_DATA_FLOAT, 0); vkd3d_symbol_make_register(®_symbol, ®); vkd3d_symbol_set_register_info(®_symbol, icb_id, SpvStorageClassPrivate, - VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL); + vkd3d_component_type_from_data_type(icb->data_type), + vkd3d_write_mask_from_component_count(icb->component_count)); spirv_compiler_put_symbol(compiler, ®_symbol); }
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 2 ++ libs/vkd3d-shader/spirv.c | 10 ++++------ libs/vkd3d-shader/tpf.c | 14 ++++++++++++++ libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 4 files changed, 21 insertions(+), 6 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 26f99b386..cb016875f 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -581,6 +581,7 @@ struct sm6_parser size_t descriptor_count;
unsigned int indexable_temp_count; + unsigned int icb_count;
struct sm6_value *values; size_t value_count; @@ -2442,6 +2443,7 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co dst->value_type = VALUE_TYPE_ICB; dst->u.icb = icb;
+ icb->register_idx = sm6->icb_count++; icb->data_type = vkd3d_data_type_from_sm6_type(elem_type); icb->element_count = type->u.array.count; icb->component_count = 1; diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 193924f67..88f39c001 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -2162,6 +2162,7 @@ static void vkd3d_symbol_make_register(struct vkd3d_symbol *symbol, break;
case VKD3DSPR_IMMCONSTBUFFER: + symbol->key.reg.idx = reg->idx[0].offset; break;
default: @@ -3506,11 +3507,7 @@ static void spirv_compiler_emit_dereference_register(struct spirv_compiler *comp indexes[index_count++] = spirv_compiler_get_constant_uint(compiler, register_info->member_idx); indexes[index_count++] = spirv_compiler_emit_register_addressing(compiler, ®->idx[2]); } - else if (reg->type == VKD3DSPR_IMMCONSTBUFFER) - { - indexes[index_count++] = spirv_compiler_emit_register_addressing(compiler, ®->idx[0]); - } - else if (reg->type == VKD3DSPR_IDXTEMP) + else if (reg->type == VKD3DSPR_IMMCONSTBUFFER || reg->type == VKD3DSPR_IDXTEMP) { indexes[index_count++] = spirv_compiler_emit_register_addressing(compiler, ®->idx[1]); } @@ -5816,7 +5813,8 @@ static void spirv_compiler_emit_dcl_immediate_constant_buffer(struct spirv_compi ptr_type_id, SpvStorageClassPrivate, const_id); vkd3d_spirv_build_op_name(builder, icb_id, "icb");
- vsir_register_init(®, VKD3DSPR_IMMCONSTBUFFER, VKD3D_DATA_FLOAT, 0); + vsir_register_init(®, VKD3DSPR_IMMCONSTBUFFER, VKD3D_DATA_FLOAT, 1); + reg.idx[0].offset = icb->register_idx; vkd3d_symbol_make_register(®_symbol, ®); vkd3d_symbol_set_register_info(®_symbol, icb_id, SpvStorageClassPrivate, vkd3d_component_type_from_data_type(icb->data_type), diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index a34f9042b..d00e28db8 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -792,6 +792,7 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ui ins->handler_idx = VKD3DSIH_INVALID; return; } + icb->register_idx = 0; icb->data_type = VKD3D_DATA_FLOAT; icb->component_count = VKD3D_VEC4_SIZE; icb->element_count = icb_size / VKD3D_VEC4_SIZE; @@ -1931,6 +1932,19 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui break; } } + else if (register_type == VKD3D_SM4_RT_IMMCONSTBUFFER) + { + if (param->idx_count != 1) + { + WARN("Unexpected idx count %u.\n", param->idx_count); + vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_INDEX_COUNT, + "Invalid index count %u for immediate const buffer register; expected count 1.", param->idx_count); + } + param->idx[1] = param->idx[0]; + param->idx[0].offset = 0; + param->idx[0].rel_addr = NULL; + param->idx_count = 2; + } else if (!shader_is_sm_5_1(priv) && vsir_register_is_descriptor(param)) { /* SM5.1 places a symbol identifier in idx[0] and moves diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index dc6112b3f..d15afdc9d 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -790,6 +790,7 @@ struct vkd3d_shader_version
struct vkd3d_shader_immediate_constant_buffer { + unsigned int register_idx; enum vkd3d_data_type data_type; /* total count is element_count * component_count */ unsigned int element_count;
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/d3d_asm.c | 26 +++++++++++++++++++------- libs/vkd3d-shader/dxil.c | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 51 insertions(+), 9 deletions(-)
diff --git a/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d-shader/d3d_asm.c index f6d511e7c..ad71a20d2 100644 --- a/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d-shader/d3d_asm.c @@ -1599,7 +1599,7 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, const struct vkd3d_shader_instruction *ins) { struct vkd3d_string_buffer *buffer = &compiler->buffer; - unsigned int i; + unsigned int i, j;
if (ins->predicate) { @@ -1657,13 +1657,25 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler,
case VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER: vkd3d_string_buffer_printf(buffer, " {\n"); - assert(ins->declaration.icb->component_count == VKD3D_VEC4_SIZE); - for (i = 0; i < ins->declaration.icb->element_count; ++i) + if (ins->declaration.icb->component_count == 1) + { + for (i = 0; i < ins->declaration.icb->element_count; ) + { + for (j = 0; i < ins->declaration.icb->element_count && j < 4; ++i, ++j) + shader_print_hex_literal(compiler, !j ? " " : ", ", ins->declaration.icb->data[i], ""); + vkd3d_string_buffer_printf(buffer, "\n"); + } + } + else { - shader_print_hex_literal(compiler, " {", ins->declaration.icb->data[4 * i + 0], ""); - shader_print_hex_literal(compiler, ", ", ins->declaration.icb->data[4 * i + 1], ""); - shader_print_hex_literal(compiler, ", ", ins->declaration.icb->data[4 * i + 2], ""); - shader_print_hex_literal(compiler, ", ", ins->declaration.icb->data[4 * i + 3], "},\n"); + assert(ins->declaration.icb->component_count == VKD3D_VEC4_SIZE); + for (i = 0; i < ins->declaration.icb->element_count; ++i) + { + shader_print_hex_literal(compiler, " {", ins->declaration.icb->data[4 * i + 0], ""); + shader_print_hex_literal(compiler, ", ", ins->declaration.icb->data[4 * i + 1], ""); + shader_print_hex_literal(compiler, ", ", ins->declaration.icb->data[4 * i + 2], ""); + shader_print_hex_literal(compiler, ", ", ins->declaration.icb->data[4 * i + 3], "},\n"); + } } shader_addline(buffer, "}"); break; diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index cb016875f..e4dae737b 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -2639,6 +2639,18 @@ static struct vkd3d_shader_instruction *sm6_parser_add_instruction(struct sm6_pa return ins; }
+static void sm6_parser_declare_icb(struct sm6_parser *sm6, const struct sm6_type *elem_type, unsigned int count, + unsigned int alignment, unsigned int init, struct sm6_value *dst) +{ + enum vkd3d_data_type data_type = vkd3d_data_type_from_sm6_type(elem_type); + struct vkd3d_shader_instruction *ins; + + ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER); + /* The icb value index will be resolved later so forward references can be handled. */ + ins->declaration.icb = (void *)(intptr_t)init; + register_init_with_id(&dst->u.reg, VKD3DSPR_IMMCONSTBUFFER, data_type, init); +} + static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const struct sm6_type *elem_type, unsigned int count, unsigned int alignment, unsigned int init, struct sm6_value *dst) { @@ -2775,7 +2787,10 @@ static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_
if (address_space == ADDRESS_SPACE_DEFAULT) { - sm6_parser_declare_indexable_temp(sm6, scalar_type, count, alignment, init, dst); + if (is_constant) + sm6_parser_declare_icb(sm6, scalar_type, count, alignment, init, dst); + else + sm6_parser_declare_indexable_temp(sm6, scalar_type, count, alignment, init, dst); } else if (address_space == ADDRESS_SPACE_GROUPSHARED) { @@ -2819,11 +2834,11 @@ static const struct vkd3d_shader_immediate_constant_buffer *resolve_forward_init static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) { const struct dxil_block *block = &sm6->root_block; + size_t i, base_value_idx = sm6->value_count; struct vkd3d_shader_instruction *ins; const struct dxil_record *record; enum vkd3d_result ret; uint64_t version; - size_t i;
sm6->p.location.line = block->id; sm6->p.location.column = 0; @@ -2881,6 +2896,21 @@ static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) ins->declaration.indexable_temp.initialiser = resolve_forward_initialiser( (uintptr_t)ins->declaration.indexable_temp.initialiser, sm6); } + else if (ins->handler_idx == VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER) + { + ins->declaration.icb = resolve_forward_initialiser((uintptr_t)ins->declaration.icb, sm6); + } + } + for (i = base_value_idx; i < sm6->value_count; ++i) + { + const struct vkd3d_shader_immediate_constant_buffer *icb; + struct sm6_value *value = &sm6->values[i]; + + if (!sm6_value_is_register(value) || value->u.reg.type != VKD3DSPR_IMMCONSTBUFFER) + continue; + + if ((icb = resolve_forward_initialiser(value->u.reg.idx[0].offset, sm6))) + value->u.reg.idx[0].offset = icb->register_idx; }
return VKD3D_OK;
Giovanni Mascellani (@giomasce) commented about libs/vkd3d-shader/spirv.c:
} const_id = vkd3d_spirv_build_op_constant_composite(builder, type_id, elements, element_count);
- vkd3d_free(elements);
This look like a leak, doesn't it?
Giovanni Mascellani (@giomasce) commented about libs/vkd3d-shader/tpf.c:
break; } }
- else if (register_type == VKD3D_SM4_RT_IMMCONSTBUFFER)
- {
if (param->idx_count != 1)
{
WARN("Unexpected idx count %u.\n", param->idx_count);
vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_INDEX_COUNT,
"Invalid index count %u for immediate const buffer register; expected count 1.", param->idx_count);
}
param->idx[1] = param->idx[0];
param->idx[0].offset = 0;
param->idx[0].rel_addr = NULL;
param->idx_count = 2;
This breaks the `d3d-asm` disassembly for TPF. Relatedly, at some point we might want to start having two different dialects for the disassembly: one that closely mimics native disassembly for D3DBC and TPF and another one that retains information that is relevant for developing VSIR, including showing the indices "hidden" from the standard disassembly and possibly showing indices in a more consistent fashion.