Replaces register offsets with component index paths to remove backend-specific offset/size logic from the IR. Also, working with components would allow for implicit size array initializers and properly handle objects which have register size 0.
In `vkd3d-shader/hlsl: Replace register offsets with index paths in load initializations.` the `transform_deref_paths_into_offsets` pass is introduced and moved forward in the following patches as other compilation passes are translated. The idea is to remove this pass after all the others are translated and then make each shader-model handle register offsets separately.
Patches for translating copy propagation, among other things, are prepared for a following merge request.
From: Francisco Casas fcasas@codeweavers.com
Signed-off-by: Francisco Casas fcasas@codeweavers.com Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com ---
v4: * Renamed "var_node" argument to "var_instr" in add_load_component(). --- libs/vkd3d-shader/hlsl.y | 99 +++++++++++++++++++++++++++------------- 1 file changed, 68 insertions(+), 31 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index bfafd981..7e7ccc20 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -272,8 +272,8 @@ static bool implicit_compatible_data_types(struct hlsl_type *t1, struct hlsl_typ return false; }
-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_component(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *var_instr, + unsigned int comp, const struct vkd3d_shader_location *loc);
static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *node, struct hlsl_type *dst_type, const struct vkd3d_shader_location *loc) @@ -311,8 +311,8 @@ static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct list *instrs,
for (dst_idx = 0; dst_idx < dst_type->dimx * dst_type->dimy; ++dst_idx) { - struct hlsl_type *src_scalar_type, *dst_scalar_type; - unsigned int src_idx, src_offset, dst_offset; + struct hlsl_type *dst_scalar_type; + unsigned int src_idx, dst_offset; struct hlsl_ir_store *store; struct hlsl_ir_constant *c;
@@ -335,13 +335,8 @@ static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct list *instrs, }
dst_offset = hlsl_compute_component_offset(ctx, dst_type, dst_idx, &dst_scalar_type); - src_offset = hlsl_compute_component_offset(ctx, src_type, src_idx, &src_scalar_type); - - if (!(c = hlsl_new_uint_constant(ctx, src_offset, loc))) - return NULL; - list_add_tail(instrs, &c->node.entry);
- if (!(load = add_load(ctx, instrs, node, &c->node, src_scalar_type, *loc))) + if (!(load = add_load_component(ctx, instrs, node, src_idx, loc))) return NULL;
if (!(cast = hlsl_new_cast(ctx, &load->node, dst_scalar_type, loc))) @@ -668,6 +663,63 @@ static struct hlsl_ir_load *add_load(struct hlsl_ctx *ctx, struct list *instrs, return load; }
+static struct hlsl_ir_load *add_load_component(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *var_instr, + unsigned int comp, const struct vkd3d_shader_location *loc) +{ + struct hlsl_type *comp_type; + struct hlsl_ir_node *offset; + struct hlsl_ir_constant *c; + struct hlsl_ir_load *load; + unsigned int comp_offset; + struct hlsl_ir_var *var; + + comp_offset = hlsl_compute_component_offset(ctx, var_instr->data_type, comp, &comp_type); + + if (!(c = hlsl_new_uint_constant(ctx, comp_offset, loc))) + return NULL; + list_add_tail(instrs, &c->node.entry); + + offset = &c->node; + + if (var_instr->type == HLSL_IR_LOAD) + { + const struct hlsl_deref *src = &hlsl_ir_load(var_instr)->src; + struct hlsl_ir_node *add; + + var = src->var; + if (src->offset.node) + { + if (!(add = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, src->offset.node, &c->node))) + return NULL; + list_add_tail(instrs, &add->entry); + offset = add; + } + } + else + { + struct vkd3d_string_buffer *name; + struct hlsl_ir_store *store; + + if (!(name = hlsl_get_string_buffer(ctx))) + return NULL; + vkd3d_string_buffer_printf(name, "<deref-%p>", var_instr); + var = hlsl_new_synthetic_var(ctx, name->buffer, var_instr->data_type, var_instr->loc); + hlsl_release_string_buffer(ctx, name); + if (!var) + return NULL; + + if (!(store = hlsl_new_simple_store(ctx, var, var_instr))) + return NULL; + list_add_tail(instrs, &store->node.entry); + } + + if (!(load = hlsl_new_load(ctx, var, offset, comp_type, *loc))) + return NULL; + list_add_tail(instrs, &load->node.entry); + + return load; +} + 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) { @@ -1766,22 +1818,17 @@ static void initialize_var_components(struct hlsl_ctx *ctx, struct list *instrs,
for (k = 0; k < src_comp_count; ++k) { - struct hlsl_type *dst_comp_type, *src_comp_type; - unsigned int dst_reg_offset, src_reg_offset; + struct hlsl_type *dst_comp_type; + unsigned int dst_reg_offset; struct hlsl_ir_store *store; struct hlsl_ir_constant *c; struct hlsl_ir_load *load; struct hlsl_ir_node *conv;
- dst_reg_offset = hlsl_compute_component_offset(ctx, dst->data_type, *store_index, &dst_comp_type); - src_reg_offset = hlsl_compute_component_offset(ctx, src->data_type, k, &src_comp_type); - - if (!(c = hlsl_new_uint_constant(ctx, src_reg_offset, &src->loc))) + if (!(load = add_load_component(ctx, instrs, src, k, &src->loc))) return; - list_add_tail(instrs, &c->node.entry);
- if (!(load = add_load(ctx, instrs, src, &c->node, src_comp_type, src->loc))) - return; + dst_reg_offset = hlsl_compute_component_offset(ctx, dst->data_type, *store_index, &dst_comp_type);
if (!(conv = add_implicit_conversion(ctx, instrs, &load->node, dst_comp_type, &src->loc))) return; @@ -2218,20 +2265,10 @@ static bool intrinsic_mul(struct hlsl_ctx *ctx, struct hlsl_ir_load *value1, *value2; struct hlsl_ir_node *mul;
- offset = hlsl_compute_component_offset(ctx, cast_type1, j * cast_type1->dimx + k, &scalar_type); - if (!(c = hlsl_new_uint_constant(ctx, offset, loc))) - return false; - list_add_tail(params->instrs, &c->node.entry); - - if (!(value1 = add_load(ctx, params->instrs, cast1, &c->node, scalar_type, *loc))) - return false; - - offset = hlsl_compute_component_offset(ctx, cast_type2, k * cast_type2->dimx + i, &scalar_type); - if (!(c = hlsl_new_uint_constant(ctx, offset, loc))) + if (!(value1 = add_load_component(ctx, params->instrs, cast1, j * cast1->data_type->dimx + k, loc))) return false; - list_add_tail(params->instrs, &c->node.entry);
- if (!(value2 = add_load(ctx, params->instrs, cast2, &c->node, scalar_type, *loc))) + if (!(value2 = add_load_component(ctx, params->instrs, cast2, k * cast2->data_type->dimx + i, loc))) return false;
if (!(mul = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MUL, &value1->node, &value2->node, loc)))
From: Francisco Casas fcasas@codeweavers.com
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 ---
v4: * Renamed hlsl_get_type_from_path_index() to hlsl_get_inner_type_from_path_index(). * Renamed "node" argument to "idx" in hlsl_get_inner_type_from_path_index(). * Renamed "field_i" to "field_idx" in hlsl_new_offset_from_path_index(). * Renamed "var_node" argument to "var_instr" in add_load_index(). --- libs/vkd3d-shader/hlsl.c | 107 +++++++++++++++++++++++++++++- libs/vkd3d-shader/hlsl.h | 7 ++ libs/vkd3d-shader/hlsl.y | 139 ++++++++++++++------------------------- 3 files changed, 162 insertions(+), 91 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 2925b4e5..0f0634d8 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_inner_type_from_path_index(struct hlsl_ctx *ctx, const struct hlsl_type *type, + struct hlsl_ir_node *idx) +{ + assert(idx); + + 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(idx); + + 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_idx = hlsl_ir_constant(idx)->value[0].u; + struct hlsl_struct_field *field = &type->e.record.fields[field_idx]; + + 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..d5cbb560 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_inner_type_from_path_index(struct hlsl_ctx *ctx, const struct hlsl_type *type, + struct hlsl_ir_node *idx); +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 7e7ccc20..91b9f9ff 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_instr, + 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;
- if (var_node->type == HLSL_IR_LOAD) + elem_type = hlsl_get_inner_type_from_path_index(ctx, var_instr->data_type, idx); + + if (var_instr->type == HLSL_IR_LOAD) { - const struct hlsl_deref *src = &hlsl_ir_load(var_node)->src; + const struct hlsl_deref *src = &hlsl_ir_load(var_instr)->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_instr->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_instr->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_instr); + var = hlsl_new_synthetic_var(ctx, name->buffer, var_instr->data_type, var_instr->loc); + hlsl_release_string_buffer(ctx, name); + if (!var) return NULL;
+ if (!(store = hlsl_new_simple_store(ctx, var, var_instr))) + 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);
From: Francisco Casas fcasas@codeweavers.com
Signed-off-by: Francisco Casas fcasas@codeweavers.com Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com ---
v4: * No changes. --- libs/vkd3d-shader/hlsl.c | 16 ++++++++++++++++ libs/vkd3d-shader/hlsl.h | 2 ++ libs/vkd3d-shader/hlsl.y | 20 ++------------------ libs/vkd3d-shader/hlsl_codegen.c | 28 ++++++---------------------- 4 files changed, 26 insertions(+), 40 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 0f0634d8..3fa87ca3 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -124,6 +124,22 @@ bool hlsl_type_is_row_major(const struct hlsl_type *type) return !!(type->modifiers & HLSL_MODIFIER_ROW_MAJOR); }
+unsigned int hlsl_type_minor_size(const struct hlsl_type *type) +{ + if (type->type != HLSL_CLASS_MATRIX || hlsl_type_is_row_major(type)) + return type->dimx; + else + return type->dimy; +} + +unsigned int hlsl_type_major_size(const struct hlsl_type *type) +{ + if (type->type != HLSL_CLASS_MATRIX || hlsl_type_is_row_major(type)) + return type->dimy; + else + return type->dimx; +} + static unsigned int get_array_size(const struct hlsl_type *type) { if (type->type == HLSL_CLASS_ARRAY) diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index d5cbb560..b82689b0 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -799,6 +799,8 @@ 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_minor_size(const struct hlsl_type *type); +unsigned int hlsl_type_major_size(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 91b9f9ff..0c5e6aca 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -1218,22 +1218,6 @@ static bool expr_common_shape(struct hlsl_ctx *ctx, struct hlsl_type *t1, struct return true; }
-static unsigned int minor_size(const struct hlsl_type *type) -{ - if (type->modifiers & HLSL_MODIFIER_ROW_MAJOR) - return type->dimx; - else - return type->dimy; -} - -static unsigned int major_size(const struct hlsl_type *type) -{ - if (type->modifiers & HLSL_MODIFIER_ROW_MAJOR) - return type->dimy; - else - return type->dimx; -} - static struct hlsl_ir_node *add_expr(struct hlsl_ctx *ctx, struct list *instrs, enum hlsl_ir_expr_op op, struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS], struct hlsl_type *type, const struct vkd3d_shader_location *loc) @@ -1249,7 +1233,7 @@ static struct hlsl_ir_node *add_expr(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_load *load; struct hlsl_ir_var *var;
- vector_type = hlsl_get_vector_type(ctx, type->base_type, minor_size(type)); + vector_type = hlsl_get_vector_type(ctx, type->base_type, hlsl_type_minor_size(type));
name = vkd3d_string_buffer_get(&ctx->string_buffers); vkd3d_string_buffer_printf(name, "<split_op-%u>", counter++); @@ -1258,7 +1242,7 @@ static struct hlsl_ir_node *add_expr(struct hlsl_ctx *ctx, struct list *instrs, if (!var) return NULL;
- for (i = 0; i < major_size(type); i++) + for (i = 0; i < hlsl_type_major_size(type); ++i) { struct hlsl_ir_node *value, *vector_operands[HLSL_MAX_OPERANDS] = { NULL }; struct hlsl_ir_store *store; diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 484b415d..373439af 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -21,22 +21,6 @@ #include "hlsl.h" #include <stdio.h>
-static unsigned int minor_size(const struct hlsl_type *type) -{ - if (type->modifiers & HLSL_MODIFIER_ROW_MAJOR) - return type->dimx; - else - return type->dimy; -} - -static unsigned int major_size(const struct hlsl_type *type) -{ - if (type->modifiers & HLSL_MODIFIER_ROW_MAJOR) - return type->dimy; - else - return type->dimx; -} - /* Split uniforms into two variables representing the constant and temp * registers, and copy the former to the latter, so that writes to uniforms * work. */ @@ -86,11 +70,11 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct list *instrs, struct
if (type->type == HLSL_CLASS_MATRIX) { - struct hlsl_type *vector_type = hlsl_get_vector_type(ctx, type->base_type, minor_size(type)); + struct hlsl_type *vector_type = hlsl_get_vector_type(ctx, type->base_type, hlsl_type_minor_size(type)); struct hlsl_semantic vector_semantic = *semantic; unsigned int i;
- for (i = 0; i < major_size(type); ++i) + for (i = 0; i < hlsl_type_major_size(type); ++i) { prepend_input_copy(ctx, instrs, var, vector_type, 4 * i, modifiers, &vector_semantic); ++vector_semantic.index; @@ -176,11 +160,11 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct list *instrs, struct
if (type->type == HLSL_CLASS_MATRIX) { - struct hlsl_type *vector_type = hlsl_get_vector_type(ctx, type->base_type, minor_size(type)); + struct hlsl_type *vector_type = hlsl_get_vector_type(ctx, type->base_type, hlsl_type_minor_size(type)); struct hlsl_semantic vector_semantic = *semantic; unsigned int i;
- for (i = 0; i < major_size(type); ++i) + for (i = 0; i < hlsl_type_major_size(type); ++i) { append_output_copy(ctx, instrs, var, vector_type, 4 * i, modifiers, &vector_semantic); ++vector_semantic.index; @@ -915,7 +899,7 @@ static bool split_matrix_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr type = rhs->data_type; if (type->type != HLSL_CLASS_MATRIX) return false; - element_type = hlsl_get_vector_type(ctx, type->base_type, minor_size(type)); + element_type = hlsl_get_vector_type(ctx, type->base_type, hlsl_type_minor_size(type));
if (rhs->type != HLSL_IR_LOAD) { @@ -923,7 +907,7 @@ static bool split_matrix_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr return false; }
- for (i = 0; i < major_size(type); ++i) + for (i = 0; i < hlsl_type_major_size(type); ++i) { if (!split_copy(ctx, store, hlsl_ir_load(rhs), 4 * i, element_type)) return false;
From: Zebediah Figura zfigura@codeweavers.com
Signed-off-by: Francisco Casas fcasas@codeweavers.com Signed-off-by: Zebediah Figura zfigura@codeweavers.com Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com ---
v4: * No changes. --- include/private/list.h | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/include/private/list.h b/include/private/list.h index b4d681fe..5e92cfb2 100644 --- a/include/private/list.h +++ b/include/private/list.h @@ -150,8 +150,8 @@ static inline unsigned int list_count( const struct list *list ) return count; }
-/* move all elements from src to the tail of dst */ -static inline void list_move_tail( struct list *dst, struct list *src ) +/* move all elements from src to before the specified element */ +static inline void list_move_before( struct list *dst, struct list *src ) { if (list_empty(src)) return;
@@ -162,8 +162,8 @@ static inline void list_move_tail( struct list *dst, struct list *src ) list_init(src); }
-/* move all elements from src to the head of dst */ -static inline void list_move_head( struct list *dst, struct list *src ) +/* move all elements from src to after the specified element */ +static inline void list_move_after( struct list *dst, struct list *src ) { if (list_empty(src)) return;
@@ -174,6 +174,18 @@ static inline void list_move_head( struct list *dst, struct list *src ) list_init(src); }
+/* move all elements from src to the head of dst */ +static inline void list_move_head( struct list *dst, struct list *src ) +{ + list_move_after( dst, src ); +} + +/* move all elements from src to the tail of dst */ +static inline void list_move_tail( struct list *dst, struct list *src ) +{ + list_move_before( dst, src ); +} + /* iterate through the list */ #define LIST_FOR_EACH(cursor,list) \ for ((cursor) = (list)->next; (cursor) != (list); (cursor) = (cursor)->next)
From: Francisco Casas fcasas@codeweavers.com
The transform_deref_paths_into_offsets pass turns these index paths back into register offsets.
Signed-off-by: Francisco Casas fcasas@codeweavers.com Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com ---
The idea is that we can move the transform_deref_paths_into_offsets() pass forward as we translate more passes to work with index paths. This, until register offsets can be totally removed, after we implement the SMxIRs and their translations.
The aim is to have 3 ways of initializing load/store nodes when using index paths:
* One that initializes the node from a another's node deref and and optional index to be appended to that deref's path. * One that initializes the node from a deref and the index of a single basic component within it. This one also generates constant nodes for the required path, so it also initializes an instruction block whose instructions must be inserted in the instruction list. * One that initializes the node directly for a whole variable. These functions are already present: hlsl_new_var_load() and hlsl_new_simple_store().
The signatures of these functions are to be placed nearby in hlsl.h as they are introduced in the following patches.
It is worth noting that the use of index paths allows to remove the data type argument when initializing store/loads because it can now be deducted from the variable and the hlsl_deref.
Applying an index over a matrix derefence retrieves a vector. If the matrix is row_major, this corresponds to a row, otherwise, it corresponds to a column. So, the code should take matrix majority into account, at least until the split_matrix_copies pass.
The first index in a path after a loading a struct should be an hlsl_ir_constant, since the field that's being addressed is always known at parse-time.
hlsl_init_simple_deref_from_var() can be used to initialize a deref that can be passed by reference to the load and store initialization functions. This value is not responsible for allocating memory and thus, the caller is not required to call hlsl_cleanup_deref(). The deref obtained with this function, can also be passed as prefix to deref_from_component_index().
---
v4: * Changed comment for subtype_index_from_component_index() and init_deref_from_component_index(). * Renamed hlsl_new_offset_node_from_deref() to hlsl_new_offset_instr_from_deref(). * Renamed subtype_index_from_component_index() to traverse_path_from_component_index(). --- libs/vkd3d-shader/hlsl.c | 302 ++++++++++++++++++++++++++++++- libs/vkd3d-shader/hlsl.h | 35 +++- libs/vkd3d-shader/hlsl.y | 102 +++++------ libs/vkd3d-shader/hlsl_codegen.c | 44 +++++ 4 files changed, 414 insertions(+), 69 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 3fa87ca3..6697e3c1 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -330,6 +330,180 @@ unsigned int hlsl_compute_component_offset(struct hlsl_ctx *ctx, struct hlsl_typ return 0; }
+static bool type_is_single_component(const struct hlsl_type *type) +{ + return type->type == HLSL_CLASS_SCALAR || type->type == HLSL_CLASS_OBJECT; +} + +/* Given a type and a component index, this function moves one step through the path required to + * reach that component within the type. + * It returns the first index of this path. + * It sets *type_ptr to the (outermost) type within the original type that contains the component. + * It sets *index_ptr to the index of the component within *type_ptr. + * So, this function can be called several times in sequence to obtain all the path's indexes until + * the component is finally reached. */ +static unsigned int traverse_path_from_component_index(struct hlsl_ctx *ctx, + struct hlsl_type **type_ptr, unsigned int *index_ptr) +{ + struct hlsl_type *type = *type_ptr; + unsigned int index = *index_ptr; + + assert(!type_is_single_component(type)); + assert(index < hlsl_type_component_count(type)); + + switch (type->type) + { + case HLSL_CLASS_VECTOR: + assert(index < type->dimx); + *type_ptr = hlsl_get_scalar_type(ctx, type->base_type); + *index_ptr = 0; + return index; + + case HLSL_CLASS_MATRIX: + { + unsigned int y = index / type->dimx, x = index % type->dimx; + bool row_major = hlsl_type_is_row_major(type); + + assert(index < type->dimx * type->dimy); + *type_ptr = hlsl_get_vector_type(ctx, type->base_type, row_major ? type->dimx : type->dimy); + *index_ptr = row_major ? x : y; + return row_major ? y : x; + } + + case HLSL_CLASS_ARRAY: + { + unsigned int elem_comp_count = hlsl_type_component_count(type->e.array.type); + unsigned int array_index; + + *type_ptr = type->e.array.type; + *index_ptr = index % elem_comp_count; + array_index = index / elem_comp_count; + assert(array_index < type->e.array.elements_count); + return array_index; + } + + case HLSL_CLASS_STRUCT: + { + struct hlsl_struct_field *field; + unsigned int field_comp_count, i; + + for (i = 0; i < type->e.record.field_count; ++i) + { + field = &type->e.record.fields[i]; + field_comp_count = hlsl_type_component_count(field->type); + if (index < field_comp_count) + { + *type_ptr = field->type; + *index_ptr = index; + return i; + } + index -= field_comp_count; + } + assert(0); + return 0; + } + + default: + assert(0); + return 0; + } +} + +struct hlsl_type *hlsl_type_get_component_type(struct hlsl_ctx *ctx, struct hlsl_type *type, + unsigned int index) +{ + while (!type_is_single_component(type)) + traverse_path_from_component_index(ctx, &type, &index); + + return type; +} + +static bool init_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_var *var, + unsigned int path_len) +{ + deref->var = var; + deref->path_len = path_len; + deref->offset.node = NULL; + + if (path_len == 0) + { + deref->path = NULL; + return true; + } + + if (!(deref->path = hlsl_alloc(ctx, sizeof(*deref->path) * deref->path_len))) + { + deref->var = NULL; + deref->path_len = 0; + return false; + } + + return true; +} + +static struct hlsl_type *get_type_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref) +{ + struct hlsl_type *type; + unsigned int i; + + assert(deref); + assert(!deref->offset.node); + + type = deref->var->data_type; + for (i = 0; i < deref->path_len; ++i) + type = hlsl_get_inner_type_from_path_index(ctx, type, deref->path[i].node); + return type; +} + +/* Initializes a deref from another deref (prefix) and a component index. + * *block is initialized to contain the new constant node instructions used by the deref's path. */ +static bool init_deref_from_component_index(struct hlsl_ctx *ctx, struct hlsl_block *block, + struct hlsl_deref *deref, const struct hlsl_deref *prefix, unsigned int index, + const struct vkd3d_shader_location *loc) +{ + unsigned int path_len, path_index, deref_path_len, i; + struct hlsl_type *path_type; + struct hlsl_ir_constant *c; + + list_init(&block->instrs); + + path_len = 0; + path_type = get_type_from_deref(ctx, prefix); + path_index = index; + while (!type_is_single_component(path_type)) + { + traverse_path_from_component_index(ctx, &path_type, &path_index); + ++path_len; + } + + if (!init_deref(ctx, deref, prefix->var, prefix->path_len + path_len)) + return false; + + deref_path_len = 0; + for (i = 0; i < prefix->path_len; ++i) + hlsl_src_from_node(&deref->path[deref_path_len++], prefix->path[i].node); + + path_type = get_type_from_deref(ctx, prefix); + path_index = index; + while (!type_is_single_component(path_type)) + { + unsigned int next_index = traverse_path_from_component_index(ctx, &path_type, &path_index); + + if (!(c = hlsl_new_uint_constant(ctx, next_index, loc))) + { + hlsl_free_instr_list(&block->instrs); + return false; + } + list_add_tail(&block->instrs, &c->node.entry); + + hlsl_src_from_node(&deref->path[deref_path_len++], &c->node); + } + + assert(deref_path_len == deref->path_len); + + return true; +} + struct hlsl_type *hlsl_get_inner_type_from_path_index(struct hlsl_ctx *ctx, const struct hlsl_type *type, struct hlsl_ir_node *idx) { @@ -435,6 +609,37 @@ struct hlsl_ir_node *hlsl_new_offset_from_path_index(struct hlsl_ctx *ctx, struc return idx_offset; }
+struct hlsl_ir_node *hlsl_new_offset_instr_from_deref(struct hlsl_ctx *ctx, struct hlsl_block *block, + const struct hlsl_deref *deref, const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_node *offset = NULL; + struct hlsl_type *type; + unsigned int i; + + list_init(&block->instrs); + + if (deref->offset.node) + return deref->offset.node; + + assert(deref->var); + + type = deref->var->data_type; + + for (i = 0; i < deref->path_len; ++i) + { + struct hlsl_block idx_block; + + if (!(offset = hlsl_new_offset_from_path_index(ctx, &idx_block, type, offset, deref->path[i].node, loc))) + return NULL; + + list_move_tail(&block->instrs, &idx_block.instrs); + + type = hlsl_get_inner_type_from_path_index(ctx, type, deref->path[i].node); + } + + return 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; @@ -525,7 +730,7 @@ struct hlsl_ir_function_decl *hlsl_get_func_decl(struct hlsl_ctx *ctx, const cha return NULL; }
-unsigned int hlsl_type_component_count(struct hlsl_type *type) +unsigned int hlsl_type_component_count(const struct hlsl_type *type) { unsigned int count = 0, i;
@@ -742,8 +947,17 @@ static bool type_is_single_reg(const struct hlsl_type *type) return type->type == HLSL_CLASS_SCALAR || type->type == HLSL_CLASS_VECTOR; }
-static void cleanup_deref(struct hlsl_deref *deref) +void hlsl_cleanup_deref(struct hlsl_deref *deref) { + unsigned int i; + + for (i = 0; i < deref->path_len; ++i) + hlsl_src_remove(&deref->path[i]); + vkd3d_free(deref->path); + + deref->path = NULL; + deref->path_len = 0; + hlsl_src_remove(&deref->offset); }
@@ -759,13 +973,20 @@ struct hlsl_ir_store *hlsl_new_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *v return NULL;
init_node(&store->node, HLSL_IR_STORE, NULL, loc); - store->lhs.var = var; + init_deref(ctx, &store->lhs, var, 0); hlsl_src_from_node(&store->lhs.offset, offset); hlsl_src_from_node(&store->rhs, rhs); store->writemask = writemask; return store; }
+/* Initializes a simple variable derefence, so that it can be passed to load/store functions. */ +void hlsl_init_simple_deref_from_var(struct hlsl_deref *deref, struct hlsl_ir_var *var) +{ + memset(deref, 0, sizeof(*deref)); + deref->var = var; +} + struct hlsl_ir_store *hlsl_new_simple_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *lhs, struct hlsl_ir_node *rhs) { return hlsl_new_store(ctx, lhs, NULL, rhs, 0, rhs->loc); @@ -862,15 +1083,76 @@ struct hlsl_ir_load *hlsl_new_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var if (!(load = hlsl_alloc(ctx, sizeof(*load)))) return NULL; init_node(&load->node, HLSL_IR_LOAD, type, loc); - load->src.var = var; + init_deref(ctx, &load->src, var, 0); hlsl_src_from_node(&load->src.offset, offset); return load; }
+struct hlsl_ir_load *hlsl_new_load_index(struct hlsl_ctx *ctx, const struct hlsl_deref *deref, + struct hlsl_ir_node *idx, const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_load *load; + struct hlsl_type *type; + unsigned int i; + + assert(!deref->offset.node); + + type = get_type_from_deref(ctx, deref); + if (idx) + type = hlsl_get_inner_type_from_path_index(ctx, type, idx); + + if (!(load = hlsl_alloc(ctx, sizeof(*load)))) + return NULL; + init_node(&load->node, HLSL_IR_LOAD, type, *loc); + + if (!init_deref(ctx, &load->src, deref->var, deref->path_len + !!idx)) + { + vkd3d_free(load); + return NULL; + } + for (i = 0; i < deref->path_len; ++i) + hlsl_src_from_node(&load->src.path[i], deref->path[i].node); + if (idx) + hlsl_src_from_node(&load->src.path[deref->path_len], idx); + + return load; +} + struct hlsl_ir_load *hlsl_new_var_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, - const struct vkd3d_shader_location loc) + struct vkd3d_shader_location loc) +{ + struct hlsl_deref var_deref; + + hlsl_init_simple_deref_from_var(&var_deref, var); + return hlsl_new_load_index(ctx, &var_deref, NULL, &loc); +} + +struct hlsl_ir_load *hlsl_new_load_component(struct hlsl_ctx *ctx, struct hlsl_block *block, + const struct hlsl_deref *deref, unsigned int comp, const struct vkd3d_shader_location *loc) { - return hlsl_new_load(ctx, var, NULL, var->data_type, loc); + struct hlsl_type *type, *comp_type; + struct hlsl_block comp_path_block; + struct hlsl_ir_load *load; + + list_init(&block->instrs); + + if (!(load = hlsl_alloc(ctx, sizeof(*load)))) + return NULL; + + type = get_type_from_deref(ctx, deref); + comp_type = hlsl_type_get_component_type(ctx, type, comp); + init_node(&load->node, HLSL_IR_LOAD, comp_type, *loc); + + if (!init_deref_from_component_index(ctx, &comp_path_block, &load->src, deref, comp, loc)) + { + vkd3d_free(load); + return NULL; + } + list_move_tail(&block->instrs, &comp_path_block.instrs); + + list_add_tail(&block->instrs, &load->node.entry); + + return load; }
struct hlsl_ir_resource_load *hlsl_new_resource_load(struct hlsl_ctx *ctx, struct hlsl_type *data_type, @@ -1705,7 +1987,7 @@ static void free_ir_jump(struct hlsl_ir_jump *jump)
static void free_ir_load(struct hlsl_ir_load *load) { - cleanup_deref(&load->src); + hlsl_cleanup_deref(&load->src); vkd3d_free(load); }
@@ -1718,8 +2000,8 @@ static void free_ir_loop(struct hlsl_ir_loop *loop) static void free_ir_resource_load(struct hlsl_ir_resource_load *load) { hlsl_src_remove(&load->coords); - cleanup_deref(&load->sampler); - cleanup_deref(&load->resource); + hlsl_cleanup_deref(&load->sampler); + hlsl_cleanup_deref(&load->resource); hlsl_src_remove(&load->texel_offset); vkd3d_free(load); } @@ -1727,7 +2009,7 @@ static void free_ir_resource_load(struct hlsl_ir_resource_load *load) static void free_ir_store(struct hlsl_ir_store *store) { hlsl_src_remove(&store->rhs); - cleanup_deref(&store->lhs); + hlsl_cleanup_deref(&store->lhs); vkd3d_free(store); }
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index b82689b0..d7eb0595 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -374,6 +374,10 @@ struct hlsl_ir_swizzle struct hlsl_deref { struct hlsl_ir_var *var; + + unsigned int path_len; + struct hlsl_src *path; + struct hlsl_src offset; };
@@ -717,6 +721,8 @@ void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, enum vkd3d_shader_target_type target_type, struct vkd3d_shader_code *out);
+void hlsl_cleanup_deref(struct hlsl_deref *deref); + void hlsl_replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new);
void hlsl_free_instr(struct hlsl_ir_node *node); @@ -751,14 +757,29 @@ struct hlsl_ir_if *hlsl_new_if(struct hlsl_ctx *ctx, struct hlsl_ir_node *condit struct hlsl_ir_constant *hlsl_new_int_constant(struct hlsl_ctx *ctx, int n, const struct vkd3d_shader_location *loc); struct hlsl_ir_jump *hlsl_new_jump(struct hlsl_ctx *ctx, enum hlsl_ir_jump_type type, struct vkd3d_shader_location loc); -struct hlsl_ir_load *hlsl_new_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, struct hlsl_ir_node *offset, - struct hlsl_type *type, struct vkd3d_shader_location loc); -struct hlsl_ir_loop *hlsl_new_loop(struct hlsl_ctx *ctx, struct vkd3d_shader_location loc); + +void hlsl_init_simple_deref_from_var(struct hlsl_deref *deref, struct hlsl_ir_var *var); + +struct hlsl_ir_load *hlsl_new_var_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, + struct vkd3d_shader_location loc); +struct hlsl_ir_load *hlsl_new_load_index(struct hlsl_ctx *ctx, const struct hlsl_deref *deref, + struct hlsl_ir_node *idx, const struct vkd3d_shader_location *loc); +struct hlsl_ir_load *hlsl_new_load_component(struct hlsl_ctx *ctx, struct hlsl_block *block, + const struct hlsl_deref *deref, unsigned int comp, const struct vkd3d_shader_location *loc); + +struct hlsl_ir_store *hlsl_new_simple_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *lhs, struct hlsl_ir_node *rhs); + +struct hlsl_ir_node *hlsl_new_offset_instr_from_deref(struct hlsl_ctx *ctx, struct hlsl_block *block, + const struct hlsl_deref *deref, const struct vkd3d_shader_location *loc); + struct hlsl_ir_resource_load *hlsl_new_resource_load(struct hlsl_ctx *ctx, struct hlsl_type *data_type, enum hlsl_resource_load_type type, struct hlsl_ir_var *resource, struct hlsl_ir_node *resource_offset, struct hlsl_ir_var *sampler, struct hlsl_ir_node *sampler_offset, struct hlsl_ir_node *coords, struct hlsl_ir_node *texel_offset, const struct vkd3d_shader_location *loc); -struct hlsl_ir_store *hlsl_new_simple_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *lhs, struct hlsl_ir_node *rhs); + +struct hlsl_ir_load *hlsl_new_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, struct hlsl_ir_node *offset, + struct hlsl_type *type, struct vkd3d_shader_location loc); +struct hlsl_ir_loop *hlsl_new_loop(struct hlsl_ctx *ctx, struct vkd3d_shader_location loc); struct hlsl_ir_store *hlsl_new_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, struct hlsl_ir_node *offset, struct hlsl_ir_node *rhs, unsigned int writemask, struct vkd3d_shader_location loc); struct hlsl_type *hlsl_new_struct_type(struct hlsl_ctx *ctx, const char *name, @@ -775,8 +796,6 @@ struct hlsl_ir_node *hlsl_new_unary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr struct hlsl_ir_var *hlsl_new_var(struct hlsl_ctx *ctx, const char *name, struct hlsl_type *type, const struct vkd3d_shader_location loc, const struct hlsl_semantic *semantic, unsigned int modifiers, const struct hlsl_reg_reservation *reg_reservation); -struct hlsl_ir_load *hlsl_new_var_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, - 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); @@ -794,10 +813,12 @@ bool hlsl_scope_add_type(struct hlsl_scope *scope, struct hlsl_type *type);
struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, unsigned int default_majority, unsigned int modifiers); -unsigned int hlsl_type_component_count(struct hlsl_type *type); +unsigned int hlsl_type_component_count(const 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); +struct hlsl_type *hlsl_type_get_component_type(struct hlsl_ctx *ctx, struct hlsl_type *type, + unsigned int index); bool hlsl_type_is_row_major(const struct hlsl_type *type); unsigned int hlsl_type_minor_size(const struct hlsl_type *type); unsigned int hlsl_type_major_size(const struct hlsl_type *type); diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 0c5e6aca..2a92d89c 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -352,7 +352,7 @@ static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct list *instrs, list_add_tail(instrs, &store->node.entry); }
- if (!(load = hlsl_new_load(ctx, var, NULL, dst_type, *loc))) + if (!(load = hlsl_new_var_load(ctx, var, *loc))) return NULL; list_add_tail(instrs, &load->node.entry);
@@ -625,31 +625,18 @@ static struct hlsl_ir_jump *add_return(struct hlsl_ctx *ctx, struct list *instrs static struct hlsl_ir_load *add_load_index(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *var_instr, struct hlsl_ir_node *idx, const struct vkd3d_shader_location *loc) { - struct hlsl_type *elem_type; - struct hlsl_ir_node *offset; + const struct hlsl_deref *src; struct hlsl_ir_load *load; - struct hlsl_block block; - struct hlsl_ir_var *var; - - elem_type = hlsl_get_inner_type_from_path_index(ctx, var_instr->data_type, idx);
if (var_instr->type == HLSL_IR_LOAD) { - const struct hlsl_deref *src = &hlsl_ir_load(var_instr)->src; - - var = src->var; - if (!(offset = hlsl_new_offset_from_path_index(ctx, &block, var_instr->data_type, src->offset.node, idx, loc))) - return NULL; - list_move_tail(instrs, &block.instrs); + src = &hlsl_ir_load(var_instr)->src; } else { struct vkd3d_string_buffer *name; struct hlsl_ir_store *store; - - if (!(offset = hlsl_new_offset_from_path_index(ctx, &block, var_instr->data_type, NULL, idx, loc))) - return NULL; - list_move_tail(instrs, &block.instrs); + struct hlsl_ir_var *var;
if (!(name = hlsl_get_string_buffer(ctx))) return NULL; @@ -662,9 +649,11 @@ static struct hlsl_ir_load *add_load_index(struct hlsl_ctx *ctx, struct list *in if (!(store = hlsl_new_simple_store(ctx, var, var_instr))) return NULL; list_add_tail(instrs, &store->node.entry); + + src = &store->lhs; }
- if (!(load = hlsl_new_load(ctx, var, offset, elem_type, *loc))) + if (!(load = hlsl_new_load_index(ctx, src, idx, loc))) return NULL; list_add_tail(instrs, &load->node.entry);
@@ -674,39 +663,19 @@ static struct hlsl_ir_load *add_load_index(struct hlsl_ctx *ctx, struct list *in static struct hlsl_ir_load *add_load_component(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *var_instr, unsigned int comp, const struct vkd3d_shader_location *loc) { - struct hlsl_type *comp_type; - struct hlsl_ir_node *offset; - struct hlsl_ir_constant *c; + const struct hlsl_deref *src; struct hlsl_ir_load *load; - unsigned int comp_offset; - struct hlsl_ir_var *var; - - comp_offset = hlsl_compute_component_offset(ctx, var_instr->data_type, comp, &comp_type); - - if (!(c = hlsl_new_uint_constant(ctx, comp_offset, loc))) - return NULL; - list_add_tail(instrs, &c->node.entry); - - offset = &c->node; + struct hlsl_block block;
if (var_instr->type == HLSL_IR_LOAD) { - const struct hlsl_deref *src = &hlsl_ir_load(var_instr)->src; - struct hlsl_ir_node *add; - - var = src->var; - if (src->offset.node) - { - if (!(add = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, src->offset.node, &c->node))) - return NULL; - list_add_tail(instrs, &add->entry); - offset = add; - } + src = &hlsl_ir_load(var_instr)->src; } else { struct vkd3d_string_buffer *name; struct hlsl_ir_store *store; + struct hlsl_ir_var *var;
if (!(name = hlsl_get_string_buffer(ctx))) return NULL; @@ -719,11 +688,13 @@ static struct hlsl_ir_load *add_load_component(struct hlsl_ctx *ctx, struct list if (!(store = hlsl_new_simple_store(ctx, var, var_instr))) return NULL; list_add_tail(instrs, &store->node.entry); + + src = &store->lhs; }
- if (!(load = hlsl_new_load(ctx, var, offset, comp_type, *loc))) + if (!(load = hlsl_new_load_component(ctx, &block, src, comp, loc))) return NULL; - list_add_tail(instrs, &load->node.entry); + list_move_tail(instrs, &block.instrs);
return load; } @@ -1277,7 +1248,7 @@ static struct hlsl_ir_node *add_expr(struct hlsl_ctx *ctx, struct list *instrs, list_add_tail(instrs, &store->node.entry); }
- if (!(load = hlsl_new_load(ctx, var, NULL, type, *loc))) + if (!(load = hlsl_new_var_load(ctx, var, *loc))) return NULL; list_add_tail(instrs, &load->node.entry);
@@ -1634,8 +1605,10 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct list *in { struct hlsl_type *lhs_type = lhs->data_type; struct hlsl_ir_store *store; + struct hlsl_ir_node *offset; struct hlsl_ir_expr *copy; unsigned int writemask = 0; + struct hlsl_block block;
if (assign_op == ASSIGN_OP_SUB) { @@ -1704,10 +1677,13 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct list *in } }
+ offset = hlsl_new_offset_instr_from_deref(ctx, &block, &hlsl_ir_load(lhs)->src, &lhs->loc); + list_move_tail(instrs, &block.instrs); + init_node(&store->node, HLSL_IR_STORE, NULL, lhs->loc); store->writemask = writemask; store->lhs.var = hlsl_ir_load(lhs)->src.var; - hlsl_src_from_node(&store->lhs.offset, hlsl_ir_load(lhs)->src.offset.node); + hlsl_src_from_node(&store->lhs.offset, offset); hlsl_src_from_node(&store->rhs, rhs); list_add_tail(instrs, &store->node.entry);
@@ -2238,7 +2214,7 @@ static bool intrinsic_mul(struct hlsl_ctx *ctx, list_add_tail(params->instrs, &store->node.entry); }
- if (!(load = hlsl_new_load(ctx, var, NULL, matrix_type, *loc))) + if (!(load = hlsl_new_var_load(ctx, var, *loc))) return false; list_add_tail(params->instrs, &load->node.entry);
@@ -2447,8 +2423,10 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl && object_type->sampler_dim != HLSL_SAMPLER_DIM_CUBEARRAY) { const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); + struct hlsl_ir_node *object_load_offset; struct hlsl_ir_resource_load *load; struct hlsl_ir_node *coords; + struct hlsl_block block;
if (object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMS || object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMSARRAY) @@ -2473,8 +2451,11 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl hlsl_get_vector_type(ctx, HLSL_TYPE_INT, sampler_dim + 1), loc))) return false;
+ object_load_offset = hlsl_new_offset_instr_from_deref(ctx, &block, &object_load->src, loc); + list_move_tail(instrs, &block.instrs); + if (!(load = hlsl_new_resource_load(ctx, object_type->e.resource_format, HLSL_RESOURCE_LOAD, - object_load->src.var, object_load->src.offset.node, NULL, NULL, coords, NULL, loc))) + object_load->src.var, object_load_offset, NULL, NULL, coords, NULL, loc))) return false; list_add_tail(instrs, &load->node.entry); return true; @@ -2484,11 +2465,13 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl && object_type->sampler_dim != HLSL_SAMPLER_DIM_2DMSARRAY) { const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); + struct hlsl_ir_node *object_load_offset, *sampler_load_offset; const struct hlsl_type *sampler_type; struct hlsl_ir_resource_load *load; struct hlsl_ir_node *offset = NULL; struct hlsl_ir_load *sampler_load; struct hlsl_ir_node *coords; + struct hlsl_block block;
if (params->args_count != 2 && params->args_count != 3) { @@ -2524,11 +2507,18 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl return false; }
+ object_load_offset = hlsl_new_offset_instr_from_deref(ctx, &block, &object_load->src, loc); + list_move_tail(instrs, &block.instrs); + + sampler_load_offset = hlsl_new_offset_instr_from_deref(ctx, &block, &sampler_load->src, loc); + list_move_tail(instrs, &block.instrs); + if (!(load = hlsl_new_resource_load(ctx, object_type->e.resource_format, - HLSL_RESOURCE_SAMPLE, object_load->src.var, object_load->src.offset.node, - sampler_load->src.var, sampler_load->src.offset.node, coords, offset, loc))) + HLSL_RESOURCE_SAMPLE, object_load->src.var, object_load_offset, + sampler_load->src.var, sampler_load_offset, coords, offset, loc))) return false; list_add_tail(instrs, &load->node.entry); + return true; } else if ((!strcmp(name, "Gather") || !strcmp(name, "GatherRed") || !strcmp(name, "GatherBlue") @@ -2539,6 +2529,7 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl || object_type->sampler_dim == HLSL_SAMPLER_DIM_CUBEARRAY)) { const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); + struct hlsl_ir_node *object_load_offset, *sampler_load_offset; enum hlsl_resource_load_type load_type; const struct hlsl_type *sampler_type; struct hlsl_ir_resource_load *load; @@ -2547,6 +2538,7 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl struct hlsl_type *result_type; struct hlsl_ir_node *coords; unsigned int read_channel; + struct hlsl_block block;
if (!strcmp(name, "GatherGreen")) { @@ -2628,9 +2620,15 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc))) return false;
+ object_load_offset = hlsl_new_offset_instr_from_deref(ctx, &block, &object_load->src, loc); + list_move_tail(instrs, &block.instrs); + + sampler_load_offset = hlsl_new_offset_instr_from_deref(ctx, &block, &sampler_load->src, loc); + list_move_tail(instrs, &block.instrs); + if (!(load = hlsl_new_resource_load(ctx, result_type, - load_type, object_load->src.var, object_load->src.offset.node, - sampler_load->src.var, sampler_load->src.offset.node, coords, offset, loc))) + load_type, object_load->src.var, object_load_offset, + sampler_load->src.var, sampler_load_offset, coords, offset, loc))) return false; list_add_tail(instrs, &load->node.entry); return true; diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 373439af..99f15a04 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -21,6 +21,48 @@ #include "hlsl.h" #include <stdio.h>
+/* TODO: remove when no longer needed, only used for transform_deref_paths_into_offsets() */ +static void replace_deref_path_with_offset(struct hlsl_ctx *ctx, struct hlsl_deref *deref, + struct hlsl_ir_node *instr) +{ + struct hlsl_ir_node *offset; + struct hlsl_block block; + + if (!deref->var) + return; + + if (!(offset = hlsl_new_offset_instr_from_deref(ctx, &block, deref, &instr->loc))) + return; + list_move_before(&instr->entry, &block.instrs); + + hlsl_cleanup_deref(deref); + hlsl_src_from_node(&deref->offset, offset); +} + +/* TODO: remove when no longer needed. */ +static bool transform_deref_paths_into_offsets(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +{ + switch(instr->type) + { + case HLSL_IR_LOAD: + replace_deref_path_with_offset(ctx, &hlsl_ir_load(instr)->src, instr); + return true; + + case HLSL_IR_STORE: + replace_deref_path_with_offset(ctx, &hlsl_ir_store(instr)->lhs, instr); + return true; + + case HLSL_IR_RESOURCE_LOAD: + replace_deref_path_with_offset(ctx, &hlsl_ir_resource_load(instr)->resource, instr); + replace_deref_path_with_offset(ctx, &hlsl_ir_resource_load(instr)->sampler, instr); + return true; + + default: + return false; + } + return false; +} + /* Split uniforms into two variables representing the constant and temp * registers, and copy the former to the latter, so that writes to uniforms * work. */ @@ -1890,6 +1932,8 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry
list_move_head(&body->instrs, &ctx->static_initializers);
+ transform_ir(ctx, transform_deref_paths_into_offsets, body, NULL); /* TODO: move forward, remove when no longer needed */ + LIST_FOR_EACH_ENTRY(var, &ctx->globals->vars, struct hlsl_ir_var, scope_entry) { if (var->modifiers & HLSL_STORAGE_UNIFORM)
From: Francisco Casas fcasas@codeweavers.com
Signed-off-by: Francisco Casas fcasas@codeweavers.com Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com ---
v4: * No changes. --- libs/vkd3d-shader/hlsl.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 6697e3c1..be36f12c 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -1594,10 +1594,23 @@ static void dump_ir_var(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer
static void dump_deref(struct vkd3d_string_buffer *buffer, const struct hlsl_deref *deref) { + unsigned int i; + if (deref->var) { vkd3d_string_buffer_printf(buffer, "%s", deref->var->name); - if (deref->offset.node) + if (deref->path_len) + { + vkd3d_string_buffer_printf(buffer, "["); + for (i = 0; i < deref->path_len; ++i) + { + vkd3d_string_buffer_printf(buffer, "["); + dump_src(buffer, &deref->path[i]); + vkd3d_string_buffer_printf(buffer, "]"); + } + vkd3d_string_buffer_printf(buffer, "]"); + } + else if (deref->offset.node) { vkd3d_string_buffer_printf(buffer, "["); dump_src(buffer, &deref->offset);
From: Francisco Casas fcasas@codeweavers.com
Signed-off-by: Francisco Casas fcasas@codeweavers.com Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com ---
v4: * Add 'init_' prefix to deref_from_component_index() call. * While at it, renamed 'node' to 'instr' in intrinsic_mul(). --- libs/vkd3d-shader/hlsl.c | 28 ++++++++++++++++++ libs/vkd3d-shader/hlsl.h | 2 ++ libs/vkd3d-shader/hlsl.y | 64 +++++++++++++++++++--------------------- 3 files changed, 60 insertions(+), 34 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index be36f12c..986aa579 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -992,6 +992,34 @@ struct hlsl_ir_store *hlsl_new_simple_store(struct hlsl_ctx *ctx, struct hlsl_ir return hlsl_new_store(ctx, lhs, NULL, rhs, 0, rhs->loc); }
+struct hlsl_ir_store *hlsl_new_store_component(struct hlsl_ctx *ctx, struct hlsl_block *block, + const struct hlsl_deref *lhs, unsigned int comp, struct hlsl_ir_node *rhs) +{ + struct hlsl_block comp_path_block; + struct hlsl_ir_store *store; + + list_init(&block->instrs); + + if (!(store = hlsl_alloc(ctx, sizeof(*store)))) + return NULL; + init_node(&store->node, HLSL_IR_STORE, NULL, rhs->loc); + + if (!init_deref_from_component_index(ctx, &comp_path_block, &store->lhs, lhs, comp, &rhs->loc)) + { + vkd3d_free(store); + return NULL; + } + list_move_tail(&block->instrs, &comp_path_block.instrs); + hlsl_src_from_node(&store->rhs, rhs); + + if (type_is_single_reg(rhs->data_type)) + store->writemask = (1 << rhs->data_type->dimx) - 1; + + list_add_tail(&block->instrs, &store->node.entry); + + return store; +} + struct hlsl_ir_constant *hlsl_new_constant(struct hlsl_ctx *ctx, struct hlsl_type *type, const struct vkd3d_shader_location *loc) { diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index d7eb0595..8ef4d015 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -768,6 +768,8 @@ struct hlsl_ir_load *hlsl_new_load_component(struct hlsl_ctx *ctx, struct hlsl_b const struct hlsl_deref *deref, unsigned int comp, const struct vkd3d_shader_location *loc);
struct hlsl_ir_store *hlsl_new_simple_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *lhs, struct hlsl_ir_node *rhs); +struct hlsl_ir_store *hlsl_new_store_component(struct hlsl_ctx *ctx, struct hlsl_block *block, + const struct hlsl_deref *lhs, unsigned int comp, struct hlsl_ir_node *rhs);
struct hlsl_ir_node *hlsl_new_offset_instr_from_deref(struct hlsl_ctx *ctx, struct hlsl_block *block, const struct hlsl_deref *deref, const struct vkd3d_shader_location *loc); diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 2a92d89c..e75971be 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -289,6 +289,7 @@ static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct list *instrs, { struct vkd3d_string_buffer *name; static unsigned int counter = 0; + struct hlsl_deref var_deref; struct hlsl_ir_load *load; struct hlsl_ir_var *var; unsigned int dst_idx; @@ -308,13 +309,14 @@ static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct list *instrs, vkd3d_string_buffer_release(&ctx->string_buffers, name); if (!var) return NULL; + hlsl_init_simple_deref_from_var(&var_deref, var);
for (dst_idx = 0; dst_idx < dst_type->dimx * dst_type->dimy; ++dst_idx) { struct hlsl_type *dst_scalar_type; - unsigned int src_idx, dst_offset; struct hlsl_ir_store *store; - struct hlsl_ir_constant *c; + struct hlsl_block block; + unsigned int src_idx;
if (broadcast) { @@ -334,7 +336,7 @@ static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct list *instrs, } }
- dst_offset = hlsl_compute_component_offset(ctx, dst_type, dst_idx, &dst_scalar_type); + dst_scalar_type = hlsl_type_get_component_type(ctx, dst_type, dst_idx);
if (!(load = add_load_component(ctx, instrs, node, src_idx, loc))) return NULL; @@ -343,13 +345,9 @@ static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct list *instrs, return NULL; list_add_tail(instrs, &cast->node.entry);
- if (!(c = hlsl_new_uint_constant(ctx, dst_offset, loc))) - return NULL; - list_add_tail(instrs, &c->node.entry); - - if (!(store = hlsl_new_store(ctx, var, &c->node, &cast->node, 0, *loc))) + if (!(store = hlsl_new_store_component(ctx, &block, &var_deref, dst_idx, &cast->node))) return NULL; - list_add_tail(instrs, &store->node.entry); + list_move_tail(instrs, &block.instrs); }
if (!(load = hlsl_new_var_load(ctx, var, *loc))) @@ -723,6 +721,7 @@ static bool add_matrix_index(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_type *mat_type = matrix->data_type, *ret_type; struct vkd3d_string_buffer *name; static unsigned int counter = 0; + struct hlsl_deref var_deref; struct hlsl_ir_load *load; struct hlsl_ir_var *var; unsigned int i; @@ -738,12 +737,14 @@ static bool add_matrix_index(struct hlsl_ctx *ctx, struct list *instrs, vkd3d_string_buffer_release(&ctx->string_buffers, name); if (!var) return false; + hlsl_init_simple_deref_from_var(&var_deref, var);
for (i = 0; i < mat_type->dimx; ++i) { struct hlsl_ir_load *column, *value; struct hlsl_ir_store *store; struct hlsl_ir_constant *c; + struct hlsl_block block;
if (!(c = hlsl_new_uint_constant(ctx, i, loc))) return false; @@ -755,9 +756,9 @@ static bool add_matrix_index(struct hlsl_ctx *ctx, struct list *instrs, 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))) + if (!(store = hlsl_new_store_component(ctx, &block, &var_deref, i, &value->node))) return false; - list_add_tail(instrs, &store->node.entry); + list_move_tail(instrs, &block.instrs); }
if (!(load = hlsl_new_var_load(ctx, var, *loc))) @@ -1733,32 +1734,30 @@ static void initialize_var_components(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_var *dst, unsigned int *store_index, struct hlsl_ir_node *src) { unsigned int src_comp_count = hlsl_type_component_count(src->data_type); + struct hlsl_deref dst_deref; unsigned int k;
+ hlsl_init_simple_deref_from_var(&dst_deref, dst); + for (k = 0; k < src_comp_count; ++k) { struct hlsl_type *dst_comp_type; - unsigned int dst_reg_offset; struct hlsl_ir_store *store; - struct hlsl_ir_constant *c; struct hlsl_ir_load *load; struct hlsl_ir_node *conv; + struct hlsl_block block;
if (!(load = add_load_component(ctx, instrs, src, k, &src->loc))) return;
- dst_reg_offset = hlsl_compute_component_offset(ctx, dst->data_type, *store_index, &dst_comp_type); + dst_comp_type = hlsl_type_get_component_type(ctx, dst->data_type, *store_index);
if (!(conv = add_implicit_conversion(ctx, instrs, &load->node, dst_comp_type, &src->loc))) return;
- if (!(c = hlsl_new_uint_constant(ctx, dst_reg_offset, &src->loc))) + if (!(store = hlsl_new_store_component(ctx, &block, &dst_deref, *store_index, conv))) return; - list_add_tail(instrs, &c->node.entry); - - if (!(store = hlsl_new_store(ctx, dst, &c->node, conv, 0, src->loc))) - return; - list_add_tail(instrs, &store->node.entry); + list_move_tail(instrs, &block.instrs);
++*store_index; } @@ -2123,6 +2122,7 @@ static bool intrinsic_mul(struct hlsl_ctx *ctx, unsigned int i, j, k, vect_count = 0; struct vkd3d_string_buffer *name; static unsigned int counter = 0; + struct hlsl_deref var_deref; struct hlsl_ir_load *load; struct hlsl_ir_var *var;
@@ -2169,15 +2169,15 @@ static bool intrinsic_mul(struct hlsl_ctx *ctx, vkd3d_string_buffer_release(&ctx->string_buffers, name); if (!var) return false; + hlsl_init_simple_deref_from_var(&var_deref, var);
for (i = 0; i < matrix_type->dimx; ++i) + { for (j = 0; j < matrix_type->dimy; ++j) { - struct hlsl_ir_node *node = NULL; - struct hlsl_type *scalar_type; + struct hlsl_ir_node *instr = NULL; struct hlsl_ir_store *store; - struct hlsl_ir_constant *c; - unsigned int offset; + struct hlsl_block block;
for (k = 0; k < cast_type1->dimx && k < cast_type2->dimy; ++k) { @@ -2193,26 +2193,22 @@ static bool intrinsic_mul(struct hlsl_ctx *ctx, if (!(mul = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MUL, &value1->node, &value2->node, loc))) return false;
- if (node) + if (instr) { - if (!(node = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_ADD, node, mul, loc))) + if (!(instr = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_ADD, instr, mul, loc))) return false; } else { - node = mul; + instr = mul; } }
- offset = hlsl_compute_component_offset(ctx, matrix_type, j * matrix_type->dimx + i, &scalar_type); - if (!(c = hlsl_new_uint_constant(ctx, offset, loc))) + if (!(store = hlsl_new_store_component(ctx, &block, &var_deref, j * matrix_type->dimx + i, instr))) return false; - list_add_tail(params->instrs, &c->node.entry); - - if (!(store = hlsl_new_store(ctx, var, &c->node, node, 0, *loc))) - return false; - list_add_tail(params->instrs, &store->node.entry); + list_move_tail(params->instrs, &block.instrs); } + }
if (!(load = hlsl_new_var_load(ctx, var, *loc))) return false;
From: Francisco Casas fcasas@codeweavers.com
Signed-off-by: Francisco Casas fcasas@codeweavers.com Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com ---
v4: * No changes. --- libs/vkd3d-shader/hlsl.c | 115 +++++++++++---------------------------- libs/vkd3d-shader/hlsl.h | 4 +- libs/vkd3d-shader/hlsl.y | 27 ++------- 3 files changed, 40 insertions(+), 106 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 986aa579..b4e3525f 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -249,87 +249,6 @@ static struct hlsl_type *hlsl_new_type(struct hlsl_ctx *ctx, const char *name, e return type; }
-/* Returns the register offset of a given component within a type, given its index. - * *comp_type will be set to the type of the component. */ -unsigned int hlsl_compute_component_offset(struct hlsl_ctx *ctx, struct hlsl_type *type, - unsigned int idx, struct hlsl_type **comp_type) -{ - switch (type->type) - { - case HLSL_CLASS_SCALAR: - case HLSL_CLASS_VECTOR: - { - assert(idx < type->dimx * type->dimy); - *comp_type = hlsl_get_scalar_type(ctx, type->base_type); - return idx; - } - case HLSL_CLASS_MATRIX: - { - unsigned int minor, major, x = idx % type->dimx, y = idx / type->dimx; - - assert(idx < type->dimx * type->dimy); - - if (hlsl_type_is_row_major(type)) - { - minor = x; - major = y; - } - else - { - minor = y; - major = x; - } - - *comp_type = hlsl_get_scalar_type(ctx, type->base_type); - return 4 * major + minor; - } - - case HLSL_CLASS_ARRAY: - { - unsigned int elem_comp_count = hlsl_type_component_count(type->e.array.type); - unsigned int array_idx = idx / elem_comp_count; - unsigned int idx_in_elem = idx % elem_comp_count; - - assert(array_idx < type->e.array.elements_count); - - return array_idx * hlsl_type_get_array_element_reg_size(type->e.array.type) + - hlsl_compute_component_offset(ctx, type->e.array.type, idx_in_elem, comp_type); - } - - case HLSL_CLASS_STRUCT: - { - struct hlsl_struct_field *field; - unsigned int elem_comp_count, i; - - for (i = 0; i < type->e.record.field_count; ++i) - { - field = &type->e.record.fields[i]; - elem_comp_count = hlsl_type_component_count(field->type); - - if (idx < elem_comp_count) - { - return field->reg_offset + - hlsl_compute_component_offset(ctx, field->type, idx, comp_type); - } - idx -= elem_comp_count; - } - - assert(0); - return 0; - } - - case HLSL_CLASS_OBJECT: - { - assert(idx == 0); - *comp_type = type; - return 0; - } - } - - assert(0); - return 0; -} - static bool type_is_single_component(const struct hlsl_type *type) { return type->type == HLSL_CLASS_SCALAR || type->type == HLSL_CLASS_OBJECT; @@ -989,7 +908,39 @@ void hlsl_init_simple_deref_from_var(struct hlsl_deref *deref, struct hlsl_ir_va
struct hlsl_ir_store *hlsl_new_simple_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *lhs, struct hlsl_ir_node *rhs) { - return hlsl_new_store(ctx, lhs, NULL, rhs, 0, rhs->loc); + struct hlsl_deref lhs_deref; + + hlsl_init_simple_deref_from_var(&lhs_deref, lhs); + return hlsl_new_store_index(ctx, &lhs_deref, NULL, rhs, 0, &rhs->loc); +} + +struct hlsl_ir_store *hlsl_new_store_index(struct hlsl_ctx *ctx, const struct hlsl_deref *lhs, + struct hlsl_ir_node *idx, struct hlsl_ir_node *rhs, unsigned int writemask, const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_store *store; + unsigned int i; + + assert(lhs); + assert(!lhs->offset.node); + + if (!(store = hlsl_alloc(ctx, sizeof(*store)))) + return NULL; + init_node(&store->node, HLSL_IR_STORE, NULL, *loc); + + if (!init_deref(ctx, &store->lhs, lhs->var, lhs->path_len + !!idx)) + return NULL; + for (i = 0; i < lhs->path_len; ++i) + hlsl_src_from_node(&store->lhs.path[i], lhs->path[i].node); + if (idx) + hlsl_src_from_node(&store->lhs.path[lhs->path_len], idx); + + hlsl_src_from_node(&store->rhs, rhs); + + if (!writemask && type_is_single_reg(rhs->data_type)) + writemask = (1 << rhs->data_type->dimx) - 1; + store->writemask = writemask; + + return store; }
struct hlsl_ir_store *hlsl_new_store_component(struct hlsl_ctx *ctx, struct hlsl_block *block, diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 8ef4d015..76721c8e 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -768,6 +768,8 @@ struct hlsl_ir_load *hlsl_new_load_component(struct hlsl_ctx *ctx, struct hlsl_b const struct hlsl_deref *deref, unsigned int comp, const struct vkd3d_shader_location *loc);
struct hlsl_ir_store *hlsl_new_simple_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *lhs, struct hlsl_ir_node *rhs); +struct hlsl_ir_store *hlsl_new_store_index(struct hlsl_ctx *ctx, const struct hlsl_deref *lhs, + struct hlsl_ir_node *idx, struct hlsl_ir_node *rhs, unsigned int writemask, const struct vkd3d_shader_location *loc); struct hlsl_ir_store *hlsl_new_store_component(struct hlsl_ctx *ctx, struct hlsl_block *block, const struct hlsl_deref *lhs, unsigned int comp, struct hlsl_ir_node *rhs);
@@ -817,8 +819,6 @@ struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, unsigned int default_majority, unsigned int modifiers); unsigned int hlsl_type_component_count(const 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); struct hlsl_type *hlsl_type_get_component_type(struct hlsl_ctx *ctx, struct hlsl_type *type, unsigned int index); bool hlsl_type_is_row_major(const struct hlsl_type *type); diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index e75971be..a5152800 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -1202,6 +1202,7 @@ static struct hlsl_ir_node *add_expr(struct hlsl_ctx *ctx, struct list *instrs, struct vkd3d_string_buffer *name; static unsigned int counter = 0; struct hlsl_type *vector_type; + struct hlsl_deref var_deref; struct hlsl_ir_load *load; struct hlsl_ir_var *var;
@@ -1213,6 +1214,7 @@ static struct hlsl_ir_node *add_expr(struct hlsl_ctx *ctx, struct list *instrs, vkd3d_string_buffer_release(&ctx->string_buffers, name); if (!var) return NULL; + hlsl_init_simple_deref_from_var(&var_deref, var);
for (i = 0; i < hlsl_type_major_size(type); ++i) { @@ -1240,11 +1242,7 @@ 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))) + if (!(store = hlsl_new_store_index(ctx, &var_deref, &c->node, value, 0, loc))) return NULL; list_add_tail(instrs, &store->node.entry); } @@ -1606,10 +1604,8 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct list *in { struct hlsl_type *lhs_type = lhs->data_type; struct hlsl_ir_store *store; - struct hlsl_ir_node *offset; struct hlsl_ir_expr *copy; unsigned int writemask = 0; - struct hlsl_block block;
if (assign_op == ASSIGN_OP_SUB) { @@ -1634,15 +1630,11 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct list *in return NULL; }
- if (!(store = hlsl_alloc(ctx, sizeof(*store)))) - return NULL; - while (lhs->type != HLSL_IR_LOAD) { if (lhs->type == HLSL_IR_EXPR && hlsl_ir_expr(lhs)->op == HLSL_OP1_CAST) { hlsl_fixme(ctx, &lhs->loc, "Cast on the LHS."); - vkd3d_free(store); return NULL; } else if (lhs->type == HLSL_IR_SWIZZLE) @@ -1656,13 +1648,11 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct list *in if (!invert_swizzle(&s, &writemask, &width)) { hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_WRITEMASK, "Invalid writemask."); - vkd3d_free(store); return NULL; }
if (!(new_swizzle = hlsl_new_swizzle(ctx, s, width, rhs, &swizzle->node.loc))) { - vkd3d_free(store); return NULL; } list_add_tail(instrs, &new_swizzle->node.entry); @@ -1673,19 +1663,12 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct list *in else { hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_LVALUE, "Invalid lvalue."); - vkd3d_free(store); return NULL; } }
- offset = hlsl_new_offset_instr_from_deref(ctx, &block, &hlsl_ir_load(lhs)->src, &lhs->loc); - list_move_tail(instrs, &block.instrs); - - init_node(&store->node, HLSL_IR_STORE, NULL, lhs->loc); - store->writemask = writemask; - store->lhs.var = hlsl_ir_load(lhs)->src.var; - hlsl_src_from_node(&store->lhs.offset, offset); - hlsl_src_from_node(&store->rhs, rhs); + if (!(store = hlsl_new_store_index(ctx, &hlsl_ir_load(lhs)->src, NULL, rhs, writemask, &rhs->loc))) + return NULL; list_add_tail(instrs, &store->node.entry);
/* Don't use the instruction itself as a source, as this makes structure
From: Francisco Casas fcasas@codeweavers.com
At this point, the parse code is free of offsets; it only uses index paths.
Signed-off-by: Francisco Casas fcasas@codeweavers.com Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com ---
v4: * Renamed deref_copy() to copy_deref(). * Removed hlsl_src_from_node() noop in copy_deref(). --- libs/vkd3d-shader/hlsl.c | 31 ++++++++++++++++++++++++------- libs/vkd3d-shader/hlsl.h | 5 ++--- libs/vkd3d-shader/hlsl.y | 31 ++++--------------------------- libs/vkd3d-shader/hlsl_codegen.c | 3 +++ 4 files changed, 33 insertions(+), 37 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index b4e3525f..bf74131a 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -866,6 +866,26 @@ static bool type_is_single_reg(const struct hlsl_type *type) return type->type == HLSL_CLASS_SCALAR || type->type == HLSL_CLASS_VECTOR; }
+static bool copy_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_deref *other) +{ + unsigned int i; + + memset(deref, 0, sizeof(*deref)); + + if (!other) + return true; + + assert(!other->offset.node); + + if (!init_deref(ctx, deref, other->var, other->path_len)) + return false; + + for (i = 0; i < deref->path_len; ++i) + hlsl_src_from_node(&deref->path[i], other->path[i].node); + + return true; +} + void hlsl_cleanup_deref(struct hlsl_deref *deref) { unsigned int i; @@ -1135,9 +1155,8 @@ struct hlsl_ir_load *hlsl_new_load_component(struct hlsl_ctx *ctx, struct hlsl_b }
struct hlsl_ir_resource_load *hlsl_new_resource_load(struct hlsl_ctx *ctx, struct hlsl_type *data_type, - enum hlsl_resource_load_type type, struct hlsl_ir_var *resource, struct hlsl_ir_node *resource_offset, - struct hlsl_ir_var *sampler, struct hlsl_ir_node *sampler_offset, struct hlsl_ir_node *coords, - struct hlsl_ir_node *texel_offset, const struct vkd3d_shader_location *loc) + enum hlsl_resource_load_type type, struct hlsl_deref *resource, struct hlsl_deref *sampler, + struct hlsl_ir_node *coords, struct hlsl_ir_node *texel_offset, const struct vkd3d_shader_location *loc) { struct hlsl_ir_resource_load *load;
@@ -1145,10 +1164,8 @@ struct hlsl_ir_resource_load *hlsl_new_resource_load(struct hlsl_ctx *ctx, struc return NULL; init_node(&load->node, HLSL_IR_RESOURCE_LOAD, data_type, *loc); load->load_type = type; - load->resource.var = resource; - hlsl_src_from_node(&load->resource.offset, resource_offset); - load->sampler.var = sampler; - hlsl_src_from_node(&load->sampler.offset, sampler_offset); + copy_deref(ctx, &load->resource, resource); + copy_deref(ctx, &load->sampler, sampler); hlsl_src_from_node(&load->coords, coords); hlsl_src_from_node(&load->texel_offset, texel_offset); return load; diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 76721c8e..2af22c03 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -777,9 +777,8 @@ struct hlsl_ir_node *hlsl_new_offset_instr_from_deref(struct hlsl_ctx *ctx, stru const struct hlsl_deref *deref, const struct vkd3d_shader_location *loc);
struct hlsl_ir_resource_load *hlsl_new_resource_load(struct hlsl_ctx *ctx, struct hlsl_type *data_type, - enum hlsl_resource_load_type type, struct hlsl_ir_var *resource, struct hlsl_ir_node *resource_offset, - struct hlsl_ir_var *sampler, struct hlsl_ir_node *sampler_offset, struct hlsl_ir_node *coords, - struct hlsl_ir_node *texel_offset, const struct vkd3d_shader_location *loc); + enum hlsl_resource_load_type type, struct hlsl_deref *resource, struct hlsl_deref *sampler, + struct hlsl_ir_node *coords, struct hlsl_ir_node *texel_offset, const struct vkd3d_shader_location *loc);
struct hlsl_ir_load *hlsl_new_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, struct hlsl_ir_node *offset, struct hlsl_type *type, struct vkd3d_shader_location loc); diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index a5152800..7df7afb9 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -2402,10 +2402,8 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl && object_type->sampler_dim != HLSL_SAMPLER_DIM_CUBEARRAY) { const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); - struct hlsl_ir_node *object_load_offset; struct hlsl_ir_resource_load *load; struct hlsl_ir_node *coords; - struct hlsl_block block;
if (object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMS || object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMSARRAY) @@ -2430,11 +2428,8 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl hlsl_get_vector_type(ctx, HLSL_TYPE_INT, sampler_dim + 1), loc))) return false;
- object_load_offset = hlsl_new_offset_instr_from_deref(ctx, &block, &object_load->src, loc); - list_move_tail(instrs, &block.instrs); - if (!(load = hlsl_new_resource_load(ctx, object_type->e.resource_format, HLSL_RESOURCE_LOAD, - object_load->src.var, object_load_offset, NULL, NULL, coords, NULL, loc))) + &object_load->src, NULL, coords, NULL, loc))) return false; list_add_tail(instrs, &load->node.entry); return true; @@ -2444,13 +2439,11 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl && object_type->sampler_dim != HLSL_SAMPLER_DIM_2DMSARRAY) { const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); - struct hlsl_ir_node *object_load_offset, *sampler_load_offset; const struct hlsl_type *sampler_type; struct hlsl_ir_resource_load *load; struct hlsl_ir_node *offset = NULL; struct hlsl_ir_load *sampler_load; struct hlsl_ir_node *coords; - struct hlsl_block block;
if (params->args_count != 2 && params->args_count != 3) { @@ -2486,15 +2479,8 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl return false; }
- object_load_offset = hlsl_new_offset_instr_from_deref(ctx, &block, &object_load->src, loc); - list_move_tail(instrs, &block.instrs); - - sampler_load_offset = hlsl_new_offset_instr_from_deref(ctx, &block, &sampler_load->src, loc); - list_move_tail(instrs, &block.instrs); - if (!(load = hlsl_new_resource_load(ctx, object_type->e.resource_format, - HLSL_RESOURCE_SAMPLE, object_load->src.var, object_load_offset, - sampler_load->src.var, sampler_load_offset, coords, offset, loc))) + HLSL_RESOURCE_SAMPLE, &object_load->src, &sampler_load->src, coords, offset, loc))) return false; list_add_tail(instrs, &load->node.entry);
@@ -2508,7 +2494,6 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl || object_type->sampler_dim == HLSL_SAMPLER_DIM_CUBEARRAY)) { const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); - struct hlsl_ir_node *object_load_offset, *sampler_load_offset; enum hlsl_resource_load_type load_type; const struct hlsl_type *sampler_type; struct hlsl_ir_resource_load *load; @@ -2517,7 +2502,6 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl struct hlsl_type *result_type; struct hlsl_ir_node *coords; unsigned int read_channel; - struct hlsl_block block;
if (!strcmp(name, "GatherGreen")) { @@ -2599,15 +2583,8 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc))) return false;
- object_load_offset = hlsl_new_offset_instr_from_deref(ctx, &block, &object_load->src, loc); - list_move_tail(instrs, &block.instrs); - - sampler_load_offset = hlsl_new_offset_instr_from_deref(ctx, &block, &sampler_load->src, loc); - list_move_tail(instrs, &block.instrs); - - if (!(load = hlsl_new_resource_load(ctx, result_type, - load_type, object_load->src.var, object_load_offset, - sampler_load->src.var, sampler_load_offset, coords, offset, loc))) + if (!(load = hlsl_new_resource_load(ctx, result_type, load_type, &object_load->src, + &sampler_load->src, coords, offset, loc))) return false; list_add_tail(instrs, &load->node.entry); return true; diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 99f15a04..45012333 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -31,6 +31,9 @@ static void replace_deref_path_with_offset(struct hlsl_ctx *ctx, struct hlsl_der if (!deref->var) return;
+ /* register offsets shouldn't be used before this point is reached. */ + assert(!deref->offset.node); + if (!(offset = hlsl_new_offset_instr_from_deref(ctx, &block, deref, &instr->loc))) return; list_move_before(&instr->entry, &block.instrs);
From: Francisco Casas fcasas@codeweavers.com
This can be done now, to ensure that register offsets are no longer used in hlsl.c and hlsl.h.
Signed-off-by: Francisco Casas fcasas@codeweavers.com Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com ---
v4: * Replaced 'node' with 'instr' in function name. --- libs/vkd3d-shader/hlsl.c | 103 ------------------------------- libs/vkd3d-shader/hlsl.h | 6 -- libs/vkd3d-shader/hlsl_codegen.c | 103 ++++++++++++++++++++++++++++++- 3 files changed, 102 insertions(+), 110 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index bf74131a..4a469d40 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -456,109 +456,6 @@ struct hlsl_type *hlsl_get_inner_type_from_path_index(struct hlsl_ctx *ctx, cons } }
-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_idx = hlsl_ir_constant(idx)->value[0].u; - struct hlsl_struct_field *field = &type->e.record.fields[field_idx]; - - 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_ir_node *hlsl_new_offset_instr_from_deref(struct hlsl_ctx *ctx, struct hlsl_block *block, - const struct hlsl_deref *deref, const struct vkd3d_shader_location *loc) -{ - struct hlsl_ir_node *offset = NULL; - struct hlsl_type *type; - unsigned int i; - - list_init(&block->instrs); - - if (deref->offset.node) - return deref->offset.node; - - assert(deref->var); - - type = deref->var->data_type; - - for (i = 0; i < deref->path_len; ++i) - { - struct hlsl_block idx_block; - - if (!(offset = hlsl_new_offset_from_path_index(ctx, &idx_block, type, offset, deref->path[i].node, loc))) - return NULL; - - list_move_tail(&block->instrs, &idx_block.instrs); - - type = hlsl_get_inner_type_from_path_index(ctx, type, deref->path[i].node); - } - - return 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 2af22c03..0c684ae9 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -737,9 +737,6 @@ struct hlsl_ir_var *hlsl_get_var(struct hlsl_scope *scope, const char *name);
struct hlsl_type *hlsl_get_inner_type_from_path_index(struct hlsl_ctx *ctx, const struct hlsl_type *type, struct hlsl_ir_node *idx); -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, @@ -773,9 +770,6 @@ struct hlsl_ir_store *hlsl_new_store_index(struct hlsl_ctx *ctx, const struct hl struct hlsl_ir_store *hlsl_new_store_component(struct hlsl_ctx *ctx, struct hlsl_block *block, const struct hlsl_deref *lhs, unsigned int comp, struct hlsl_ir_node *rhs);
-struct hlsl_ir_node *hlsl_new_offset_instr_from_deref(struct hlsl_ctx *ctx, struct hlsl_block *block, - const struct hlsl_deref *deref, const struct vkd3d_shader_location *loc); - struct hlsl_ir_resource_load *hlsl_new_resource_load(struct hlsl_ctx *ctx, struct hlsl_type *data_type, enum hlsl_resource_load_type type, struct hlsl_deref *resource, struct hlsl_deref *sampler, struct hlsl_ir_node *coords, struct hlsl_ir_node *texel_offset, const struct vkd3d_shader_location *loc); diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 45012333..fdccd2c7 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -21,6 +21,107 @@ #include "hlsl.h" #include <stdio.h>
+/* TODO: remove when no longer needed, only used for new_offset_instr_from_deref() */ +static struct hlsl_ir_node *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_idx = hlsl_ir_constant(idx)->value[0].u; + struct hlsl_struct_field *field = &type->e.record.fields[field_idx]; + + 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; +} + +/* TODO: remove when no longer needed, only used for replace_deref_path_with_offset() */ +static struct hlsl_ir_node *new_offset_instr_from_deref(struct hlsl_ctx *ctx, struct hlsl_block *block, + const struct hlsl_deref *deref, const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_node *offset = NULL; + struct hlsl_type *type; + unsigned int i; + + list_init(&block->instrs); + + assert(deref->var); + type = deref->var->data_type; + + for (i = 0; i < deref->path_len; ++i) + { + struct hlsl_block idx_block; + + if (!(offset = new_offset_from_path_index(ctx, &idx_block, type, offset, deref->path[i].node, loc))) + return NULL; + + list_move_tail(&block->instrs, &idx_block.instrs); + + type = hlsl_get_inner_type_from_path_index(ctx, type, deref->path[i].node); + } + + return offset; +} + /* TODO: remove when no longer needed, only used for transform_deref_paths_into_offsets() */ static void replace_deref_path_with_offset(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_node *instr) @@ -34,7 +135,7 @@ static void replace_deref_path_with_offset(struct hlsl_ctx *ctx, struct hlsl_der /* register offsets shouldn't be used before this point is reached. */ assert(!deref->offset.node);
- if (!(offset = hlsl_new_offset_instr_from_deref(ctx, &block, deref, &instr->loc))) + if (!(offset = new_offset_instr_from_deref(ctx, &block, deref, &instr->loc))) return; list_move_before(&instr->entry, &block.instrs);
From: Francisco Casas fcasas@codeweavers.com
Signed-off-by: Francisco Casas fcasas@codeweavers.com Signed-off-by: Zebediah Figura zfigura@codeweavers.com Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com ---
v4: * No changes. --- libs/vkd3d-shader/hlsl_codegen.c | 81 +++++++++++++++----------------- 1 file changed, 37 insertions(+), 44 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index fdccd2c7..befd3694 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -204,11 +204,44 @@ static void prepend_uniform_copy(struct hlsl_ctx *ctx, struct list *instrs, stru list_add_after(&load->node.entry, &store->node.entry); }
+static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, + struct hlsl_type *type, unsigned int modifiers, const struct hlsl_semantic *semantic, bool output) +{ + struct hlsl_semantic new_semantic; + struct vkd3d_string_buffer *name; + struct hlsl_ir_var *ext_var; + + if (!(name = hlsl_get_string_buffer(ctx))) + return NULL; + vkd3d_string_buffer_printf(name, "<%s-%s%u>", output ? "output" : "input", semantic->name, semantic->index); + if (!(new_semantic.name = hlsl_strdup(ctx, semantic->name))) + { + hlsl_release_string_buffer(ctx, name); + return NULL; + } + new_semantic.index = semantic->index; + if (!(ext_var = hlsl_new_var(ctx, hlsl_strdup(ctx, name->buffer), + type, var->loc, &new_semantic, modifiers, NULL))) + { + hlsl_release_string_buffer(ctx, name); + vkd3d_free((void *)new_semantic.name); + return NULL; + } + hlsl_release_string_buffer(ctx, name); + if (output) + ext_var->is_output_semantic = 1; + else + ext_var->is_input_semantic = 1; + ext_var->is_param = var->is_param; + list_add_before(&var->scope_entry, &ext_var->scope_entry); + list_add_tail(&ctx->extern_vars, &ext_var->extern_entry); + + return ext_var; +} + static void prepend_input_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_var *var, struct hlsl_type *type, unsigned int field_offset, unsigned int modifiers, const struct hlsl_semantic *semantic) { - struct vkd3d_string_buffer *name; - struct hlsl_semantic new_semantic; struct hlsl_ir_constant *offset; struct hlsl_ir_store *store; struct hlsl_ir_load *load; @@ -229,27 +262,8 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct list *instrs, struct return; }
- if (!(name = hlsl_get_string_buffer(ctx))) + if (!(input = add_semantic_var(ctx, var, type, modifiers, semantic, false))) return; - vkd3d_string_buffer_printf(name, "<input-%s%u>", semantic->name, semantic->index); - if (!(new_semantic.name = hlsl_strdup(ctx, semantic->name))) - { - hlsl_release_string_buffer(ctx, name); - return; - } - new_semantic.index = semantic->index; - if (!(input = hlsl_new_var(ctx, hlsl_strdup(ctx, name->buffer), - type, var->loc, &new_semantic, modifiers, NULL))) - { - hlsl_release_string_buffer(ctx, name); - vkd3d_free((void *)new_semantic.name); - return; - } - hlsl_release_string_buffer(ctx, name); - input->is_input_semantic = 1; - input->is_param = var->is_param; - list_add_before(&var->scope_entry, &input->scope_entry); - list_add_tail(&ctx->extern_vars, &input->extern_entry);
if (!(load = hlsl_new_var_load(ctx, input, var->loc))) return; @@ -297,8 +311,6 @@ static void prepend_input_var_copy(struct hlsl_ctx *ctx, struct list *instrs, st static void append_output_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_var *var, struct hlsl_type *type, unsigned int field_offset, unsigned int modifiers, const struct hlsl_semantic *semantic) { - struct vkd3d_string_buffer *name; - struct hlsl_semantic new_semantic; struct hlsl_ir_constant *offset; struct hlsl_ir_store *store; struct hlsl_ir_var *output; @@ -319,27 +331,8 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct list *instrs, struct return; }
- if (!(name = hlsl_get_string_buffer(ctx))) + if (!(output = add_semantic_var(ctx, var, type, modifiers, semantic, true))) return; - vkd3d_string_buffer_printf(name, "<output-%s%u>", semantic->name, semantic->index); - if (!(new_semantic.name = hlsl_strdup(ctx, semantic->name))) - { - hlsl_release_string_buffer(ctx, name); - return; - } - new_semantic.index = semantic->index; - if (!(output = hlsl_new_var(ctx, hlsl_strdup(ctx, name->buffer), - type, var->loc, &new_semantic, modifiers, NULL))) - { - vkd3d_free((void *)new_semantic.name); - hlsl_release_string_buffer(ctx, name); - return; - } - hlsl_release_string_buffer(ctx, name); - output->is_output_semantic = 1; - output->is_param = var->is_param; - list_add_before(&var->scope_entry, &output->scope_entry); - list_add_tail(&ctx->extern_vars, &output->extern_entry);
if (!(offset = hlsl_new_uint_constant(ctx, field_offset, &var->loc))) return;
From: Francisco Casas fcasas@codeweavers.com
Signed-off-by: Francisco Casas fcasas@codeweavers.com Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com ---
The recursive structure of prepend_input_var_copy() and append_output_var_copy() could be preserved creating additional (redudant) loads to complete the paths. Otherwise we would be requiring passing whole paths as arguments.
These additional loads should be handled by DCE.
Still, matrix vectors are copied iteratively instead of recursively now, to avoid the boilerplate of creating new loads in this last step.
v4: * Removed "type" parameter in prepend_* and append_* functions since it can be obtained directly from the created loads. * Added comments for the redudant loads. --- libs/vkd3d-shader/hlsl_codegen.c | 196 +++++++++++++++++++------------ 1 file changed, 124 insertions(+), 72 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index befd3694..774ee824 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -239,59 +239,78 @@ static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir return ext_var; }
-static void prepend_input_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_var *var, - struct hlsl_type *type, unsigned int field_offset, unsigned int modifiers, const struct hlsl_semantic *semantic) +static void prepend_input_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_load *lhs, + unsigned int modifiers, const struct hlsl_semantic *semantic) { - struct hlsl_ir_constant *offset; - struct hlsl_ir_store *store; - struct hlsl_ir_load *load; - struct hlsl_ir_var *input; + struct hlsl_type *type = lhs->node.data_type, *vector_type; + struct hlsl_ir_var *var = lhs->src.var; + unsigned int i;
- if (type->type == HLSL_CLASS_MATRIX) + vector_type = hlsl_get_vector_type(ctx, type->base_type, hlsl_type_minor_size(type)); + + for (i = 0; i < hlsl_type_major_size(type); ++i) { - struct hlsl_type *vector_type = hlsl_get_vector_type(ctx, type->base_type, hlsl_type_minor_size(type)); - struct hlsl_semantic vector_semantic = *semantic; - unsigned int i; + struct hlsl_semantic semantic_copy = *semantic; + struct hlsl_ir_store *store; + struct hlsl_ir_constant *c; + struct hlsl_ir_var *input; + struct hlsl_ir_load *load;
- for (i = 0; i < hlsl_type_major_size(type); ++i) - { - prepend_input_copy(ctx, instrs, var, vector_type, 4 * i, modifiers, &vector_semantic); - ++vector_semantic.index; - } + semantic_copy.index = semantic->index + i;
- return; - } + if (!(input = add_semantic_var(ctx, var, vector_type, modifiers, &semantic_copy, false))) + return;
- if (!(input = add_semantic_var(ctx, var, type, modifiers, semantic, false))) - return; + if (!(load = hlsl_new_var_load(ctx, input, var->loc))) + return; + list_add_after(&lhs->node.entry, &load->node.entry);
- if (!(load = hlsl_new_var_load(ctx, input, var->loc))) - return; - list_add_head(instrs, &load->node.entry); + if (type->type == HLSL_CLASS_MATRIX) + { + if (!(c = hlsl_new_uint_constant(ctx, i, &var->loc))) + return; + list_add_after(&load->node.entry, &c->node.entry);
- if (!(offset = hlsl_new_uint_constant(ctx, field_offset, &var->loc))) - return; - list_add_after(&load->node.entry, &offset->node.entry); + if (!(store = hlsl_new_store_index(ctx, &lhs->src, &c->node, &load->node, 0, &var->loc))) + return; + list_add_after(&c->node.entry, &store->node.entry); + } + else + { + assert(i == 0);
- if (!(store = hlsl_new_store(ctx, var, &offset->node, &load->node, 0, var->loc))) - return; - list_add_after(&offset->node.entry, &store->node.entry); + if (!(store = hlsl_new_store_index(ctx, &lhs->src, NULL, &load->node, 0, &var->loc))) + return; + list_add_after(&load->node.entry, &store->node.entry); + } + } }
-static void prepend_input_struct_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_var *var, - struct hlsl_type *type, unsigned int field_offset) +static void prepend_input_struct_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_load *lhs) { + struct hlsl_type *type = lhs->node.data_type; + struct hlsl_ir_var *var = lhs->src.var; size_t i;
for (i = 0; i < type->e.record.field_count; ++i) { const struct hlsl_struct_field *field = &type->e.record.fields[i]; + struct hlsl_ir_load *field_load; + struct hlsl_ir_constant *c; + + if (!(c = hlsl_new_uint_constant(ctx, i, &var->loc))) + return; + list_add_after(&lhs->node.entry, &c->node.entry); + + /* This redudant load is expected to be deleted later by DCE */ + if (!(field_load = hlsl_new_load_index(ctx, &lhs->src, &c->node, &var->loc))) + return; + list_add_after(&c->node.entry, &field_load->node.entry);
if (field->type->type == HLSL_CLASS_STRUCT) - prepend_input_struct_copy(ctx, instrs, var, field->type, field_offset + field->reg_offset); + prepend_input_struct_copy(ctx, instrs, field_load); else if (field->semantic.name) - prepend_input_copy(ctx, instrs, var, field->type, - field_offset + field->reg_offset, field->modifiers, &field->semantic); + prepend_input_copy(ctx, instrs, field_load, field->modifiers, &field->semantic); else hlsl_error(ctx, &field->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_SEMANTIC, "Field '%s' is missing a semantic.", field->name); @@ -302,65 +321,91 @@ static void prepend_input_struct_copy(struct hlsl_ctx *ctx, struct list *instrs, * and copy the former to the latter, so that writes to input variables work. */ static void prepend_input_var_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_var *var) { + struct hlsl_ir_load *load; + + /* This redudant load is expected to be deleted later by DCE */ + if (!(load = hlsl_new_var_load(ctx, var, var->loc))) + return; + list_add_head(instrs, &load->node.entry); + if (var->data_type->type == HLSL_CLASS_STRUCT) - prepend_input_struct_copy(ctx, instrs, var, var->data_type, 0); + prepend_input_struct_copy(ctx, instrs, load); else if (var->semantic.name) - prepend_input_copy(ctx, instrs, var, var->data_type, 0, var->modifiers, &var->semantic); + prepend_input_copy(ctx, instrs, load, var->modifiers, &var->semantic); }
-static void append_output_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_var *var, - struct hlsl_type *type, unsigned int field_offset, unsigned int modifiers, const struct hlsl_semantic *semantic) +static void append_output_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_load *rhs, + unsigned int modifiers, const struct hlsl_semantic *semantic) { - struct hlsl_ir_constant *offset; - struct hlsl_ir_store *store; - struct hlsl_ir_var *output; - struct hlsl_ir_load *load; + struct hlsl_type *type = rhs->node.data_type, *vector_type; + struct hlsl_ir_var *var = rhs->src.var; + unsigned int i; + + vector_type = hlsl_get_vector_type(ctx, type->base_type, hlsl_type_minor_size(type));
- if (type->type == HLSL_CLASS_MATRIX) + for (i = 0; i < hlsl_type_major_size(type); ++i) { - struct hlsl_type *vector_type = hlsl_get_vector_type(ctx, type->base_type, hlsl_type_minor_size(type)); - struct hlsl_semantic vector_semantic = *semantic; - unsigned int i; + struct hlsl_semantic semantic_copy = *semantic; + struct hlsl_ir_store *store; + struct hlsl_ir_constant *c; + struct hlsl_ir_var *output; + struct hlsl_ir_load *load;
- for (i = 0; i < hlsl_type_major_size(type); ++i) - { - append_output_copy(ctx, instrs, var, vector_type, 4 * i, modifiers, &vector_semantic); - ++vector_semantic.index; - } + semantic_copy.index = semantic->index + i;
- return; - } + if (!(output = add_semantic_var(ctx, var, vector_type, modifiers, &semantic_copy, true))) + return;
- if (!(output = add_semantic_var(ctx, var, type, modifiers, semantic, true))) - return; + if (type->type == HLSL_CLASS_MATRIX) + { + if (!(c = hlsl_new_uint_constant(ctx, i, &var->loc))) + return; + list_add_tail(instrs, &c->node.entry);
- if (!(offset = hlsl_new_uint_constant(ctx, field_offset, &var->loc))) - return; - list_add_tail(instrs, &offset->node.entry); + if (!(load = hlsl_new_load_index(ctx, &rhs->src, &c->node, &var->loc))) + return; + list_add_tail(instrs, &load->node.entry); + } + else + { + assert(i == 0);
- if (!(load = hlsl_new_load(ctx, var, &offset->node, type, var->loc))) - return; - list_add_after(&offset->node.entry, &load->node.entry); + if (!(load = hlsl_new_load_index(ctx, &rhs->src, NULL, &var->loc))) + return; + list_add_tail(instrs, &load->node.entry); + }
- if (!(store = hlsl_new_store(ctx, output, NULL, &load->node, 0, var->loc))) - return; - list_add_after(&load->node.entry, &store->node.entry); + if (!(store = hlsl_new_simple_store(ctx, output, &load->node))) + return; + list_add_tail(instrs, &store->node.entry); + } }
-static void append_output_struct_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_var *var, - struct hlsl_type *type, unsigned int field_offset) +static void append_output_struct_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_load *rhs) { + struct hlsl_type *type = rhs->node.data_type; + struct hlsl_ir_var *var = rhs->src.var; size_t i;
for (i = 0; i < type->e.record.field_count; ++i) { const struct hlsl_struct_field *field = &type->e.record.fields[i]; + struct hlsl_ir_load *field_load; + struct hlsl_ir_constant *c; + + if (!(c = hlsl_new_uint_constant(ctx, i, &var->loc))) + return; + list_add_tail(instrs, &c->node.entry); + + /* This redudant load is expected to be deleted later by DCE */ + if (!(field_load = hlsl_new_load_index(ctx, &rhs->src, &c->node, &var->loc))) + return; + list_add_tail(instrs, &field_load->node.entry);
if (field->type->type == HLSL_CLASS_STRUCT) - append_output_struct_copy(ctx, instrs, var, field->type, field_offset + field->reg_offset); + append_output_struct_copy(ctx, instrs, field_load); else if (field->semantic.name) - append_output_copy(ctx, instrs, var, field->type, - field_offset + field->reg_offset, field->modifiers, &field->semantic); + append_output_copy(ctx, instrs, field_load, field->modifiers, &field->semantic); else hlsl_error(ctx, &field->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_SEMANTIC, "Field '%s' is missing a semantic.", field->name); @@ -372,10 +417,17 @@ static void append_output_struct_copy(struct hlsl_ctx *ctx, struct list *instrs, * variables work. */ static void append_output_var_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_var *var) { + struct hlsl_ir_load *load; + + /* This redudant load is expected to be deleted later by DCE */ + if (!(load = hlsl_new_var_load(ctx, var, var->loc))) + return; + list_add_tail(instrs, &load->node.entry); + if (var->data_type->type == HLSL_CLASS_STRUCT) - append_output_struct_copy(ctx, instrs, var, var->data_type, 0); + append_output_struct_copy(ctx, instrs, load); else if (var->semantic.name) - append_output_copy(ctx, instrs, var, var->data_type, 0, var->modifiers, &var->semantic); + append_output_copy(ctx, instrs, load, var->modifiers, &var->semantic); }
static bool transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx, struct hlsl_ir_node *, void *), @@ -2029,8 +2081,6 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry
list_move_head(&body->instrs, &ctx->static_initializers);
- transform_ir(ctx, transform_deref_paths_into_offsets, body, NULL); /* TODO: move forward, remove when no longer needed */ - LIST_FOR_EACH_ENTRY(var, &ctx->globals->vars, struct hlsl_ir_var, scope_entry) { if (var->modifiers & HLSL_STORAGE_UNIFORM) @@ -2064,6 +2114,8 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry append_output_var_copy(ctx, &body->instrs, entry_func->return_var); }
+ transform_ir(ctx, transform_deref_paths_into_offsets, body, NULL); /* TODO: move forward, remove when no longer needed */ + transform_ir(ctx, lower_broadcasts, body, NULL); while (transform_ir(ctx, fold_redundant_casts, body, NULL)); do
From: Francisco Casas fcasas@codeweavers.com
hlsl_new_store() and hlsl_new_load() are deleted, so now there are no more direct ways to create derefs with offsets in hlsl.c and hlsl.h.
Signed-off-by: Francisco Casas fcasas@codeweavers.com Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com ---
v4: * Renamed 'indx' to 'idx'. --- libs/vkd3d-shader/hlsl.c | 32 ------------------------- libs/vkd3d-shader/hlsl.h | 4 ---- libs/vkd3d-shader/hlsl_codegen.c | 40 +++++++++----------------------- 3 files changed, 11 insertions(+), 65 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 4a469d40..a47e3d2d 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -797,25 +797,6 @@ void hlsl_cleanup_deref(struct hlsl_deref *deref) hlsl_src_remove(&deref->offset); }
-struct hlsl_ir_store *hlsl_new_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, struct hlsl_ir_node *offset, - struct hlsl_ir_node *rhs, unsigned int writemask, struct vkd3d_shader_location loc) -{ - struct hlsl_ir_store *store; - - if (!writemask && type_is_single_reg(rhs->data_type)) - writemask = (1 << rhs->data_type->dimx) - 1; - - if (!(store = hlsl_alloc(ctx, sizeof(*store)))) - return NULL; - - init_node(&store->node, HLSL_IR_STORE, NULL, loc); - init_deref(ctx, &store->lhs, var, 0); - hlsl_src_from_node(&store->lhs.offset, offset); - hlsl_src_from_node(&store->rhs, rhs); - store->writemask = writemask; - return store; -} - /* Initializes a simple variable derefence, so that it can be passed to load/store functions. */ void hlsl_init_simple_deref_from_var(struct hlsl_deref *deref, struct hlsl_ir_var *var) { @@ -971,19 +952,6 @@ struct hlsl_ir_if *hlsl_new_if(struct hlsl_ctx *ctx, struct hlsl_ir_node *condit return iff; }
-struct hlsl_ir_load *hlsl_new_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, struct hlsl_ir_node *offset, - struct hlsl_type *type, const struct vkd3d_shader_location loc) -{ - struct hlsl_ir_load *load; - - if (!(load = hlsl_alloc(ctx, sizeof(*load)))) - return NULL; - init_node(&load->node, HLSL_IR_LOAD, type, loc); - init_deref(ctx, &load->src, var, 0); - hlsl_src_from_node(&load->src.offset, offset); - return load; -} - struct hlsl_ir_load *hlsl_new_load_index(struct hlsl_ctx *ctx, const struct hlsl_deref *deref, struct hlsl_ir_node *idx, const struct vkd3d_shader_location *loc) { diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 0c684ae9..7970665c 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -774,11 +774,7 @@ struct hlsl_ir_resource_load *hlsl_new_resource_load(struct hlsl_ctx *ctx, struc enum hlsl_resource_load_type type, struct hlsl_deref *resource, struct hlsl_deref *sampler, struct hlsl_ir_node *coords, struct hlsl_ir_node *texel_offset, const struct vkd3d_shader_location *loc);
-struct hlsl_ir_load *hlsl_new_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, struct hlsl_ir_node *offset, - struct hlsl_type *type, struct vkd3d_shader_location loc); struct hlsl_ir_loop *hlsl_new_loop(struct hlsl_ctx *ctx, struct vkd3d_shader_location loc); -struct hlsl_ir_store *hlsl_new_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, struct hlsl_ir_node *offset, - struct hlsl_ir_node *rhs, unsigned int writemask, struct vkd3d_shader_location loc); struct hlsl_type *hlsl_new_struct_type(struct hlsl_ctx *ctx, const char *name, struct hlsl_struct_field *fields, size_t field_count); struct hlsl_ir_swizzle *hlsl_new_swizzle(struct hlsl_ctx *ctx, DWORD s, unsigned int components, diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 774ee824..36a417e5 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -958,39 +958,21 @@ static bool fold_redundant_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst * split_matrix_copies(). Inserts new instructions right before * "store". */ static bool split_copy(struct hlsl_ctx *ctx, struct hlsl_ir_store *store, - const struct hlsl_ir_load *load, const unsigned int offset, struct hlsl_type *type) + const struct hlsl_ir_load *load, const unsigned int idx, struct hlsl_type *type) { - struct hlsl_ir_node *offset_instr, *add; struct hlsl_ir_store *split_store; struct hlsl_ir_load *split_load; struct hlsl_ir_constant *c;
- if (!(c = hlsl_new_uint_constant(ctx, offset, &store->node.loc))) + if (!(c = hlsl_new_uint_constant(ctx, idx, &store->node.loc))) return false; list_add_before(&store->node.entry, &c->node.entry);
- offset_instr = &c->node; - if (load->src.offset.node) - { - if (!(add = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, load->src.offset.node, &c->node))) - return false; - list_add_before(&store->node.entry, &add->entry); - offset_instr = add; - } - if (!(split_load = hlsl_new_load(ctx, load->src.var, offset_instr, type, store->node.loc))) + if (!(split_load = hlsl_new_load_index(ctx, &load->src, &c->node, &store->node.loc))) return false; list_add_before(&store->node.entry, &split_load->node.entry);
- offset_instr = &c->node; - if (store->lhs.offset.node) - { - if (!(add = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, store->lhs.offset.node, &c->node))) - return false; - list_add_before(&store->node.entry, &add->entry); - offset_instr = add; - } - - if (!(split_store = hlsl_new_store(ctx, store->lhs.var, offset_instr, &split_load->node, 0, store->node.loc))) + if (!(split_store = hlsl_new_store_index(ctx, &store->lhs, &c->node, &split_load->node, 0, &store->node.loc))) return false; list_add_before(&store->node.entry, &split_store->node.entry);
@@ -1002,8 +984,8 @@ static bool split_array_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, const struct hlsl_ir_node *rhs; struct hlsl_type *element_type; const struct hlsl_type *type; - unsigned int element_size, i; struct hlsl_ir_store *store; + unsigned int i;
if (instr->type != HLSL_IR_STORE) return false; @@ -1014,7 +996,6 @@ static bool split_array_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, if (type->type != HLSL_CLASS_ARRAY) return false; element_type = type->e.array.type; - element_size = hlsl_type_get_array_element_reg_size(element_type);
if (rhs->type != HLSL_IR_LOAD) { @@ -1024,7 +1005,7 @@ static bool split_array_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr,
for (i = 0; i < type->e.array.elements_count; ++i) { - if (!split_copy(ctx, store, hlsl_ir_load(rhs), i * element_size, element_type)) + if (!split_copy(ctx, store, hlsl_ir_load(rhs), i, element_type)) return false; }
@@ -1062,7 +1043,7 @@ static bool split_struct_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr { const struct hlsl_struct_field *field = &type->e.record.fields[i];
- if (!split_copy(ctx, store, hlsl_ir_load(rhs), field->reg_offset, field->type)) + if (!split_copy(ctx, store, hlsl_ir_load(rhs), i, field->type)) return false; }
@@ -1100,7 +1081,7 @@ static bool split_matrix_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr
for (i = 0; i < hlsl_type_major_size(type); ++i) { - if (!split_copy(ctx, store, hlsl_ir_load(rhs), 4 * i, element_type)) + if (!split_copy(ctx, store, hlsl_ir_load(rhs), i, element_type)) return false; }
@@ -2114,8 +2095,6 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry append_output_var_copy(ctx, &body->instrs, entry_func->return_var); }
- transform_ir(ctx, transform_deref_paths_into_offsets, body, NULL); /* TODO: move forward, remove when no longer needed */ - transform_ir(ctx, lower_broadcasts, body, NULL); while (transform_ir(ctx, fold_redundant_casts, body, NULL)); do @@ -2125,6 +2104,9 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry } while (progress); transform_ir(ctx, split_matrix_copies, body, NULL); + + transform_ir(ctx, transform_deref_paths_into_offsets, body, NULL); /* TODO: move forward, remove when no longer needed */ + transform_ir(ctx, lower_narrowing_casts, body, NULL); transform_ir(ctx, lower_casts_to_bool, body, NULL); do
I can't approve this, for unclear reasons. Maybe I'm missing some sort of perms? There's no indication in the web UI why I can't approve, and using the `lab` command line tool claims success but doesn't actually do anything.