Signed-off-by: Francisco Casas fcasas@codeweavers.com --- Makefile.am | 1 - libs/vkd3d-shader/hlsl.y | 72 ++++++++++++++++++++++++++++++++++------ 2 files changed, 61 insertions(+), 12 deletions(-)
diff --git a/Makefile.am b/Makefile.am index d15e50c3..1086d028 100644 --- a/Makefile.am +++ b/Makefile.am @@ -298,7 +298,6 @@ XFAIL_TESTS = \ tests/hlsl-initializer-flattening.shader_test \ tests/hlsl-initializer-invalid-n-args.shader_test \ tests/hlsl-initializer-local-array.shader_test \ - tests/hlsl-initializer-numeric.shader_test \ tests/hlsl-initializer-static-array.shader_test \ tests/hlsl-initializer-struct.shader_test \ tests/hlsl-bool-cast.shader_test \ diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 988e0743..a89e4432 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -1278,6 +1278,54 @@ static bool add_increment(struct hlsl_ctx *ctx, struct list *instrs, bool decrem return true; }
+static void numeric_var_initializer(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, + struct parse_variable_def *v, unsigned int reg_offset, struct hlsl_type *type, + unsigned int *initializer_i, struct list *instrs) +{ + unsigned int writemask_offset = 0; + unsigned int components_read = 0; + + if (type->type == HLSL_CLASS_MATRIX) + hlsl_fixme(ctx, &var->loc, "Matrix initializer\n"); + + while (components_read < hlsl_type_component_count(type)) + { + struct hlsl_ir_store *store; + struct hlsl_ir_constant *c; + struct hlsl_ir_node *node; + unsigned int width; + + assert(*initializer_i < v->initializer.args_count); + node = v->initializer.args[*initializer_i]; + *initializer_i += 1; + + width = hlsl_type_component_count(node->data_type); + components_read += width; + + if (components_read > hlsl_type_component_count(type)) + { + hlsl_error(ctx, &node->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, + "Initializer argument has spare components.\n"); + return; + } + + if (!(node = add_implicit_conversion(ctx, instrs, node, + hlsl_get_vector_type(ctx, type->base_type, width), &node->loc))) + return; + + if (!(c = hlsl_new_uint_constant(ctx, reg_offset, node->loc))) + return; + list_add_tail(instrs, &c->node.entry); + + if (!(store = hlsl_new_store(ctx, var, &c->node, node, + ((1u << width) - 1) << writemask_offset, node->loc))) + return; + list_add_tail(instrs, &store->node.entry); + + writemask_offset += width; + } +} + static void struct_var_initializer(struct hlsl_ctx *ctx, struct list *list, struct hlsl_ir_var *var, struct parse_initializer *initializer) { @@ -1449,7 +1497,6 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t if (v->initializer.args_count) { unsigned int size = initializer_size(&v->initializer); - struct hlsl_ir_load *load;
if (type->type <= HLSL_CLASS_LAST_NUMERIC && type->dimx * type->dimy != size && size != 1) @@ -1473,7 +1520,6 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t vkd3d_free(v); continue; } - if (type->type == HLSL_CLASS_STRUCT) { struct_var_initializer(ctx, statements_list, var, &v->initializer); @@ -1495,23 +1541,27 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t vkd3d_free(v); continue; } - if (v->initializer.args_count > 1) + + if (type->type <= HLSL_CLASS_LAST_NUMERIC && size == 1) { - hlsl_fixme(ctx, &v->loc, "Complex initializer."); - free_parse_initializer(&v->initializer); - vkd3d_free(v); - continue; + struct hlsl_ir_load *load = hlsl_new_var_load(ctx, var, var->loc); + + list_add_tail(v->initializer.instrs, &load->node.entry); + add_assignment(ctx, v->initializer.instrs, &load->node, ASSIGN_OP_ASSIGN, v->initializer.args[0]); } + else + { + unsigned int initializer_i = 0;
- load = hlsl_new_var_load(ctx, var, var->loc); - list_add_tail(v->initializer.instrs, &load->node.entry); - add_assignment(ctx, v->initializer.instrs, &load->node, ASSIGN_OP_ASSIGN, v->initializer.args[0]); - vkd3d_free(v->initializer.args); + numeric_var_initializer(ctx, var, v, 0, type, &initializer_i, v->initializer.instrs); + }
if (modifiers & HLSL_STORAGE_STATIC) list_move_tail(&ctx->static_initializers, v->initializer.instrs); else list_move_tail(statements_list, v->initializer.instrs); + + vkd3d_free(v->initializer.args); vkd3d_free(v->initializer.instrs); }