From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 52 ++++++++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 10 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 3e02bdad7..f770311b7 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -2600,7 +2600,7 @@ 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, +static struct vkd3d_shader_instruction *sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const struct sm6_type *elem_type, unsigned int count, unsigned int alignment, bool is_constant, struct sm6_value *dst) { @@ -2616,11 +2616,15 @@ static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, ins->declaration.indexable_temp.component_count = 1;
register_init_with_id(&dst->u.reg, VKD3DSPR_IDXTEMP, data_type, ins->declaration.indexable_temp.register_idx); + + return ins; }
static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_record *record) { + struct vkd3d_shader_src_param *initialiser; const struct sm6_type *type, *scalar_type; + struct vkd3d_shader_instruction *ins; unsigned int alignment, count; uint64_t address_space; struct sm6_value *dst; @@ -2718,17 +2722,17 @@ static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_ dst->type = type; dst->value_type = VALUE_TYPE_REG;
- if (init) - { - WARN("Unsupported initialiser.\n"); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, - "Global variable initialisers are not supported."); - return false; - } - if (address_space == ADDRESS_SPACE_DEFAULT) { - sm6_parser_declare_indexable_temp(sm6, scalar_type, count, alignment, is_constant, dst); + ins = sm6_parser_declare_indexable_temp(sm6, scalar_type, count, alignment, is_constant, dst); + if (init) + { + if (!(initialiser = instruction_src_params_alloc(ins, 1, sm6))) + return false; + src_param_init(initialiser); + /* The value index will be resolved later so forward references can be handled. */ + register_init_with_id(&initialiser->reg, VKD3DSPR_IMMCONSTBUFFER, VKD3D_DATA_FLOAT, init - 1); + } } else if (address_space == ADDRESS_SPACE_GROUPSHARED) { @@ -2749,9 +2753,29 @@ static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_ return true; }
+static void register_resolve_forward_initialiser(struct vkd3d_shader_register *initialiser, + struct sm6_parser *sm6) +{ + unsigned int index = initialiser->idx[0].offset; + const struct sm6_value *value; + + if (index >= sm6->value_count || !(value = sm6_parser_get_value_safe(sm6, index)) + || !sm6_value_is_register(value)) + { + WARN("Invalid initialiser index %u.\n", index); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Global variable initialiser value index %u is invalid.", index); + } + else + { + *initialiser = value->u.reg; + } +} + 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; @@ -2804,6 +2828,14 @@ 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->src_count) + register_resolve_forward_initialiser((struct vkd3d_shader_register *)&ins->src->reg, sm6); + } + return VKD3D_OK; }