From: Francisco Casas fcasas@codeweavers.com
--- I did some minor changes, so I'm removing Francisco's Signed-off-by. --- libs/vkd3d-shader/hlsl.h | 6 ++ libs/vkd3d-shader/hlsl.y | 115 +++++++++++++++++++-- tests/hlsl-initializer-flatten.shader_test | 8 +- 3 files changed, 118 insertions(+), 11 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 802adf87..18b70853 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -726,6 +726,9 @@ struct hlsl_ir_function_decl *hlsl_get_func_decl(struct hlsl_ctx *ctx, const cha struct hlsl_type *hlsl_get_type(struct hlsl_scope *scope, const char *name, bool recursive); struct hlsl_ir_var *hlsl_get_var(struct hlsl_scope *scope, const char *name);
+struct hlsl_ir_node *hlsl_load_index(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *instr, + unsigned int idx, const struct vkd3d_shader_location *loc); + struct hlsl_type *hlsl_new_array_type(struct hlsl_ctx *ctx, struct hlsl_type *basic_type, unsigned int array_size); struct hlsl_ir_node *hlsl_new_binary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2); @@ -768,6 +771,9 @@ struct hlsl_ir_var *hlsl_new_var(struct hlsl_ctx *ctx, const char *name, struct struct hlsl_ir_load *hlsl_new_var_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, const struct vkd3d_shader_location loc);
+struct hlsl_ir_node *hlsl_store_index(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_var *var, + struct hlsl_ir_node *rhs, unsigned int idx, const struct vkd3d_shader_location *loc); + void hlsl_error(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc, enum vkd3d_shader_error error, const char *fmt, ...) VKD3D_PRINTF_FUNC(4, 5); void hlsl_fixme(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc, diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 1ee1db4c..5b57a7bd 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -1534,6 +1534,108 @@ static bool add_increment(struct hlsl_ctx *ctx, struct list *instrs, bool decrem return true; }
+static bool append_node_components(struct hlsl_ctx *ctx, struct list *instrs, + struct hlsl_ir_node *node, struct hlsl_ir_node **comps, unsigned int *comps_count, + const struct vkd3d_shader_location *loc) +{ + struct hlsl_type *type = node->data_type; + + switch (type->type) + { + case HLSL_CLASS_SCALAR: + case HLSL_CLASS_VECTOR: + case HLSL_CLASS_MATRIX: + { + unsigned int idx; + + for (idx = 0; idx < type->dimy * type->dimx; idx++) + { + struct hlsl_ir_node *value; + + if (!(value = hlsl_load_index(ctx, instrs, node, idx, loc))) + return false; + + comps[*comps_count] = value; + *comps_count += 1; + } + break; + } + + case HLSL_CLASS_STRUCT: + { + struct hlsl_struct_field *field; + struct hlsl_ir_node *load; + + LIST_FOR_EACH_ENTRY(field, type->e.elements, struct hlsl_struct_field, entry) + { + if (!add_record_load(ctx, instrs, node, field, *loc)) + return false; + + load = node_from_list(instrs); + if (!append_node_components(ctx, instrs, load, comps, comps_count, loc)) + return false; + } + break; + } + + case HLSL_CLASS_ARRAY: + { + struct hlsl_ir_constant *c; + struct hlsl_ir_node *load; + unsigned int i; + + for (i = 0; i < type->e.array.elements_count; i++) + { + if (!(c = hlsl_new_uint_constant(ctx, i, loc))) + return false; + list_add_tail(instrs, &c->node.entry); + + if (!add_array_load(ctx, instrs, node, &c->node, *loc)) + return false; + + load = node_from_list(instrs); + if (!append_node_components(ctx, instrs, load, comps, comps_count, loc)) + return false; + } + break; + } + + case HLSL_CLASS_OBJECT: + { + hlsl_fixme(ctx, loc, "Flattening of objects."); + return false; + } + } + + return true; +} + +static bool flatten_parse_initializer(struct hlsl_ctx *ctx, struct parse_initializer *initializer) +{ + unsigned int size = initializer_size(initializer); + unsigned int new_args_count = 0; + struct hlsl_ir_node **new_args; + bool success = true; + unsigned int i = 0; + + new_args = hlsl_alloc(ctx, size * sizeof(struct hlsl_ir_node *)); + if (!new_args) + return false; + + for (i = 0; i < initializer->args_count; i++) + { + success = append_node_components(ctx, initializer->instrs, initializer->args[i], new_args, + &new_args_count, &initializer->args[i]->loc); + if (!success) + break; + } + + vkd3d_free(initializer->args); + initializer->args = new_args; + initializer->args_count = new_args_count; + return success; +} + static void initialize_numeric_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, struct parse_initializer *initializer, unsigned int reg_offset, struct hlsl_type *type, unsigned int *initializer_offset) @@ -1768,14 +1870,13 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t } else { - if (v->initializer.args_count != size) + if (!flatten_parse_initializer(ctx, &v->initializer)) { - hlsl_fixme(ctx, &v->loc, "Flatten initializer."); free_parse_initializer(&v->initializer); vkd3d_free(v); continue; } - + assert(v->initializer.args_count == size); initialize_numeric_var(ctx, var, &v->initializer, 0, type, &initializer_offset); } } @@ -2113,7 +2214,7 @@ static struct hlsl_ir_node *compute_offset_from_index(struct hlsl_ctx *ctx, stru } }
-static struct hlsl_ir_node *load_index(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *instr, +struct hlsl_ir_node *hlsl_load_index(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *instr, unsigned int idx, const struct vkd3d_shader_location *loc) { struct hlsl_type *scal_type = hlsl_get_scalar_type(ctx, instr->data_type->base_type); @@ -2135,7 +2236,7 @@ static struct hlsl_ir_node *load_index(struct hlsl_ctx *ctx, struct list *instrs return &load->node; }
-static struct hlsl_ir_node *store_index(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_var *var, +struct hlsl_ir_node *hlsl_store_index(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_var *var, struct hlsl_ir_node *rhs, unsigned int idx, const struct vkd3d_shader_location *loc) { struct hlsl_ir_node *offset; @@ -2188,13 +2289,13 @@ static struct list *add_constructor(struct hlsl_ctx *ctx, struct hlsl_type *type { struct hlsl_ir_node *value;
- if (!(value = load_index(ctx, params->instrs, arg, j, &loc))) + if (!(value = hlsl_load_index(ctx, params->instrs, arg, j, &loc))) return NULL;
if (!(value = add_implicit_conversion(ctx, params->instrs, value, scal_type, &arg->loc))) return NULL;
- if (!store_index(ctx, params->instrs, var, value, idx, &loc)) + if (!hlsl_store_index(ctx, params->instrs, var, value, idx, &loc)) return NULL; } } diff --git a/tests/hlsl-initializer-flatten.shader_test b/tests/hlsl-initializer-flatten.shader_test index 3a430e0d..56e2e372 100644 --- a/tests/hlsl-initializer-flatten.shader_test +++ b/tests/hlsl-initializer-flatten.shader_test @@ -6,7 +6,7 @@ float4 main() : sv_target }
[test] -todo draw quad +draw quad probe all rgba (1, 2, 3, 4)
@@ -56,7 +56,7 @@ float4 main() : sv_target }
[test] -todo draw quad +draw quad probe all rgba (1.0, 2.0, 3.0, 4.0)
@@ -69,5 +69,5 @@ float4 main() : sv_target }
[test] -todo draw quad -probe all rgba (1.0, 2.0, 3.0, 4.0) +draw quad +todo probe all rgba (1.0, 2.0, 3.0, 4.0)