The transform_deref_paths_into_offsets pass turns these index paths back into register offsets, they should not be used anywhere before that.
Signed-off-by: Francisco Casas fcasas@codeweavers.com
---
The idea is that we can move this 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 were placed nearby in hlsl.h
hlsl_new_resource_load() was modified to receive deref arguments instead of var+offset pairs.
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_get_direct_var_deref() can be used to create a deref value that can be passed by reference in the first 2 cases. This value shall not be modified after being created.
Signed-off-by: Francisco Casas fcasas@codeweavers.com --- libs/vkd3d-shader/hlsl.c | 371 +++++++++++++++++++++++++++---- libs/vkd3d-shader/hlsl.h | 35 ++- libs/vkd3d-shader/hlsl.y | 147 +++++------- libs/vkd3d-shader/hlsl_codegen.c | 71 ++++++ 4 files changed, 469 insertions(+), 155 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 17ccd305..c7416054 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -249,39 +249,51 @@ 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) +/* Returns the path of a given component within a type, given its index. + * *comp_type will be set to the type of the component. + * *path_len will be set to the lenght of the path. + * Memory should be free afterwards. + */ +unsigned int *hlsl_compute_component_path(struct hlsl_ctx *ctx, struct hlsl_type *type, + unsigned int idx, struct hlsl_type **comp_type, unsigned int *path_len) { + unsigned int *path; + switch (type->type) { case HLSL_CLASS_SCALAR: + case HLSL_CLASS_OBJECT: + { + assert(idx == 0); + *comp_type = type; + *path_len = 0; + path = hlsl_alloc(ctx, 0 * sizeof(unsigned int)); + return path; + } case HLSL_CLASS_VECTOR: { assert(idx < type->dimx * type->dimy); *comp_type = hlsl_get_scalar_type(ctx, type->base_type); - return idx; + *path_len = 1; + if (!(path = hlsl_alloc(ctx, 1 * sizeof(unsigned int)))) + return NULL; + path[0] = idx; + return path; } case HLSL_CLASS_MATRIX: { - unsigned int minor, major, x = idx % type->dimx, y = idx / type->dimx; + unsigned int y = idx / type->dimx, x = idx % type->dimx; + bool row_major = hlsl_type_is_row_major(type);
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; + *path_len = 2; + if (!(path = hlsl_alloc(ctx, 2 * sizeof(unsigned int)))) + return NULL; + path[0] = row_major? y : x; + path[1] = row_major? x : y; + return path; }
case HLSL_CLASS_ARRAY: @@ -289,45 +301,64 @@ unsigned int hlsl_compute_component_offset(struct hlsl_ctx *ctx, struct hlsl_typ 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; + unsigned int elem_path_len; + unsigned int *elem_path;
- assert(array_idx < type->e.array.elements_count); + elem_path = hlsl_compute_component_path(ctx, type->e.array.type, idx_in_elem, comp_type, &elem_path_len); + if (elem_path_len && !elem_path) + return NULL;
- 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); + *path_len = elem_path_len + 1; + if (!(path = hlsl_alloc(ctx, (*path_len) * sizeof(unsigned int)))) + { + vkd3d_free(elem_path); + return NULL; + } + memcpy(path + 1, elem_path, elem_path_len * sizeof(unsigned int)); + vkd3d_free(elem_path); + path[0] = array_idx; + return path; }
case HLSL_CLASS_STRUCT: { struct hlsl_struct_field *field; - unsigned int elem_comp_count, i; + unsigned int field_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); + field_comp_count = hlsl_type_component_count(field->type);
- if (idx < elem_comp_count) + if (idx < field_comp_count) { - return field->reg_offset + - hlsl_compute_component_offset(ctx, field->type, idx, comp_type); + unsigned int field_path_len; + unsigned int *field_path; + + field_path = hlsl_compute_component_path(ctx, field->type, idx, comp_type, &field_path_len); + if (field_path_len && !field_path) + return NULL; + + *path_len = field_path_len + 1; + if (!(path = hlsl_alloc(ctx, (*path_len) * sizeof(unsigned int)))) + { + vkd3d_free(field_path); + return NULL; + } + memcpy(path + 1, field_path, field_path_len * sizeof(unsigned int)); + vkd3d_free(field_path); + path[0] = i; + return path; } - idx -= elem_comp_count; + idx -= field_comp_count; } - assert(0); - return 0; - } - - case HLSL_CLASS_OBJECT: - { - assert(idx == 0); - *comp_type = type; - return 0; + return NULL; } }
assert(0); - return 0; + return NULL; }
struct hlsl_type *hlsl_get_type_from_path_index(struct hlsl_ctx *ctx, const struct hlsl_type *type, @@ -733,6 +764,62 @@ static bool type_is_single_reg(const struct hlsl_type *type) return type->type == HLSL_CLASS_SCALAR || type->type == HLSL_CLASS_VECTOR; }
+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 bool deref_copy(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_deref *other) +{ + unsigned int i; + + if (!other) + { + deref->var = NULL; + deref->path = NULL; + deref->path_len = 0; + return true; + } + + 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); + + hlsl_src_from_node(&deref->offset, other->offset.node); + + return true; +} + +static struct hlsl_type *get_type_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref) +{ + struct hlsl_type *type = deref->var->data_type; + unsigned int i; + + for (i = 0; i < deref->path_len; ++i) + type = hlsl_get_type_from_path_index(ctx, type, deref->path[i].node); + return type; +} + 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) { @@ -745,16 +832,113 @@ 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; }
+/* Returns a simple variable derefence, so that the value can be stored and then passed by reference + * to load/store functions. It shall not be modified afterwards. */ +struct hlsl_deref hlsl_get_direct_var_deref(struct hlsl_ir_var *var) +{ + struct hlsl_deref deref = {}; + + deref.var = var; + return deref; +} + 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_get_direct_var_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, struct vkd3d_shader_location loc) +{ + struct hlsl_ir_store *store; + unsigned int i; + + assert(lhs); + + 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[i], 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, + const struct hlsl_deref *lhs, unsigned int comp, struct hlsl_ir_node *rhs) +{ + struct hlsl_type *type, *comp_type; + unsigned int *path, path_len, i; + struct hlsl_ir_store *store; + struct hlsl_ir_constant *c; + + list_init(&block->instrs); + + if (!(store = hlsl_alloc(ctx, sizeof(*store)))) + return NULL; + init_node(&store->node, HLSL_IR_STORE, NULL, rhs->loc); + + type = get_type_from_deref(ctx, lhs); + path = hlsl_compute_component_path(ctx, type, comp, &comp_type, &path_len); + if (path_len && !path) + { + vkd3d_free(store); + return NULL; + } + + if (!init_deref(ctx, &store->lhs, lhs->var, lhs->path_len + path_len)) + { + vkd3d_free(path); + vkd3d_free(store); + return NULL; + } + + for (i = 0; i < lhs->path_len; ++i) + hlsl_src_from_node(&store->lhs.path[i], lhs->path[i].node); + for (i = 0; i < path_len; ++i) + { + if (!(c = hlsl_new_uint_constant(ctx, path[i], &rhs->loc))) + { + vkd3d_free(path); + hlsl_free_instr_list(&block->instrs); + hlsl_free_deref(&store->lhs); + vkd3d_free(store); + return NULL; + } + list_add_tail(&block->instrs, &c->node.entry); + + hlsl_src_from_node(&store->lhs.path[lhs->path_len + i], &c->node); + } + vkd3d_free(path); + + 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, @@ -848,21 +1032,103 @@ 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, struct vkd3d_shader_location loc) +{ + struct hlsl_ir_load *load; + struct hlsl_type *type; + unsigned int i; + + type = get_type_from_deref(ctx, deref); + if (idx) + type = hlsl_get_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[i], 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) { - return hlsl_new_load(ctx, var, NULL, var->data_type, loc); + struct hlsl_deref var_deref = hlsl_get_direct_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, struct vkd3d_shader_location loc) +{ + struct hlsl_type *type, *comp_type; + unsigned int *path, path_len, i; + struct hlsl_ir_constant *c; + struct hlsl_ir_load *load; + + list_init(&block->instrs); + + type = get_type_from_deref(ctx, deref); + path = hlsl_compute_component_path(ctx, type, comp, &comp_type, &path_len); + if (path_len && !path) + return NULL; + + if (!(load = hlsl_alloc(ctx, sizeof(*load)))) + { + vkd3d_free(path); + return NULL; + } + init_node(&load->node, HLSL_IR_LOAD, comp_type, loc); + + + if (!init_deref(ctx, &load->src, deref->var, deref->path_len + path_len)) + { + vkd3d_free(path); + 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); + for (i = 0; i < path_len; ++i) + { + if (!(c = hlsl_new_uint_constant(ctx, path[i], &loc))) + { + vkd3d_free(path); + hlsl_free_instr_list(&block->instrs); + hlsl_free_deref(&load->src); + vkd3d_free(load); + return NULL; + } + list_add_tail(&block->instrs, &c->node.entry); + + hlsl_src_from_node(&load->src.path[deref->path_len + i], &c->node); + } + vkd3d_free(path); + + 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, - 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;
@@ -870,10 +1136,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); + deref_copy(ctx, &load->resource, resource); + deref_copy(ctx, &load->sampler, sampler); hlsl_src_from_node(&load->coords, coords); hlsl_src_from_node(&load->texel_offset, texel_offset); return load; @@ -1664,6 +1928,15 @@ void hlsl_free_instr_list(struct list *list)
void hlsl_free_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); }
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index fbadd9c6..d3885540 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; };
@@ -753,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_deref hlsl_get_direct_var_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, 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, 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, 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); + +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); + 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_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_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, @@ -777,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); @@ -798,8 +815,8 @@ 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_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); +unsigned int *hlsl_compute_component_path(struct hlsl_ctx *ctx, struct hlsl_type *type, + unsigned int idx, struct hlsl_type **comp_type, unsigned int *path_len); 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 63904580..ed45d54f 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; + var_deref = hlsl_get_direct_var_deref(var);
for (dst_idx = 0; dst_idx < dst_type->dimx * dst_type->dimy; ++dst_idx) { + unsigned int src_idx, *dst_path, dst_path_len; 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;
if (broadcast) { @@ -334,7 +336,10 @@ 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_path = hlsl_compute_component_path(ctx, dst_type, dst_idx, &dst_scalar_type, &dst_path_len); + if (dst_path_len && !dst_path) + return NULL; + vkd3d_free(dst_path);
if (!(load = add_load_component(ctx, instrs, node, src_idx, *loc))) return NULL; @@ -343,16 +348,12 @@ 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))) + if (!(store = hlsl_new_store_component(ctx, &block, &var_deref, dst_idx, &cast->node))) return NULL; - list_add_tail(instrs, &c->node.entry); - - if (!(store = hlsl_new_store(ctx, var, &c->node, &cast->node, 0, *loc))) - return NULL; - list_add_tail(instrs, &store->node.entry); + list_move_tail(instrs, &block.instrs); }
- 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,22 +626,13 @@ 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_node, struct hlsl_ir_node *idx, const struct vkd3d_shader_location loc) { - struct hlsl_type *elem_type; - struct hlsl_ir_node *offset; struct hlsl_ir_load *load; - struct hlsl_block block; - - elem_type = hlsl_get_type_from_path_index(ctx, var_node->data_type, idx);
if (var_node->type == HLSL_IR_LOAD) { const struct hlsl_deref *src = &hlsl_ir_load(var_node)->src;
- if (!(offset = hlsl_new_offset_from_path_index(ctx, &block, var_node->data_type, src->offset.node, idx, &loc))) - return NULL; - list_move_tail(instrs, &block.instrs); - - if (!(load = hlsl_new_load(ctx, src->var, offset, elem_type, loc))) + if (!(load = hlsl_new_load_index(ctx, src, idx, loc))) return NULL; list_add_tail(instrs, &load->node.entry); } @@ -650,10 +642,6 @@ static struct hlsl_ir_load *add_load_index(struct hlsl_ctx *ctx, struct list *in struct hlsl_ir_var *var; char name[27];
- if (!(offset = hlsl_new_offset_from_path_index(ctx, &block, var_node->data_type, NULL, idx, &loc))) - return NULL; - list_move_tail(instrs, &block.instrs); - sprintf(name, "<deref-%p>", var_node); if (!(var = hlsl_new_synthetic_var(ctx, name, var_node->data_type, var_node->loc))) return NULL; @@ -662,7 +650,7 @@ static struct hlsl_ir_load *add_load_index(struct hlsl_ctx *ctx, struct list *in return NULL; list_add_tail(instrs, &store->node.entry);
- if (!(load = hlsl_new_load(ctx, var, offset, elem_type, loc))) + if (!(load = hlsl_new_load_index(ctx, &store->lhs, idx, loc))) return NULL; list_add_tail(instrs, &load->node.entry); } @@ -673,38 +661,16 @@ 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_node, 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_node->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_node->type == HLSL_IR_LOAD) { const struct hlsl_deref *src = &hlsl_ir_load(var_node)->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; - }
- 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); } else { @@ -720,9 +686,9 @@ static struct hlsl_ir_load *add_load_component(struct hlsl_ctx *ctx, struct list return NULL; list_add_tail(instrs, &store->node.entry);
- if (!(load = hlsl_new_load(ctx, var, offset, comp_type, loc))) + if (!(load = hlsl_new_load_component(ctx, &block, &store->lhs, comp, loc))) return NULL; - list_add_tail(instrs, &load->node.entry); + list_move_tail(instrs, &block.instrs); }
return load; @@ -752,6 +718,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; @@ -767,12 +734,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; + var_deref = hlsl_get_direct_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; @@ -784,9 +753,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))) @@ -1234,6 +1203,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;
@@ -1245,6 +1215,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; + var_deref = hlsl_get_direct_var_deref(var);
for (i = 0; i < hlsl_type_major_size(type); i++) { @@ -1272,16 +1243,12 @@ 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); }
- 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);
@@ -1664,15 +1631,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) @@ -1686,13 +1649,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); @@ -1703,16 +1664,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; } }
- 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->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 @@ -1761,32 +1718,32 @@ 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 = hlsl_get_direct_var_deref(dst); unsigned int k;
for (k = 0; k < src_comp_count; ++k) { + unsigned int dst_path_len, *dst_path; 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); - - if (!(conv = add_implicit_conversion(ctx, instrs, &load->node, dst_comp_type, &src->loc))) + dst_path = hlsl_compute_component_path(ctx, dst->data_type, *store_index, &dst_comp_type, &dst_path_len); + if (dst_path_len && !dst_path) return; + vkd3d_free(dst_path);
- if (!(c = hlsl_new_uint_constant(ctx, dst_reg_offset, &src->loc))) + if (!(conv = add_implicit_conversion(ctx, instrs, &load->node, dst_comp_type, &src->loc))) return; - list_add_tail(instrs, &c->node.entry);
- if (!(store = hlsl_new_store(ctx, dst, &c->node, conv, 0, src->loc))) + if (!(store = hlsl_new_store_component(ctx, &block, &dst_deref, *store_index, conv))) return; - list_add_tail(instrs, &store->node.entry); + list_move_tail(instrs, &block.instrs);
++*store_index; } @@ -2151,6 +2108,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;
@@ -2197,15 +2155,15 @@ static bool intrinsic_mul(struct hlsl_ctx *ctx, vkd3d_string_buffer_release(&ctx->string_buffers, name); if (!var) return false; + var_deref = hlsl_get_direct_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_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) { @@ -2232,17 +2190,13 @@ static bool intrinsic_mul(struct hlsl_ctx *ctx, } }
- offset = hlsl_compute_component_offset(ctx, matrix_type, j * matrix_type->dimx + i, &scalar_type); - if (!(c = hlsl_new_uint_constant(ctx, offset, loc))) - return false; - list_add_tail(params->instrs, &c->node.entry); - - if (!(store = hlsl_new_store(ctx, var, &c->node, node, 0, *loc))) + if (!(store = hlsl_new_store_component(ctx, &block, &var_deref, j * matrix_type->dimx + i, node))) return false; - list_add_tail(params->instrs, &store->node.entry); + list_move_tail(params->instrs, &block.instrs); } + }
- 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);
@@ -2478,7 +2432,7 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl return false;
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, NULL, coords, NULL, loc))) return false; list_add_tail(instrs, &load->node.entry); return true; @@ -2529,10 +2483,10 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl }
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, &sampler_load->src, 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") @@ -2633,8 +2587,7 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl return false;
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, &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 373439af..513e599e 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -21,6 +21,75 @@ #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_type *type; + unsigned int i; + + if (!deref->var) + return; + + type = deref->var->data_type; + + /* register offsets shouldn't be used before this point is reached. */ + assert(!deref->offset.node); + + offset = NULL; + + for (i = 0; i < deref->path_len; ++i) + { + struct hlsl_ir_node *block_instr, *block_next; + struct hlsl_block block; + + if (!(offset = hlsl_new_offset_from_path_index(ctx, &block, type, offset, deref->path[i].node, &instr->loc))) + return; + + LIST_FOR_EACH_ENTRY_SAFE(block_instr, block_next, &block.instrs, struct hlsl_ir_node, entry) + { + list_remove(&block_instr->entry); + list_add_before(&instr->entry, &block_instr->entry); + } + + type = hlsl_get_type_from_path_index(ctx, type, deref->path[i].node); + } + + hlsl_free_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 +1959,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)
Hi,
a first round on this one. Given that it's pretty large, I think I'll need some more thinking next week.
Il 01/07/22 23:24, Francisco Casas ha scritto:
The transform_deref_paths_into_offsets pass turns these index paths back into register offsets, they should not be used anywhere before that.
Signed-off-by: Francisco Casas fcasas@codeweavers.com
The idea is that we can move this 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 were placed nearby in hlsl.h
hlsl_new_resource_load() was modified to receive deref arguments instead of var+offset pairs.
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_get_direct_var_deref() can be used to create a deref value that can be passed by reference in the first 2 cases. This value shall not be modified after being created.
Signed-off-by: Francisco Casas fcasas@codeweavers.com
libs/vkd3d-shader/hlsl.c | 371 +++++++++++++++++++++++++++---- libs/vkd3d-shader/hlsl.h | 35 ++- libs/vkd3d-shader/hlsl.y | 147 +++++------- libs/vkd3d-shader/hlsl_codegen.c | 71 ++++++ 4 files changed, 469 insertions(+), 155 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 17ccd305..c7416054 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -249,39 +249,51 @@ 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)
+/* Returns the path of a given component within a type, given its index.
- *comp_type will be set to the type of the component.
- *path_len will be set to the lenght of the path.
- Memory should be free afterwards.
- */
+unsigned int *hlsl_compute_component_path(struct hlsl_ctx *ctx, struct hlsl_type *type,
{unsigned int idx, struct hlsl_type **comp_type, unsigned int *path_len)
- unsigned int *path;
switch (type->type) {
Notice that here and elsewhere you don't need to put braces around a case block, unless you want to declare variables in it. I am not sure of what is suggested when some case blocks declare variables and others don't.
On the other hand, I think we tend to leave a blank line between case blocks.
case HLSL_CLASS_SCALAR:
case HLSL_CLASS_OBJECT:
{
assert(idx == 0);
*comp_type = type;
*path_len = 0;
path = hlsl_alloc(ctx, 0 * sizeof(unsigned int));
return path;
Hmm, this means that this function can return NULL even if it succeeds. You're clearly aware of that because when checking for failure you look at both the returned pointer and the path length, but it seems to me an unidiomatic form. Maybe it's better to allocate one byte here and stipulate that the function returns NULL if and only if it fails?
} case HLSL_CLASS_VECTOR: { assert(idx < type->dimx * type->dimy);
Isn't dimy always 1 for vectors?
*comp_type = hlsl_get_scalar_type(ctx, type->base_type);
return idx;
*path_len = 1;
if (!(path = hlsl_alloc(ctx, 1 * sizeof(unsigned int))))
return NULL;
path[0] = idx;
return path; } case HLSL_CLASS_MATRIX: {
unsigned int minor, major, x = idx % type->dimx, y = idx / type->dimx;
unsigned int y = idx / type->dimx, x = idx % type->dimx;
bool row_major = hlsl_type_is_row_major(type); 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;
*path_len = 2;
if (!(path = hlsl_alloc(ctx, 2 * sizeof(unsigned int))))
return NULL;
path[0] = row_major? y : x;
path[1] = row_major? x : y;
return path; } case HLSL_CLASS_ARRAY:
@@ -289,45 +301,64 @@ unsigned int hlsl_compute_component_offset(struct hlsl_ctx *ctx, struct hlsl_typ 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;
unsigned int elem_path_len;
unsigned int *elem_path;
assert(array_idx < type->e.array.elements_count);
Didn't this assertion make sense? Given that equivalent ones are present in the other branches, I'd leave it.
elem_path = hlsl_compute_component_path(ctx, type->e.array.type, idx_in_elem, comp_type, &elem_path_len);
if (elem_path_len && !elem_path)
return NULL;
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);
*path_len = elem_path_len + 1;
if (!(path = hlsl_alloc(ctx, (*path_len) * sizeof(unsigned int))))
{
vkd3d_free(elem_path);
return NULL;
}
memcpy(path + 1, elem_path, elem_path_len * sizeof(unsigned int));
vkd3d_free(elem_path);
path[0] = array_idx;
return path; } case HLSL_CLASS_STRUCT: { struct hlsl_struct_field *field;
unsigned int elem_comp_count, i;
unsigned int field_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);
field_comp_count = hlsl_type_component_count(field->type);
if (idx < elem_comp_count)
if (idx < field_comp_count) {
return field->reg_offset +
hlsl_compute_component_offset(ctx, field->type, idx, comp_type);
unsigned int field_path_len;
unsigned int *field_path;
field_path = hlsl_compute_component_path(ctx, field->type, idx, comp_type, &field_path_len);
if (field_path_len && !field_path)
return NULL;
*path_len = field_path_len + 1;
if (!(path = hlsl_alloc(ctx, (*path_len) * sizeof(unsigned int))))
{
vkd3d_free(field_path);
return NULL;
}
memcpy(path + 1, field_path, field_path_len * sizeof(unsigned int));
vkd3d_free(field_path);
path[0] = i;
return path; }
idx -= elem_comp_count;
idx -= field_comp_count; }
assert(0);
return 0;
}
case HLSL_CLASS_OBJECT:
{
assert(idx == 0);
*comp_type = type;
return 0;
return NULL; } } assert(0);
- return 0;
return NULL; }
struct hlsl_type *hlsl_get_type_from_path_index(struct hlsl_ctx *ctx, const struct hlsl_type *type,
@@ -733,6 +764,62 @@ static bool type_is_single_reg(const struct hlsl_type *type) return type->type == HLSL_CLASS_SCALAR || type->type == HLSL_CLASS_VECTOR; }
+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 bool deref_copy(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_deref *other) +{
- unsigned int i;
- if (!other)
- {
deref->var = NULL;
deref->path = NULL;
deref->path_len = 0;
I guess you're forgetting "offset" here? BTW, with a memset you can initialize everything in one line.
return true;
- }
- 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);
- hlsl_src_from_node(&deref->offset, other->offset.node);
- return true;
+}
+static struct hlsl_type *get_type_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref) +{
- struct hlsl_type *type = deref->var->data_type;
- unsigned int i;
- for (i = 0; i < deref->path_len; ++i)
type = hlsl_get_type_from_path_index(ctx, type, deref->path[i].node);
- return type;
+}
- 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) {
@@ -745,16 +832,113 @@ 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; }
+/* Returns a simple variable derefence, so that the value can be stored and then passed by reference
- to load/store functions. It shall not be modified afterwards. */
+struct hlsl_deref hlsl_get_direct_var_deref(struct hlsl_ir_var *var) +{
- struct hlsl_deref deref = {};
- deref.var = var;
- return deref;
+}
- 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_get_direct_var_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, struct vkd3d_shader_location loc)
+{
- struct hlsl_ir_store *store;
- unsigned int i;
- assert(lhs);
- 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[i], idx);
Using "i" here makes the code more obscure than it should be. Could you please use "lhs->path_len" instead?
- 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,
const struct hlsl_deref *lhs, unsigned int comp, struct hlsl_ir_node *rhs)
+{
struct hlsl_type *type, *comp_type;
unsigned int *path, path_len, i;
struct hlsl_ir_store *store;
struct hlsl_ir_constant *c;
list_init(&block->instrs);
if (!(store = hlsl_alloc(ctx, sizeof(*store))))
return NULL;
init_node(&store->node, HLSL_IR_STORE, NULL, rhs->loc);
type = get_type_from_deref(ctx, lhs);
path = hlsl_compute_component_path(ctx, type, comp, &comp_type, &path_len);
if (path_len && !path)
{
vkd3d_free(store);
return NULL;
}
if (!init_deref(ctx, &store->lhs, lhs->var, lhs->path_len + path_len))
{
vkd3d_free(path);
vkd3d_free(store);
return NULL;
}
for (i = 0; i < lhs->path_len; ++i)
hlsl_src_from_node(&store->lhs.path[i], lhs->path[i].node);
for (i = 0; i < path_len; ++i)
{
if (!(c = hlsl_new_uint_constant(ctx, path[i], &rhs->loc)))
{
vkd3d_free(path);
hlsl_free_instr_list(&block->instrs);
hlsl_free_deref(&store->lhs);
vkd3d_free(store);
return NULL;
}
list_add_tail(&block->instrs, &c->node.entry);
hlsl_src_from_node(&store->lhs.path[lhs->path_len + i], &c->node);
}
vkd3d_free(path);
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,
@@ -848,21 +1032,103 @@ 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, struct vkd3d_shader_location loc)
+{
- struct hlsl_ir_load *load;
- struct hlsl_type *type;
- unsigned int i;
- type = get_type_from_deref(ctx, deref);
- if (idx)
type = hlsl_get_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[i], idx);
Same as above.
- 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)
- return hlsl_new_load(ctx, var, NULL, var->data_type, loc);
- struct hlsl_deref var_deref = hlsl_get_direct_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, struct vkd3d_shader_location loc)
+{
- struct hlsl_type *type, *comp_type;
- unsigned int *path, path_len, i;
- struct hlsl_ir_constant *c;
- struct hlsl_ir_load *load;
- list_init(&block->instrs);
- type = get_type_from_deref(ctx, deref);
- path = hlsl_compute_component_path(ctx, type, comp, &comp_type, &path_len);
- if (path_len && !path)
return NULL;
- if (!(load = hlsl_alloc(ctx, sizeof(*load))))
- {
vkd3d_free(path);
return NULL;
- }
- init_node(&load->node, HLSL_IR_LOAD, comp_type, loc);
There are two blank lines here, I belive that's a mistake?
if (!init_deref(ctx, &load->src, deref->var, deref->path_len + path_len))
{
vkd3d_free(path);
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);
for (i = 0; i < path_len; ++i)
{
if (!(c = hlsl_new_uint_constant(ctx, path[i], &loc)))
{
vkd3d_free(path);
hlsl_free_instr_list(&block->instrs);
hlsl_free_deref(&load->src);
vkd3d_free(load);
return NULL;
}
list_add_tail(&block->instrs, &c->node.entry);
hlsl_src_from_node(&load->src.path[deref->path_len + i], &c->node);
}
vkd3d_free(path);
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,
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_resource_load *load;struct hlsl_ir_node *coords, struct hlsl_ir_node *texel_offset, const struct vkd3d_shader_location *loc)
@@ -870,10 +1136,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);
- deref_copy(ctx, &load->resource, resource);
- deref_copy(ctx, &load->sampler, sampler); hlsl_src_from_node(&load->coords, coords); hlsl_src_from_node(&load->texel_offset, texel_offset); return load;
@@ -1664,6 +1928,15 @@ void hlsl_free_instr_list(struct list *list)
void hlsl_free_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);
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index fbadd9c6..d3885540 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;
@@ -753,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_deref hlsl_get_direct_var_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, 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, 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, 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);
+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);
- 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_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_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, @@ -777,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);
@@ -798,8 +815,8 @@ 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_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);
+unsigned int *hlsl_compute_component_path(struct hlsl_ctx *ctx, struct hlsl_type *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 idx, struct hlsl_type **comp_type, unsigned int *path_len);
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 63904580..ed45d54f 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;
var_deref = hlsl_get_direct_var_deref(var); for (dst_idx = 0; dst_idx < dst_type->dimx * dst_type->dimy; ++dst_idx) {
unsigned int src_idx, *dst_path, dst_path_len; 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; if (broadcast) {
@@ -334,7 +336,10 @@ 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_path = hlsl_compute_component_path(ctx, dst_type, dst_idx, &dst_scalar_type, &dst_path_len);
if (dst_path_len && !dst_path)
return NULL;
vkd3d_free(dst_path); if (!(load = add_load_component(ctx, instrs, node, src_idx, *loc))) return NULL;
@@ -343,16 +348,12 @@ 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)))
if (!(store = hlsl_new_store_component(ctx, &block, &var_deref, dst_idx, &cast->node))) return NULL;
list_add_tail(instrs, &c->node.entry);
if (!(store = hlsl_new_store(ctx, var, &c->node, &cast->node, 0, *loc)))
return NULL;
list_add_tail(instrs, &store->node.entry);
list_move_tail(instrs, &block.instrs);
It's not wrong, and maybe it could even be accepted as it is, but here you're basically computing the path, then dropping it, then computing it again.
}
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,22 +626,13 @@ 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_node, struct hlsl_ir_node *idx, const struct vkd3d_shader_location loc) {
struct hlsl_type *elem_type;
struct hlsl_ir_node *offset; struct hlsl_ir_load *load;
struct hlsl_block block;
elem_type = hlsl_get_type_from_path_index(ctx, var_node->data_type, idx);
if (var_node->type == HLSL_IR_LOAD) { const struct hlsl_deref *src = &hlsl_ir_load(var_node)->src;
if (!(offset = hlsl_new_offset_from_path_index(ctx, &block, var_node->data_type, src->offset.node, idx, &loc)))
return NULL;
list_move_tail(instrs, &block.instrs);
if (!(load = hlsl_new_load(ctx, src->var, offset, elem_type, loc)))
if (!(load = hlsl_new_load_index(ctx, src, idx, loc))) return NULL; list_add_tail(instrs, &load->node.entry); }
@@ -650,10 +642,6 @@ static struct hlsl_ir_load *add_load_index(struct hlsl_ctx *ctx, struct list *in struct hlsl_ir_var *var; char name[27];
if (!(offset = hlsl_new_offset_from_path_index(ctx, &block, var_node->data_type, NULL, idx, &loc)))
return NULL;
list_move_tail(instrs, &block.instrs);
sprintf(name, "<deref-%p>", var_node); if (!(var = hlsl_new_synthetic_var(ctx, name, var_node->data_type, var_node->loc))) return NULL;
@@ -662,7 +650,7 @@ static struct hlsl_ir_load *add_load_index(struct hlsl_ctx *ctx, struct list *in return NULL; list_add_tail(instrs, &store->node.entry);
if (!(load = hlsl_new_load(ctx, var, offset, elem_type, loc)))
if (!(load = hlsl_new_load_index(ctx, &store->lhs, idx, loc))) return NULL; list_add_tail(instrs, &load->node.entry); }
@@ -673,38 +661,16 @@ 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_node, 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_node->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_node->type == HLSL_IR_LOAD) { const struct hlsl_deref *src = &hlsl_ir_load(var_node)->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;
}
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); } else {
@@ -720,9 +686,9 @@ static struct hlsl_ir_load *add_load_component(struct hlsl_ctx *ctx, struct list return NULL; list_add_tail(instrs, &store->node.entry);
if (!(load = hlsl_new_load(ctx, var, offset, comp_type, loc)))
if (!(load = hlsl_new_load_component(ctx, &block, &store->lhs, comp, loc))) return NULL;
list_add_tail(instrs, &load->node.entry);
list_move_tail(instrs, &block.instrs); } return load;
@@ -752,6 +718,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;
@@ -767,12 +734,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;
var_deref = hlsl_get_direct_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;
@@ -784,9 +753,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)))
@@ -1234,6 +1203,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;
@@ -1245,6 +1215,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;
var_deref = hlsl_get_direct_var_deref(var); for (i = 0; i < hlsl_type_major_size(type); i++) {
@@ -1272,16 +1243,12 @@ 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); }
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);
@@ -1664,15 +1631,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)
@@ -1686,13 +1649,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);
@@ -1703,16 +1664,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; } }
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->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
@@ -1761,32 +1718,32 @@ 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 = hlsl_get_direct_var_deref(dst); unsigned int k;
for (k = 0; k < src_comp_count; ++k) {
unsigned int dst_path_len, *dst_path; 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);
if (!(conv = add_implicit_conversion(ctx, instrs, &load->node, dst_comp_type, &src->loc)))
dst_path = hlsl_compute_component_path(ctx, dst->data_type, *store_index, &dst_comp_type, &dst_path_len);
if (dst_path_len && !dst_path) return;
vkd3d_free(dst_path);
if (!(c = hlsl_new_uint_constant(ctx, dst_reg_offset, &src->loc)))
if (!(conv = add_implicit_conversion(ctx, instrs, &load->node, dst_comp_type, &src->loc))) return;
list_add_tail(instrs, &c->node.entry);
if (!(store = hlsl_new_store(ctx, dst, &c->node, conv, 0, src->loc)))
if (!(store = hlsl_new_store_component(ctx, &block, &dst_deref, *store_index, conv))) return;
list_add_tail(instrs, &store->node.entry);
list_move_tail(instrs, &block.instrs);
Same as above. Though on second thought it might really be the case that it's the best alternative, at least for the moment.
++*store_index; }
@@ -2151,6 +2108,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;
@@ -2197,15 +2155,15 @@ static bool intrinsic_mul(struct hlsl_ctx *ctx, vkd3d_string_buffer_release(&ctx->string_buffers, name); if (!var) return false;
var_deref = hlsl_get_direct_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_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) {
@@ -2232,17 +2190,13 @@ static bool intrinsic_mul(struct hlsl_ctx *ctx, } }
offset = hlsl_compute_component_offset(ctx, matrix_type, j * matrix_type->dimx + i, &scalar_type);
if (!(c = hlsl_new_uint_constant(ctx, offset, loc)))
return false;
list_add_tail(params->instrs, &c->node.entry);
if (!(store = hlsl_new_store(ctx, var, &c->node, node, 0, *loc)))
if (!(store = hlsl_new_store_component(ctx, &block, &var_deref, j * matrix_type->dimx + i, node))) return false;
list_add_tail(params->instrs, &store->node.entry);
list_move_tail(params->instrs, &block.instrs); }
- }
- 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);
@@ -2478,7 +2432,7 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl return false;
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, NULL, coords, NULL, loc))) return false; list_add_tail(instrs, &load->node.entry); return true;
@@ -2529,10 +2483,10 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl }
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, &sampler_load->src, 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")
@@ -2633,8 +2587,7 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl return false;
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, &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 373439af..513e599e 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -21,6 +21,75 @@ #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_type *type;
- unsigned int i;
- if (!deref->var)
return;
- type = deref->var->data_type;
- /* register offsets shouldn't be used before this point is reached. */
- assert(!deref->offset.node);
- offset = NULL;
- for (i = 0; i < deref->path_len; ++i)
- {
struct hlsl_ir_node *block_instr, *block_next;
struct hlsl_block block;
if (!(offset = hlsl_new_offset_from_path_index(ctx, &block, type, offset, deref->path[i].node, &instr->loc)))
return;
LIST_FOR_EACH_ENTRY_SAFE(block_instr, block_next, &block.instrs, struct hlsl_ir_node, entry)
{
list_remove(&block_instr->entry);
list_add_before(&instr->entry, &block_instr->entry);
}
Unless I am mistaken, list_move_tail() should do the same thing (but faster).
type = hlsl_get_type_from_path_index(ctx, type, deref->path[i].node);
- }
- hlsl_free_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 +1959,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)
Thanks, Giovanni.
On 08-07-22 11:43, Giovanni Mascellani wrote:
Hi,
a first round on this one. Given that it's pretty large, I think I'll need some more thinking next week.
Il 01/07/22 23:24, Francisco Casas ha scritto:
The transform_deref_paths_into_offsets pass turns these index paths back into register offsets, they should not be used anywhere before that.
Signed-off-by: Francisco Casas fcasas@codeweavers.com
The idea is that we can move this 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 were placed nearby in hlsl.h
hlsl_new_resource_load() was modified to receive deref arguments instead of var+offset pairs.
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_get_direct_var_deref() can be used to create a deref value that can be passed by reference in the first 2 cases. This value shall not be modified after being created.
Signed-off-by: Francisco Casas fcasas@codeweavers.com
libs/vkd3d-shader/hlsl.c | 371 +++++++++++++++++++++++++++---- libs/vkd3d-shader/hlsl.h | 35 ++- libs/vkd3d-shader/hlsl.y | 147 +++++------- libs/vkd3d-shader/hlsl_codegen.c | 71 ++++++ 4 files changed, 469 insertions(+), 155 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 17ccd305..c7416054 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -249,39 +249,51 @@ 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) +/* Returns the path of a given component within a type, given its index.
- *comp_type will be set to the type of the component.
- *path_len will be set to the lenght of the path.
- Memory should be free afterwards.
- */
+unsigned int *hlsl_compute_component_path(struct hlsl_ctx *ctx, struct hlsl_type *type, + unsigned int idx, struct hlsl_type **comp_type, unsigned int *path_len) { + unsigned int *path;
switch (type->type) {
Notice that here and elsewhere you don't need to put braces around a case block, unless you want to declare variables in it. I am not sure of what is suggested when some case blocks declare variables and others don't.
On the other hand, I think we tend to leave a blank line between case blocks.
I see. I will modify the switch blocks in the next version then. (And try to remember these rules!).
case HLSL_CLASS_SCALAR: + case HLSL_CLASS_OBJECT: + { + assert(idx == 0); + *comp_type = type; + *path_len = 0; + path = hlsl_alloc(ctx, 0 * sizeof(unsigned int)); + return path;
Hmm, this means that this function can return NULL even if it succeeds. You're clearly aware of that because when checking for failure you look at both the returned pointer and the path length, but it seems to me an unidiomatic form. Maybe it's better to allocate one byte here and stipulate that the function returns NULL if and only if it fails?
That's a good idea; I will change it for the next version too.
+ } case HLSL_CLASS_VECTOR: { assert(idx < type->dimx * type->dimy);
Isn't dimy always 1 for vectors?
Yes. Well, this may also cover if we ever assing type->dimy = 0 by mistake. I am not sure what's better; seems superfluous.
*comp_type = hlsl_get_scalar_type(ctx, type->base_type); - return idx; + *path_len = 1; + if (!(path = hlsl_alloc(ctx, 1 * sizeof(unsigned int)))) + return NULL; + path[0] = idx; + return path; } case HLSL_CLASS_MATRIX: { - unsigned int minor, major, x = idx % type->dimx, y = idx / type->dimx; + unsigned int y = idx / type->dimx, x = idx % type->dimx; + bool row_major = hlsl_type_is_row_major(type); 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; + *path_len = 2; + if (!(path = hlsl_alloc(ctx, 2 * sizeof(unsigned int)))) + return NULL; + path[0] = row_major? y : x; + path[1] = row_major? x : y; + return path; } case HLSL_CLASS_ARRAY: @@ -289,45 +301,64 @@ unsigned int hlsl_compute_component_offset(struct hlsl_ctx *ctx, struct hlsl_typ 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; + unsigned int elem_path_len; + unsigned int *elem_path; - assert(array_idx < type->e.array.elements_count);
Didn't this assertion make sense? Given that equivalent ones are present in the other branches, I'd leave it.
Okay, I don't know why I deleted it.
+ elem_path = hlsl_compute_component_path(ctx, type->e.array.type, idx_in_elem, comp_type, &elem_path_len); + if (elem_path_len && !elem_path) + return NULL; - 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); + *path_len = elem_path_len + 1; + if (!(path = hlsl_alloc(ctx, (*path_len) * sizeof(unsigned int)))) + { + vkd3d_free(elem_path); + return NULL; + } + memcpy(path + 1, elem_path, elem_path_len * sizeof(unsigned int)); + vkd3d_free(elem_path); + path[0] = array_idx; + return path; } case HLSL_CLASS_STRUCT: { struct hlsl_struct_field *field; - unsigned int elem_comp_count, i; + unsigned int field_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); + field_comp_count = hlsl_type_component_count(field->type); - if (idx < elem_comp_count) + if (idx < field_comp_count) { - return field->reg_offset + - hlsl_compute_component_offset(ctx, field->type, idx, comp_type); + unsigned int field_path_len; + unsigned int *field_path;
+ field_path = hlsl_compute_component_path(ctx, field->type, idx, comp_type, &field_path_len); + if (field_path_len && !field_path) + return NULL;
+ *path_len = field_path_len + 1; + if (!(path = hlsl_alloc(ctx, (*path_len) * sizeof(unsigned int)))) + { + vkd3d_free(field_path); + return NULL; + } + memcpy(path + 1, field_path, field_path_len * sizeof(unsigned int)); + vkd3d_free(field_path); + path[0] = i; + return path; } - idx -= elem_comp_count; + idx -= field_comp_count; }
assert(0); - return 0; - }
- case HLSL_CLASS_OBJECT: - { - assert(idx == 0); - *comp_type = type; - return 0; + return NULL; } } assert(0); - return 0; + return NULL; } struct hlsl_type *hlsl_get_type_from_path_index(struct hlsl_ctx *ctx, const struct hlsl_type *type, @@ -733,6 +764,62 @@ static bool type_is_single_reg(const struct hlsl_type *type) return type->type == HLSL_CLASS_SCALAR || type->type == HLSL_CLASS_VECTOR; } +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 bool deref_copy(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_deref *other) +{ + unsigned int i;
+ if (!other) + { + deref->var = NULL; + deref->path = NULL; + deref->path_len = 0;
I guess you're forgetting "offset" here? BTW, with a memset you can initialize everything in one line.
Well, deref_copy() isn't intended to copy dereferences that use offsets instead of index paths. Maybe I should add an
assert(!other->offset);
+ return true; + }
+ 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);
+ hlsl_src_from_node(&deref->offset, other->offset.node);
+ return true; +}
+static struct hlsl_type *get_type_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref) +{ + struct hlsl_type *type = deref->var->data_type; + unsigned int i;
+ for (i = 0; i < deref->path_len; ++i) + type = hlsl_get_type_from_path_index(ctx, type, deref->path[i].node); + return type; +}
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) { @@ -745,16 +832,113 @@ 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; } +/* Returns a simple variable derefence, so that the value can be stored and then passed by reference
- to load/store functions. It shall not be modified afterwards. */
+struct hlsl_deref hlsl_get_direct_var_deref(struct hlsl_ir_var *var) +{ + struct hlsl_deref deref = {};
+ deref.var = var; + return deref; +}
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_get_direct_var_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, struct vkd3d_shader_location loc) +{ + struct hlsl_ir_store *store; + unsigned int i;
+ assert(lhs);
+ 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[i], idx);
Using "i" here makes the code more obscure than it should be. Could you please use "lhs->path_len" instead?
Roger.
+ 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, + const struct hlsl_deref *lhs, unsigned int comp, struct hlsl_ir_node *rhs) +{ + struct hlsl_type *type, *comp_type; + unsigned int *path, path_len, i; + struct hlsl_ir_store *store; + struct hlsl_ir_constant *c;
+ list_init(&block->instrs);
+ if (!(store = hlsl_alloc(ctx, sizeof(*store)))) + return NULL; + init_node(&store->node, HLSL_IR_STORE, NULL, rhs->loc);
+ type = get_type_from_deref(ctx, lhs); + path = hlsl_compute_component_path(ctx, type, comp, &comp_type, &path_len); + if (path_len && !path) + { + vkd3d_free(store); + return NULL; + }
+ if (!init_deref(ctx, &store->lhs, lhs->var, lhs->path_len + path_len)) + { + vkd3d_free(path); + vkd3d_free(store); + return NULL; + }
+ for (i = 0; i < lhs->path_len; ++i) + hlsl_src_from_node(&store->lhs.path[i], lhs->path[i].node); + for (i = 0; i < path_len; ++i) + { + if (!(c = hlsl_new_uint_constant(ctx, path[i], &rhs->loc))) + { + vkd3d_free(path); + hlsl_free_instr_list(&block->instrs); + hlsl_free_deref(&store->lhs); + vkd3d_free(store); + return NULL; + } + list_add_tail(&block->instrs, &c->node.entry);
+ hlsl_src_from_node(&store->lhs.path[lhs->path_len + i], &c->node); + } + vkd3d_free(path);
+ 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, @@ -848,21 +1032,103 @@ 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, struct vkd3d_shader_location loc) +{ + struct hlsl_ir_load *load; + struct hlsl_type *type; + unsigned int i;
+ type = get_type_from_deref(ctx, deref); + if (idx) + type = hlsl_get_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[i], idx);
Same as above.
Roger, roger.
+ 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) { - return hlsl_new_load(ctx, var, NULL, var->data_type, loc); + struct hlsl_deref var_deref = hlsl_get_direct_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, struct vkd3d_shader_location loc) +{ + struct hlsl_type *type, *comp_type; + unsigned int *path, path_len, i; + struct hlsl_ir_constant *c; + struct hlsl_ir_load *load;
+ list_init(&block->instrs);
+ type = get_type_from_deref(ctx, deref); + path = hlsl_compute_component_path(ctx, type, comp, &comp_type, &path_len); + if (path_len && !path) + return NULL;
+ if (!(load = hlsl_alloc(ctx, sizeof(*load)))) + { + vkd3d_free(path); + return NULL; + } + init_node(&load->node, HLSL_IR_LOAD, comp_type, loc);
There are two blank lines here, I belive that's a mistake?
Ah, yes!
+ if (!init_deref(ctx, &load->src, deref->var, deref->path_len + path_len)) + { + vkd3d_free(path); + 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); + for (i = 0; i < path_len; ++i) + { + if (!(c = hlsl_new_uint_constant(ctx, path[i], &loc))) + { + vkd3d_free(path); + hlsl_free_instr_list(&block->instrs); + hlsl_free_deref(&load->src); + vkd3d_free(load); + return NULL; + } + list_add_tail(&block->instrs, &c->node.entry);
+ hlsl_src_from_node(&load->src.path[deref->path_len + i], &c->node); + } + vkd3d_free(path);
+ 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, - 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; @@ -870,10 +1136,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); + deref_copy(ctx, &load->resource, resource); + deref_copy(ctx, &load->sampler, sampler); hlsl_src_from_node(&load->coords, coords); hlsl_src_from_node(&load->texel_offset, texel_offset); return load; @@ -1664,6 +1928,15 @@ void hlsl_free_instr_list(struct list *list) void hlsl_free_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); } diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index fbadd9c6..d3885540 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; }; @@ -753,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_deref hlsl_get_direct_var_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, 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, 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, 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);
+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);
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_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_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, @@ -777,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); @@ -798,8 +815,8 @@ 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_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); +unsigned int *hlsl_compute_component_path(struct hlsl_ctx *ctx, struct hlsl_type *type, + unsigned int idx, struct hlsl_type **comp_type, unsigned int *path_len); 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 63904580..ed45d54f 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; + var_deref = hlsl_get_direct_var_deref(var); for (dst_idx = 0; dst_idx < dst_type->dimx * dst_type->dimy; ++dst_idx) { + unsigned int src_idx, *dst_path, dst_path_len; 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; if (broadcast) { @@ -334,7 +336,10 @@ 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_path = hlsl_compute_component_path(ctx, dst_type, dst_idx, &dst_scalar_type, &dst_path_len); + if (dst_path_len && !dst_path) + return NULL; + vkd3d_free(dst_path); if (!(load = add_load_component(ctx, instrs, node, src_idx, *loc))) return NULL; @@ -343,16 +348,12 @@ 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))) + if (!(store = hlsl_new_store_component(ctx, &block, &var_deref, dst_idx, &cast->node))) return NULL; - list_add_tail(instrs, &c->node.entry);
- if (!(store = hlsl_new_store(ctx, var, &c->node, &cast->node, 0, *loc))) - return NULL; - list_add_tail(instrs, &store->node.entry); + list_move_tail(instrs, &block.instrs);
It's not wrong, and maybe it could even be accepted as it is, but here you're basically computing the path, then dropping it, then computing it again.
Well, I needed to do
dst_path = hlsl_compute_component_path(ctx, dst_type, dst_idx, &dst_scalar_type, &dst_path_len);
just to obtain the dst_scalar_type, to create the cast node which is passed to the store.
I could add a function just to get the type from the component but it would have a somewhat redudant implementation. Another idea may be having functions to initialize a store/load from a path, but I don't think that adding different ways of doing the same thing is good.
Also, I don't think that the overhead of this approach is significative, so I would keep this implementation. For now at least.
} - 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,22 +626,13 @@ 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_node, struct hlsl_ir_node *idx, const struct vkd3d_shader_location loc) { - struct hlsl_type *elem_type; - struct hlsl_ir_node *offset; struct hlsl_ir_load *load; - struct hlsl_block block;
- elem_type = hlsl_get_type_from_path_index(ctx, var_node->data_type, idx); if (var_node->type == HLSL_IR_LOAD) { const struct hlsl_deref *src = &hlsl_ir_load(var_node)->src; - if (!(offset = hlsl_new_offset_from_path_index(ctx, &block, var_node->data_type, src->offset.node, idx, &loc))) - return NULL; - list_move_tail(instrs, &block.instrs);
- if (!(load = hlsl_new_load(ctx, src->var, offset, elem_type, loc))) + if (!(load = hlsl_new_load_index(ctx, src, idx, loc))) return NULL; list_add_tail(instrs, &load->node.entry); } @@ -650,10 +642,6 @@ static struct hlsl_ir_load *add_load_index(struct hlsl_ctx *ctx, struct list *in struct hlsl_ir_var *var; char name[27]; - if (!(offset = hlsl_new_offset_from_path_index(ctx, &block, var_node->data_type, NULL, idx, &loc))) - return NULL; - list_move_tail(instrs, &block.instrs);
sprintf(name, "<deref-%p>", var_node); if (!(var = hlsl_new_synthetic_var(ctx, name, var_node->data_type, var_node->loc))) return NULL; @@ -662,7 +650,7 @@ static struct hlsl_ir_load *add_load_index(struct hlsl_ctx *ctx, struct list *in return NULL; list_add_tail(instrs, &store->node.entry); - if (!(load = hlsl_new_load(ctx, var, offset, elem_type, loc))) + if (!(load = hlsl_new_load_index(ctx, &store->lhs, idx, loc))) return NULL; list_add_tail(instrs, &load->node.entry); } @@ -673,38 +661,16 @@ 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_node, 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_node->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_node->type == HLSL_IR_LOAD) { const struct hlsl_deref *src = &hlsl_ir_load(var_node)->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; - } - 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); } else { @@ -720,9 +686,9 @@ static struct hlsl_ir_load *add_load_component(struct hlsl_ctx *ctx, struct list return NULL; list_add_tail(instrs, &store->node.entry); - if (!(load = hlsl_new_load(ctx, var, offset, comp_type, loc))) + if (!(load = hlsl_new_load_component(ctx, &block, &store->lhs, comp, loc))) return NULL; - list_add_tail(instrs, &load->node.entry); + list_move_tail(instrs, &block.instrs); } return load; @@ -752,6 +718,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; @@ -767,12 +734,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; + var_deref = hlsl_get_direct_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; @@ -784,9 +753,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))) @@ -1234,6 +1203,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; @@ -1245,6 +1215,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; + var_deref = hlsl_get_direct_var_deref(var); for (i = 0; i < hlsl_type_major_size(type); i++) { @@ -1272,16 +1243,12 @@ 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); } - 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); @@ -1664,15 +1631,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) @@ -1686,13 +1649,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); @@ -1703,16 +1664,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; } } - 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->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 @@ -1761,32 +1718,32 @@ 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 = hlsl_get_direct_var_deref(dst); unsigned int k; for (k = 0; k < src_comp_count; ++k) { + unsigned int dst_path_len, *dst_path; 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);
- if (!(conv = add_implicit_conversion(ctx, instrs, &load->node, dst_comp_type, &src->loc))) + dst_path = hlsl_compute_component_path(ctx, dst->data_type, *store_index, &dst_comp_type, &dst_path_len); + if (dst_path_len && !dst_path) return; + vkd3d_free(dst_path); - if (!(c = hlsl_new_uint_constant(ctx, dst_reg_offset, &src->loc))) + if (!(conv = add_implicit_conversion(ctx, instrs, &load->node, dst_comp_type, &src->loc))) return; - list_add_tail(instrs, &c->node.entry); - if (!(store = hlsl_new_store(ctx, dst, &c->node, conv, 0, src->loc))) + if (!(store = hlsl_new_store_component(ctx, &block, &dst_deref, *store_index, conv))) return; - list_add_tail(instrs, &store->node.entry); + list_move_tail(instrs, &block.instrs);
Same as above. Though on second thought it might really be the case that it's the best alternative, at least for the moment.
++*store_index;
} @@ -2151,6 +2108,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; @@ -2197,15 +2155,15 @@ static bool intrinsic_mul(struct hlsl_ctx *ctx, vkd3d_string_buffer_release(&ctx->string_buffers, name); if (!var) return false; + var_deref = hlsl_get_direct_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_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) { @@ -2232,17 +2190,13 @@ static bool intrinsic_mul(struct hlsl_ctx *ctx, } } - offset = hlsl_compute_component_offset(ctx, matrix_type, j * matrix_type->dimx + i, &scalar_type); - if (!(c = hlsl_new_uint_constant(ctx, offset, loc))) - return false; - list_add_tail(params->instrs, &c->node.entry);
- if (!(store = hlsl_new_store(ctx, var, &c->node, node, 0, *loc))) + if (!(store = hlsl_new_store_component(ctx, &block, &var_deref, j * matrix_type->dimx + i, node))) return false; - list_add_tail(params->instrs, &store->node.entry); + list_move_tail(params->instrs, &block.instrs); } + } - 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); @@ -2478,7 +2432,7 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl return false; 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, NULL, coords, NULL, loc))) return false; list_add_tail(instrs, &load->node.entry); return true; @@ -2529,10 +2483,10 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl } 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, &sampler_load->src, 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") @@ -2633,8 +2587,7 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl return false; 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, &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 373439af..513e599e 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -21,6 +21,75 @@ #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_type *type; + unsigned int i;
+ if (!deref->var) + return;
+ type = deref->var->data_type;
+ /* register offsets shouldn't be used before this point is reached. */ + assert(!deref->offset.node);
+ offset = NULL;
+ for (i = 0; i < deref->path_len; ++i) + { + struct hlsl_ir_node *block_instr, *block_next; + struct hlsl_block block;
+ if (!(offset = hlsl_new_offset_from_path_index(ctx, &block, type, offset, deref->path[i].node, &instr->loc))) + return;
+ LIST_FOR_EACH_ENTRY_SAFE(block_instr, block_next, &block.instrs, struct hlsl_ir_node, entry) + { + list_remove(&block_instr->entry); + list_add_before(&instr->entry, &block_instr->entry); + }
Unless I am mistaken, list_move_tail() should do the same thing (but faster).
Good point, as we agreed upon, I will add Zeb's
b810928d zfigura include: Add list_move_after() and list_move_before().
before this one so that we use list_add_before() instead.
+ type = hlsl_get_type_from_path_index(ctx, type, deref->path[i].node); + }
+ hlsl_free_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 +1959,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)
Thanks, Giovanni.
On 7/1/22 16:24, Francisco Casas wrote:
+/* Returns the path of a given component within a type, given its index.
- *comp_type will be set to the type of the component.
- *path_len will be set to the lenght of the path.
- Memory should be free afterwards.
- */
+unsigned int *hlsl_compute_component_path(struct hlsl_ctx *ctx, struct hlsl_type *type,
unsigned int idx, struct hlsl_type **comp_type, unsigned int *path_len)
This is awkward partly because zero is a valid length. Ideally it should return bool. More than that, though, it's filling fields of struct hlsl_deref, so what about something like
static bool hlsl_deref_from_component_index(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_var *var, unsigned int index)
This obviously doesn't lend itself nicely to recursion. I ended up playing around with this for a bit and came up with the following abbreviated code:
unsigned int subtype_index_from_component_index(struct hlsl_ctx *ctx, inout const struct hlsl_type **type, inout unsigned int *index) { assert(index < hlsl_type_component_count(type));
... }
static bool hlsl_deref_from_component_index(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_var *var, uint index) { const struct hlsl_type *type = var->data_type; unsigned int *indices; size_t index_count;
while (/* type is not 1x1 numeric */) { indices[index_count++] = subtype_index_from_component(ctx, &type, &index); }
init_deref(ctx, deref, var, index_count); // and so on }
Thoughts?
+/* Returns a simple variable derefence, so that the value can be stored and then passed by reference
- to load/store functions. It shall not be modified afterwards. */
+struct hlsl_deref hlsl_get_direct_var_deref(struct hlsl_ir_var *var) +{
- struct hlsl_deref deref = {};
- deref.var = var;
- return deref;
+}
Naming: for consistency with hlsl_new_simple_store() I'd replace "direct" with "simple". (Also naming: perhaps hlsl_simple_deref_from_var instead, i.e. follow the "X from Y" pattern given what the function is doing).
I'm also inclined to say this should take the hlsl_deref as a pointer in the first argument, rather than returning a struct.
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)
Separate patch?
@@ -870,10 +1136,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);
- deref_copy(ctx, &load->resource, resource);
- deref_copy(ctx, &load->sampler, sampler);
Actually that means deref_copy() could be pulled out of this patch, right? Just to save another hunk :-)
@@ -334,7 +336,10 @@ 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_path = hlsl_compute_component_path(ctx, dst_type, dst_idx, &dst_scalar_type, &dst_path_len);
if (dst_path_len && !dst_path)
return NULL;
vkd3d_free(dst_path);
As far as I can tell we're just doing this so that we can get the right destination type to cast into. In that case my inclination is to move that cast into hlsl_new_store_component() itself. Same in initialize_var_components().
if (!(load = add_load_component(ctx, instrs, node, src_idx, *loc))) return NULL;
@@ -343,16 +348,12 @@ 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)))
if (!(store = hlsl_new_store_component(ctx, &block, &var_deref, dst_idx, &cast->node))) return NULL;
list_add_tail(instrs, &c->node.entry);
if (!(store = hlsl_new_store(ctx, var, &c->node, &cast->node, 0, *loc)))
return NULL;
list_add_tail(instrs, &store->node.entry);
list_move_tail(instrs, &block.instrs); }
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,22 +626,13 @@ 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_node, struct hlsl_ir_node *idx, const struct vkd3d_shader_location loc) {
struct hlsl_type *elem_type;
struct hlsl_ir_node *offset; struct hlsl_ir_load *load;
struct hlsl_block block;
elem_type = hlsl_get_type_from_path_index(ctx, var_node->data_type, idx);
if (var_node->type == HLSL_IR_LOAD) { const struct hlsl_deref *src = &hlsl_ir_load(var_node)->src;
if (!(offset = hlsl_new_offset_from_path_index(ctx, &block, var_node->data_type, src->offset.node, idx, &loc)))
return NULL;
list_move_tail(instrs, &block.instrs);
if (!(load = hlsl_new_load(ctx, src->var, offset, elem_type, loc)))
if (!(load = hlsl_new_load_index(ctx, src, idx, loc))) return NULL; list_add_tail(instrs, &load->node.entry); }
Is it possible to introduce hlsl_new_load_index() and hlsl_new_load_component() in helper patch(es), the same way we did for add_load_index()? Same for stores I think.
(I know this is a lot of splitting, and/or busywork, but the more the patch is split, the easier it is to be sure we've caught all the errors.)
On 08-07-22 17:28, Zebediah Figura wrote:
On 7/1/22 16:24, Francisco Casas wrote:
+/* Returns the path of a given component within a type, given its index.
- *comp_type will be set to the type of the component.
- *path_len will be set to the lenght of the path.
- Memory should be free afterwards.
- */
+unsigned int *hlsl_compute_component_path(struct hlsl_ctx *ctx, struct hlsl_type *type, + unsigned int idx, struct hlsl_type **comp_type, unsigned int *path_len)
This is awkward partly because zero is a valid length. Ideally it should return bool. More than that, though, it's filling fields of struct hlsl_deref, so what about something like
static bool hlsl_deref_from_component_index(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_var *var, unsigned int index)
This obviously doesn't lend itself nicely to recursion. I ended up playing around with this for a bit and came up with the following abbreviated code:
unsigned int subtype_index_from_component_index(struct hlsl_ctx *ctx, inout const struct hlsl_type **type, inout unsigned int *index) { assert(index < hlsl_type_component_count(type));
... }
static bool hlsl_deref_from_component_index(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_var *var, uint index) { const struct hlsl_type *type = var->data_type; unsigned int *indices; size_t index_count;
while (/* type is not 1x1 numeric */) { indices[index_count++] = subtype_index_from_component(ctx, &type, &index); }
init_deref(ctx, deref, var, index_count); // and so on }
Thoughts?
At first glance, and assuming we don't need hlsl_compute_component_path() somewhere else, this seems like a great idea!
I could also use subtype_index_from_component_index() to create a function to retrieve the component type without retrieving the path. As this is needed a couple of times.
+/* Returns a simple variable derefence, so that the value can be stored and then passed by reference
- to load/store functions. It shall not be modified afterwards. */
+struct hlsl_deref hlsl_get_direct_var_deref(struct hlsl_ir_var *var) +{ + struct hlsl_deref deref = {};
+ deref.var = var; + return deref; +}
Naming: for consistency with hlsl_new_simple_store() I'd replace "direct" with "simple". (Also naming: perhaps hlsl_simple_deref_from_var instead, i.e. follow the "X from Y" pattern given what the function is doing).
I'm also inclined to say this should take the hlsl_deref as a pointer in the first argument, rather than returning a struct.
Okay.
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)
Separate patch?
Hmm, I will give it a try.
@@ -870,10 +1136,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); + deref_copy(ctx, &load->resource, resource); + deref_copy(ctx, &load->sampler, sampler);
Actually that means deref_copy() could be pulled out of this patch, right? Just to save another hunk :-)
Sure!
@@ -334,7 +336,10 @@ 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_path = hlsl_compute_component_path(ctx, dst_type, dst_idx, &dst_scalar_type, &dst_path_len); + if (dst_path_len && !dst_path) + return NULL; + vkd3d_free(dst_path);
As far as I can tell we're just doing this so that we can get the right destination type to cast into. In that case my inclination is to move that cast into hlsl_new_store_component() itself. Same in initialize_var_components().
We could also use the aforementioned hypothetical function that retrieves the component type without retrieving the path. I will evaluate both alternatives.
if (!(load = add_load_component(ctx, instrs, node, src_idx, *loc))) return NULL; @@ -343,16 +348,12 @@ 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))) + if (!(store = hlsl_new_store_component(ctx, &block, &var_deref, dst_idx, &cast->node))) return NULL; - list_add_tail(instrs, &c->node.entry);
- if (!(store = hlsl_new_store(ctx, var, &c->node, &cast->node, 0, *loc))) - return NULL; - list_add_tail(instrs, &store->node.entry); + list_move_tail(instrs, &block.instrs); } - 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,22 +626,13 @@ 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_node, struct hlsl_ir_node *idx, const struct vkd3d_shader_location loc) { - struct hlsl_type *elem_type; - struct hlsl_ir_node *offset; struct hlsl_ir_load *load; - struct hlsl_block block;
- elem_type = hlsl_get_type_from_path_index(ctx, var_node->data_type, idx); if (var_node->type == HLSL_IR_LOAD) { const struct hlsl_deref *src = &hlsl_ir_load(var_node)->src; - if (!(offset = hlsl_new_offset_from_path_index(ctx, &block, var_node->data_type, src->offset.node, idx, &loc))) - return NULL; - list_move_tail(instrs, &block.instrs);
- if (!(load = hlsl_new_load(ctx, src->var, offset, elem_type, loc))) + if (!(load = hlsl_new_load_index(ctx, src, idx, loc))) return NULL; list_add_tail(instrs, &load->node.entry); }
Is it possible to introduce hlsl_new_load_index() and hlsl_new_load_component() in helper patch(es), the same way we did for add_load_index()? Same for stores I think.
(I know this is a lot of splitting, and/or busywork, but the more the patch is split, the easier it is to be sure we've caught all the errors.)
I fear I may need to add a lot of transitional code, which also requires to be understood, to keep the program working, so this splitting seems to be an "economy of scale" thing. Right now I am not sure how much of this transitional code would be actually needed. I will give it a try.