At this point add_load() is split into add_load_component() and add_load_index(); register offsets are hidden for these functions.
Signed-off-by: Francisco Casas fcasas@codeweavers.com Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com ---
v3: * Using hlsl_get_string_buffer() and hlsl_release_string_buffer(). * Use switch statement in hlsl_get_type_from_path_index().
Signed-off-by: Francisco Casas fcasas@codeweavers.com --- libs/vkd3d-shader/hlsl.c | 107 ++++++++++++++++++++++++++++++- libs/vkd3d-shader/hlsl.h | 7 ++ libs/vkd3d-shader/hlsl.y | 135 ++++++++++++++------------------------- 3 files changed, 160 insertions(+), 89 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 2925b4e5..6bd27781 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -117,7 +117,7 @@ void hlsl_free_var(struct hlsl_ir_var *decl) vkd3d_free(decl); }
-static bool hlsl_type_is_row_major(const struct hlsl_type *type) +bool hlsl_type_is_row_major(const struct hlsl_type *type) { /* Default to column-major if the majority isn't explicitly set, which can * happen for anonymous nodes. */ @@ -314,6 +314,111 @@ unsigned int hlsl_compute_component_offset(struct hlsl_ctx *ctx, struct hlsl_typ return 0; }
+struct hlsl_type *hlsl_get_type_from_path_index(struct hlsl_ctx *ctx, const struct hlsl_type *type, + struct hlsl_ir_node *node) +{ + assert(node); + + switch (type->type) + { + case HLSL_CLASS_VECTOR: + return hlsl_get_scalar_type(ctx, type->base_type); + + case HLSL_CLASS_MATRIX: + if (hlsl_type_is_row_major(type)) + return hlsl_get_vector_type(ctx, type->base_type, type->dimx); + else + return hlsl_get_vector_type(ctx, type->base_type, type->dimy); + + case HLSL_CLASS_ARRAY: + return type->e.array.type; + + case HLSL_CLASS_STRUCT: + { + struct hlsl_ir_constant *c = hlsl_ir_constant(node); + + assert(c->value[0].u < type->e.record.field_count); + return type->e.record.fields[c->value[0].u].type; + } + + default: + assert(0); + return NULL; + } +} + +struct hlsl_ir_node *hlsl_new_offset_from_path_index(struct hlsl_ctx *ctx, struct hlsl_block *block, + struct hlsl_type *type, struct hlsl_ir_node *offset, struct hlsl_ir_node *idx, + const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_node *idx_offset = NULL; + struct hlsl_ir_constant *c; + + list_init(&block->instrs); + + switch (type->type) + { + case HLSL_CLASS_VECTOR: + idx_offset = idx; + break; + + case HLSL_CLASS_MATRIX: + { + if (!(c = hlsl_new_uint_constant(ctx, 4, loc))) + return NULL; + list_add_tail(&block->instrs, &c->node.entry); + + if (!(idx_offset = hlsl_new_binary_expr(ctx, HLSL_OP2_MUL, &c->node, idx))) + return NULL; + list_add_tail(&block->instrs, &idx_offset->entry); + + break; + } + + case HLSL_CLASS_ARRAY: + { + unsigned int size = hlsl_type_get_array_element_reg_size(type->e.array.type); + + if (!(c = hlsl_new_uint_constant(ctx, size, loc))) + return NULL; + list_add_tail(&block->instrs, &c->node.entry); + + if (!(idx_offset = hlsl_new_binary_expr(ctx, HLSL_OP2_MUL, &c->node, idx))) + return NULL; + list_add_tail(&block->instrs, &idx_offset->entry); + + break; + } + + case HLSL_CLASS_STRUCT: + { + unsigned int field_i = hlsl_ir_constant(idx)->value[0].u; + struct hlsl_struct_field *field = &type->e.record.fields[field_i]; + + if (!(c = hlsl_new_uint_constant(ctx, field->reg_offset, loc))) + return NULL; + list_add_tail(&block->instrs, &c->node.entry); + + idx_offset = &c->node; + + break; + } + + default: + assert(0); + return NULL; + } + + if (offset) + { + if (!(idx_offset = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, offset, idx_offset))) + return NULL; + list_add_tail(&block->instrs, &idx_offset->entry); + } + + return idx_offset; +} + struct hlsl_type *hlsl_new_array_type(struct hlsl_ctx *ctx, struct hlsl_type *basic_type, unsigned int array_size) { struct hlsl_type *type; diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index ce1f69df..2a6402ce 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -729,6 +729,12 @@ 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_type *hlsl_get_type_from_path_index(struct hlsl_ctx *ctx, const struct hlsl_type *type, + struct hlsl_ir_node *node); +struct hlsl_ir_node *hlsl_new_offset_from_path_index(struct hlsl_ctx *ctx, struct hlsl_block *block, + struct hlsl_type *type, struct hlsl_ir_node *offset, struct hlsl_ir_node *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); @@ -792,6 +798,7 @@ unsigned int hlsl_type_component_count(struct hlsl_type *type); unsigned int hlsl_type_get_array_element_reg_size(const struct hlsl_type *type); unsigned int hlsl_compute_component_offset(struct hlsl_ctx *ctx, struct hlsl_type *type, unsigned int idx, struct hlsl_type **comp_type); +bool hlsl_type_is_row_major(const struct hlsl_type *type); unsigned int hlsl_type_get_sm4_offset(const struct hlsl_type *type, unsigned int offset); bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2);
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 3b3d3582..aa351548 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -622,44 +622,52 @@ static struct hlsl_ir_jump *add_return(struct hlsl_ctx *ctx, struct list *instrs return jump; }
-static struct hlsl_ir_load *add_load(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *var_node, - struct hlsl_ir_node *offset, struct hlsl_type *data_type, const struct vkd3d_shader_location loc) +static struct hlsl_ir_load *add_load_index(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *var_node, + struct hlsl_ir_node *idx, const struct vkd3d_shader_location *loc) { - struct hlsl_ir_node *add = NULL; + struct hlsl_type *elem_type; + struct hlsl_ir_node *offset; struct hlsl_ir_load *load; + struct hlsl_block block; struct hlsl_ir_var *var;
+ elem_type = hlsl_get_type_from_path_index(ctx, var_node->data_type, idx); + if (var_node->type == HLSL_IR_LOAD) { const struct hlsl_deref *src = &hlsl_ir_load(var_node)->src;
var = src->var; - if (src->offset.node) - { - if (!(add = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, src->offset.node, offset))) - return NULL; - list_add_tail(instrs, &add->entry); - offset = add; - } + if (!(offset = hlsl_new_offset_from_path_index(ctx, &block, var_node->data_type, src->offset.node, idx, loc))) + return NULL; + list_move_tail(instrs, &block.instrs); } else { + struct vkd3d_string_buffer *name; struct hlsl_ir_store *store; - char name[27];
- sprintf(name, "<deref-%p>", var_node); - if (!(var = hlsl_new_synthetic_var(ctx, name, var_node->data_type, var_node->loc))) + if (!(offset = hlsl_new_offset_from_path_index(ctx, &block, var_node->data_type, NULL, idx, loc))) return NULL; + list_move_tail(instrs, &block.instrs);
- if (!(store = hlsl_new_simple_store(ctx, var, var_node))) + if (!(name = hlsl_get_string_buffer(ctx))) + return NULL; + vkd3d_string_buffer_printf(name, "<deref-%p>", var_node); + var = hlsl_new_synthetic_var(ctx, name->buffer, var_node->data_type, var_node->loc); + hlsl_release_string_buffer(ctx, name); + if (!var) return NULL;
+ if (!(store = hlsl_new_simple_store(ctx, var, var_node))) + return NULL; list_add_tail(instrs, &store->node.entry); }
- if (!(load = hlsl_new_load(ctx, var, offset, data_type, loc))) + if (!(load = hlsl_new_load(ctx, var, offset, elem_type, *loc))) return NULL; list_add_tail(instrs, &load->node.entry); + return load; }
@@ -723,61 +731,21 @@ static struct hlsl_ir_load *add_load_component(struct hlsl_ctx *ctx, struct list static bool add_record_load(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *record, unsigned int idx, const struct vkd3d_shader_location loc) { - const struct hlsl_struct_field *field; struct hlsl_ir_constant *c;
assert(idx < record->data_type->e.record.field_count); - field = &record->data_type->e.record.fields[idx];
- if (!(c = hlsl_new_uint_constant(ctx, field->reg_offset, &loc))) + if (!(c = hlsl_new_uint_constant(ctx, idx, &loc))) return false; list_add_tail(instrs, &c->node.entry);
- return !!add_load(ctx, instrs, record, &c->node, field->type, loc); + return !!add_load_index(ctx, instrs, record, &c->node, &loc); }
static struct hlsl_ir_node *add_binary_arithmetic_expr(struct hlsl_ctx *ctx, struct list *instrs, enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2, const struct vkd3d_shader_location *loc);
-static struct hlsl_ir_node *add_matrix_scalar_load(struct hlsl_ctx *ctx, struct list *instrs, - struct hlsl_ir_node *matrix, struct hlsl_ir_node *x, struct hlsl_ir_node *y, - const struct vkd3d_shader_location *loc) -{ - struct hlsl_ir_node *major, *minor, *mul, *add; - struct hlsl_ir_constant *four; - struct hlsl_ir_load *load; - struct hlsl_type *type = matrix->data_type, *scalar_type; - - scalar_type = hlsl_get_scalar_type(ctx, type->base_type); - - if (type->modifiers & HLSL_MODIFIER_ROW_MAJOR) - { - minor = x; - major = y; - } - else - { - minor = y; - major = x; - } - - if (!(four = hlsl_new_uint_constant(ctx, 4, loc))) - return NULL; - list_add_tail(instrs, &four->node.entry); - - if (!(mul = add_binary_arithmetic_expr(ctx, instrs, HLSL_OP2_MUL, &four->node, major, loc))) - return NULL; - - if (!(add = add_binary_arithmetic_expr(ctx, instrs, HLSL_OP2_ADD, mul, minor, loc))) - return NULL; - - if (!(load = add_load(ctx, instrs, matrix, add, scalar_type, *loc))) - return NULL; - - return &load->node; -} - static bool add_matrix_index(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *matrix, struct hlsl_ir_node *index, const struct vkd3d_shader_location *loc) { @@ -788,6 +756,9 @@ static bool add_matrix_index(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_var *var; unsigned int i;
+ if (hlsl_type_is_row_major(mat_type)) + return add_load_index(ctx, instrs, matrix, index, loc); + ret_type = hlsl_get_vector_type(ctx, mat_type->base_type, mat_type->dimx);
name = vkd3d_string_buffer_get(&ctx->string_buffers); @@ -799,18 +770,21 @@ static bool add_matrix_index(struct hlsl_ctx *ctx, struct list *instrs,
for (i = 0; i < mat_type->dimx; ++i) { + struct hlsl_ir_load *column, *value; struct hlsl_ir_store *store; - struct hlsl_ir_node *value; struct hlsl_ir_constant *c;
if (!(c = hlsl_new_uint_constant(ctx, i, loc))) return false; list_add_tail(instrs, &c->node.entry);
- if (!(value = add_matrix_scalar_load(ctx, instrs, matrix, &c->node, index, loc))) + if (!(column = add_load_index(ctx, instrs, matrix, &c->node, loc))) return false;
- if (!(store = hlsl_new_store(ctx, var, &c->node, value, 0, *loc))) + if (!(value = add_load_index(ctx, instrs, &column->node, index, loc))) + return false; + + if (!(store = hlsl_new_store(ctx, var, &c->node, &value->node, 0, *loc))) return false; list_add_tail(instrs, &store->node.entry); } @@ -826,30 +800,11 @@ static bool add_array_load(struct hlsl_ctx *ctx, struct list *instrs, struct hls struct hlsl_ir_node *index, const struct vkd3d_shader_location loc) { const struct hlsl_type *expr_type = array->data_type; - struct hlsl_type *data_type; - struct hlsl_ir_constant *c; - - if (expr_type->type == HLSL_CLASS_ARRAY) - { - data_type = expr_type->e.array.type; - - if (!(c = hlsl_new_uint_constant(ctx, hlsl_type_get_array_element_reg_size(data_type), &loc))) - return false; - list_add_tail(instrs, &c->node.entry);
- if (!(index = hlsl_new_binary_expr(ctx, HLSL_OP2_MUL, index, &c->node))) - return false; - list_add_tail(instrs, &index->entry); - } - else if (expr_type->type == HLSL_CLASS_MATRIX) - { + if (expr_type->type == HLSL_CLASS_MATRIX) return add_matrix_index(ctx, instrs, array, index, &loc); - } - else if (expr_type->type == HLSL_CLASS_VECTOR) - { - data_type = hlsl_get_scalar_type(ctx, expr_type->base_type); - } - else + + if (expr_type->type != HLSL_CLASS_ARRAY && expr_type->type != HLSL_CLASS_VECTOR) { if (expr_type->type == HLSL_CLASS_SCALAR) hlsl_error(ctx, &loc, VKD3D_SHADER_ERROR_HLSL_INVALID_INDEX, "Scalar expressions cannot be array-indexed."); @@ -858,7 +813,10 @@ static bool add_array_load(struct hlsl_ctx *ctx, struct list *instrs, struct hls return false; }
- return !!add_load(ctx, instrs, array, index, data_type, loc); + if (!add_load_index(ctx, instrs, array, index, &loc)) + return false; + + return true; }
static const struct hlsl_struct_field *get_struct_field(const struct hlsl_struct_field *fields, @@ -1307,7 +1265,7 @@ static struct hlsl_ir_node *add_expr(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_constant *c; unsigned int j;
- if (!(c = hlsl_new_uint_constant(ctx, 4 * i, loc))) + if (!(c = hlsl_new_uint_constant(ctx, i, loc))) return NULL; list_add_tail(instrs, &c->node.entry);
@@ -1315,12 +1273,9 @@ static struct hlsl_ir_node *add_expr(struct hlsl_ctx *ctx, struct list *instrs, { if (operands[j]) { - struct hlsl_type *vector_arg_type; struct hlsl_ir_load *load;
- vector_arg_type = hlsl_get_vector_type(ctx, operands[j]->data_type->base_type, minor_size(type)); - - if (!(load = add_load(ctx, instrs, operands[j], &c->node, vector_arg_type, *loc))) + if (!(load = add_load_index(ctx, instrs, operands[j], &c->node, loc))) return NULL; vector_operands[j] = &load->node; } @@ -1329,6 +1284,10 @@ static struct hlsl_ir_node *add_expr(struct hlsl_ctx *ctx, struct list *instrs, if (!(value = add_expr(ctx, instrs, op, vector_operands, vector_type, loc))) return NULL;
+ if (!(c = hlsl_new_uint_constant(ctx, 4 * i, loc))) + return NULL; + list_add_tail(instrs, &c->node.entry); + if (!(store = hlsl_new_store(ctx, var, &c->node, value, 0, *loc))) return NULL; list_add_tail(instrs, &store->node.entry);