[PATCH vkd3d v3 09/17] vkd3d-shader/hlsl: Replace register offsets with index paths in load initializations.

Giovanni Mascellani wine at mascellani.eu
Fri Jul 22 07:34:49 CDT 2022


Signed-off-by: Giovanni Mascellani <gmascellani at codeweavers.com>

Il 20/07/22 15:23, Francisco Casas ha scritto:
> The transform_deref_paths_into_offsets pass turns these index paths back
> into register offsets.
> 
> Signed-off-by: Francisco Casas <fcasas at codeweavers.com>
> ---
> 
> The idea is that we can move the transform_deref_paths_into_offsets()
> pass forward as we translate more passes to work with index paths.
> This, until register offsets can be totally removed, after we implement
> the SMxIRs and their translations.
> 
> The aim is to have 3 ways of initializing load/store nodes when using index
> paths:
> 
> * One that initializes the node from a another's node deref and and
>    optional index to be appended to that deref's path.
> * One that initializes the node from a deref and the index
>    of a single basic component within it. This one also generates constant
>    nodes for the required path, so it also initializes an instruction block
>    whose instructions must be inserted in the instruction list.
> * One that initializes the node directly for a whole variable. These functions
>    are already present: hlsl_new_var_load() and hlsl_new_simple_store().
> 
> The signatures of these functions are to be placed nearby in hlsl.h as
> they are introduced in the following patches.
> 
> It is worth noting that the use of index paths allows to remove the data type
> argument when initializing store/loads because it can now be deducted from the
> variable and the hlsl_deref.
> 
> Applying an index over a matrix derefence retrieves a vector. If the matrix
> is row_major, this corresponds to a row, otherwise, it corresponds to a
> column. So, the code should take matrix majority into account, at least until
> the split_matrix_copies pass.
> 
> The first index in a path after a loading a struct should be an
> hlsl_ir_constant, since the field that's being addressed is always
> known at parse-time.
> 
> hlsl_init_simple_deref_from_var() can be used to initialize a deref that can
> be passed by reference to the load and store initialization functions.
> This value shall not be modified after being created and does not
> require to call hlsl_cleanup_deref().
> The deref obtained with this function, can also be passed be passed as prefix
> to deref_from_component_index().
> 
> ---
> 
> v3:
> * Replaced compute_component_path() with deref_from_component_index().
> * Wrote implementation of init_deref() and get_type_from_deref() further
>    up in the file.
> * Made hlsl_new_load_component() use deref_from_component_index()
>    instead of the removed compute_component_path().
> * Rewrote hlsl.c function comments in present and active voice.
> * Renamed
>      typep -> type_ptr
>      indexp -> index_ptr
>    in subtype_index_from_component_index().
> * Added space before '?' in ternary operators.
> 
> Signed-off-by: Francisco Casas <fcasas at codeweavers.com>
> ---
>   libs/vkd3d-shader/hlsl.c         | 298 +++++++++++++++++++++++++++++--
>   libs/vkd3d-shader/hlsl.h         |  35 +++-
>   libs/vkd3d-shader/hlsl.y         | 102 ++++++-----
>   libs/vkd3d-shader/hlsl_codegen.c |  44 +++++
>   4 files changed, 410 insertions(+), 69 deletions(-)
> 
> diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c
> index 66acce23..535433ee 100644
> --- a/libs/vkd3d-shader/hlsl.c
> +++ b/libs/vkd3d-shader/hlsl.c
> @@ -330,6 +330,176 @@ unsigned int hlsl_compute_component_offset(struct hlsl_ctx *ctx, struct hlsl_typ
>       return 0;
>   }
>   
> +static bool type_is_single_component(const struct hlsl_type *type)
> +{
> +    return type->type == HLSL_CLASS_SCALAR || type->type == HLSL_CLASS_OBJECT;
> +}
> +
> +/* Given a type and a component index, this function returns the next path index required to reach
> + * the component within the type.
> + * It sets *type to the subtype within the original type that contains the component.
> + * It sets *index to the index of the component within *type. */
> +static unsigned int subtype_index_from_component_index(struct hlsl_ctx *ctx,
> +        struct hlsl_type **type_ptr, unsigned int *index_ptr)
> +{
> +    struct hlsl_type *type = *type_ptr;
> +    unsigned int index = *index_ptr;
> +
> +    assert(!type_is_single_component(type));
> +    assert(index < hlsl_type_component_count(type));
> +
> +    switch (type->type)
> +    {
> +        case HLSL_CLASS_VECTOR:
> +            assert(index < type->dimx);
> +            *type_ptr = hlsl_get_scalar_type(ctx, type->base_type);
> +            *index_ptr = 0;
> +            return index;
> +
> +        case HLSL_CLASS_MATRIX:
> +        {
> +            unsigned int y = index / type->dimx, x = index % type->dimx;
> +            bool row_major = hlsl_type_is_row_major(type);
> +
> +            assert(index < type->dimx * type->dimy);
> +            *type_ptr = hlsl_get_vector_type(ctx, type->base_type, row_major ? type->dimx : type->dimy);
> +            *index_ptr = row_major ? x : y;
> +            return row_major ? y : x;
> +        }
> +
> +        case HLSL_CLASS_ARRAY:
> +        {
> +            unsigned int elem_comp_count = hlsl_type_component_count(type->e.array.type);
> +            unsigned int array_index;
> +
> +            *type_ptr = type->e.array.type;
> +            *index_ptr = index % elem_comp_count;
> +            array_index = index / elem_comp_count;
> +            assert(array_index < type->e.array.elements_count);
> +            return array_index;
> +        }
> +
> +        case HLSL_CLASS_STRUCT:
> +        {
> +            struct hlsl_struct_field *field;
> +            unsigned int field_comp_count, i;
> +
> +            for (i = 0; i < type->e.record.field_count; ++i)
> +            {
> +                field = &type->e.record.fields[i];
> +                field_comp_count = hlsl_type_component_count(field->type);
> +                if (index < field_comp_count)
> +                {
> +                    *type_ptr = field->type;
> +                    *index_ptr = index;
> +                    return i;
> +                }
> +                index -= field_comp_count;
> +            }
> +            assert(0);
> +            return 0;
> +        }
> +
> +        default:
> +            assert(0);
> +            return 0;
> +    }
> +}
> +
> +struct hlsl_type *hlsl_type_get_component_type(struct hlsl_ctx *ctx, struct hlsl_type *type,
> +        unsigned int index)
> +{
> +    while (!type_is_single_component(type))
> +        subtype_index_from_component_index(ctx, &type, &index);
> +
> +    return type;
> +}
> +
> +static bool init_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_var *var,
> +        unsigned int path_len)
> +{
> +    deref->var = var;
> +    deref->path_len = path_len;
> +    deref->offset.node = NULL;
> +
> +    if (path_len == 0)
> +    {
> +        deref->path = NULL;
> +        return true;
> +    }
> +
> +    if (!(deref->path = hlsl_alloc(ctx, sizeof(*deref->path) * deref->path_len)))
> +    {
> +        deref->var = NULL;
> +        deref->path_len = 0;
> +        return false;
> +    }
> +
> +    return true;
> +}
> +
> +static struct hlsl_type *get_type_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref)
> +{
> +    struct hlsl_type *type;
> +    unsigned int i;
> +
> +    assert(deref);
> +    assert(!deref->offset.node);
> +
> +    type = deref->var->data_type;
> +    for (i = 0; i < deref->path_len; ++i)
> +        type = hlsl_get_type_from_path_index(ctx, type, deref->path[i].node);
> +    return type;
> +}
> +
> +/* Initializes a deref from another deref (prefix) and a component index. */
> +static bool deref_from_component_index(struct hlsl_ctx *ctx, struct hlsl_block *block,
> +        struct hlsl_deref *deref, const struct hlsl_deref *prefix, unsigned int index,
> +        const struct vkd3d_shader_location *loc)
> +{
> +    unsigned int path_len, path_index, deref_path_len, i;
> +    struct hlsl_type *path_type;
> +    struct hlsl_ir_constant *c;
> +
> +    list_init(&block->instrs);
> +
> +    path_len = 0;
> +    path_type = get_type_from_deref(ctx, prefix);
> +    path_index = index;
> +    while (!type_is_single_component(path_type))
> +    {
> +        subtype_index_from_component_index(ctx, &path_type, &path_index);
> +        ++path_len;
> +    }
> +
> +    if (!init_deref(ctx, deref, prefix->var, prefix->path_len + path_len))
> +        return false;
> +
> +    deref_path_len = 0;
> +    for (i = 0; i < prefix->path_len; ++i)
> +        hlsl_src_from_node(&deref->path[deref_path_len++], prefix->path[i].node);
> +
> +    path_type = get_type_from_deref(ctx, prefix);
> +    path_index = index;
> +    while (!type_is_single_component(path_type))
> +    {
> +        unsigned int next_index = subtype_index_from_component_index(ctx, &path_type, &path_index);
> +
> +        if (!(c = hlsl_new_uint_constant(ctx, next_index, loc)))
> +        {
> +            hlsl_free_instr_list(&block->instrs);
> +            return false;
> +        }
> +        list_add_tail(&block->instrs, &c->node.entry);
> +
> +        hlsl_src_from_node(&deref->path[deref_path_len++], &c->node);
> +    }
> +
> +    assert(deref_path_len == deref->path_len);
> +
> +    return true;
> +}
> +
>   struct hlsl_type *hlsl_get_type_from_path_index(struct hlsl_ctx *ctx, const struct hlsl_type *type,
>           struct hlsl_ir_node *node)
>   {
> @@ -435,6 +605,37 @@ struct hlsl_ir_node *hlsl_new_offset_from_path_index(struct hlsl_ctx *ctx, struc
>       return idx_offset;
>   }
>   
> +struct hlsl_ir_node *hlsl_new_offset_node_from_deref(struct hlsl_ctx *ctx, struct hlsl_block *block,
> +        const struct hlsl_deref *deref, const struct vkd3d_shader_location *loc)
> +{
> +    struct hlsl_ir_node *offset = NULL;
> +    struct hlsl_type *type;
> +    unsigned int i;
> +
> +    list_init(&block->instrs);
> +
> +    if (deref->offset.node)
> +        return deref->offset.node;
> +
> +    assert(deref->var);
> +
> +    type = deref->var->data_type;
> +
> +    for (i = 0; i < deref->path_len; ++i)
> +    {
> +        struct hlsl_block idx_block;
> +
> +        if (!(offset = hlsl_new_offset_from_path_index(ctx, &idx_block, type, offset, deref->path[i].node, loc)))
> +            return NULL;
> +
> +        list_move_tail(&block->instrs, &idx_block.instrs);
> +
> +        type = hlsl_get_type_from_path_index(ctx, type, deref->path[i].node);
> +    }
> +
> +    return offset;
> +}
> +
>   struct hlsl_type *hlsl_new_array_type(struct hlsl_ctx *ctx, struct hlsl_type *basic_type, unsigned int array_size)
>   {
>       struct hlsl_type *type;
> @@ -525,7 +726,7 @@ struct hlsl_ir_function_decl *hlsl_get_func_decl(struct hlsl_ctx *ctx, const cha
>       return NULL;
>   }
>   
> -unsigned int hlsl_type_component_count(struct hlsl_type *type)
> +unsigned int hlsl_type_component_count(const struct hlsl_type *type)
>   {
>       unsigned int count = 0, i;
>   
> @@ -742,8 +943,17 @@ static bool type_is_single_reg(const struct hlsl_type *type)
>       return type->type == HLSL_CLASS_SCALAR || type->type == HLSL_CLASS_VECTOR;
>   }
>   
> -static void cleanup_deref(struct hlsl_deref *deref)
> +void hlsl_cleanup_deref(struct hlsl_deref *deref)
>   {
> +    unsigned int i;
> +
> +    for (i = 0; i < deref->path_len; ++i)
> +        hlsl_src_remove(&deref->path[i]);
> +    vkd3d_free(deref->path);
> +
> +    deref->path = NULL;
> +    deref->path_len = 0;
> +
>       hlsl_src_remove(&deref->offset);
>   }
>   
> @@ -759,13 +969,20 @@ struct hlsl_ir_store *hlsl_new_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *v
>           return NULL;
>   
>       init_node(&store->node, HLSL_IR_STORE, NULL, loc);
> -    store->lhs.var = var;
> +    init_deref(ctx, &store->lhs, var, 0);
>       hlsl_src_from_node(&store->lhs.offset, offset);
>       hlsl_src_from_node(&store->rhs, rhs);
>       store->writemask = writemask;
>       return store;
>   }
>   
> +/* Initializes a simple variable derefence, so that it can be passed to load/store functions. */
> +void hlsl_init_simple_deref_from_var(struct hlsl_deref *deref, struct hlsl_ir_var *var)
> +{
> +    memset(deref, 0, sizeof(*deref));
> +    deref->var = var;
> +}
> +
>   struct hlsl_ir_store *hlsl_new_simple_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *lhs, struct hlsl_ir_node *rhs)
>   {
>       return hlsl_new_store(ctx, lhs, NULL, rhs, 0, rhs->loc);
> @@ -862,15 +1079,76 @@ struct hlsl_ir_load *hlsl_new_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var
>       if (!(load = hlsl_alloc(ctx, sizeof(*load))))
>           return NULL;
>       init_node(&load->node, HLSL_IR_LOAD, type, loc);
> -    load->src.var = var;
> +    init_deref(ctx, &load->src, var, 0);
>       hlsl_src_from_node(&load->src.offset, offset);
>       return load;
>   }
>   
> +struct hlsl_ir_load *hlsl_new_load_index(struct hlsl_ctx *ctx, const struct hlsl_deref *deref,
> +        struct hlsl_ir_node *idx, const struct vkd3d_shader_location *loc)
> +{
> +    struct hlsl_ir_load *load;
> +    struct hlsl_type *type;
> +    unsigned int i;
> +
> +    assert(!deref->offset.node);
> +
> +    type = get_type_from_deref(ctx, deref);
> +    if (idx)
> +        type = hlsl_get_type_from_path_index(ctx, type, idx);
> +
> +    if (!(load = hlsl_alloc(ctx, sizeof(*load))))
> +        return NULL;
> +    init_node(&load->node, HLSL_IR_LOAD, type, *loc);
> +
> +    if (!init_deref(ctx, &load->src, deref->var, deref->path_len + !!idx))
> +    {
> +        vkd3d_free(load);
> +        return NULL;
> +    }
> +    for (i = 0; i < deref->path_len; ++i)
> +        hlsl_src_from_node(&load->src.path[i], deref->path[i].node);
> +    if (idx)
> +        hlsl_src_from_node(&load->src.path[deref->path_len], idx);
> +
> +    return load;
> +}
> +
>   struct hlsl_ir_load *hlsl_new_var_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var,
> -        const struct vkd3d_shader_location loc)
> +        struct vkd3d_shader_location loc)
> +{
> +    struct hlsl_deref var_deref;
> +
> +    hlsl_init_simple_deref_from_var(&var_deref, var);
> +    return hlsl_new_load_index(ctx, &var_deref, NULL, &loc);
> +}
> +
> +struct hlsl_ir_load *hlsl_new_load_component(struct hlsl_ctx *ctx, struct hlsl_block *block,
> +        const struct hlsl_deref *deref, unsigned int comp, const struct vkd3d_shader_location *loc)
>   {
> -    return hlsl_new_load(ctx, var, NULL, var->data_type, loc);
> +    struct hlsl_type *type, *comp_type;
> +    struct hlsl_block comp_path_block;
> +    struct hlsl_ir_load *load;
> +
> +    list_init(&block->instrs);
> +
> +    if (!(load = hlsl_alloc(ctx, sizeof(*load))))
> +        return NULL;
> +
> +    type = get_type_from_deref(ctx, deref);
> +    comp_type = hlsl_type_get_component_type(ctx, type, comp);
> +    init_node(&load->node, HLSL_IR_LOAD, comp_type, *loc);
> +
> +    if (!deref_from_component_index(ctx, &comp_path_block, &load->src, deref, comp, loc))
> +    {
> +        vkd3d_free(load);
> +        return NULL;
> +    }
> +    list_move_tail(&block->instrs, &comp_path_block.instrs);
> +
> +    list_add_tail(&block->instrs, &load->node.entry);
> +
> +    return load;
>   }
>   
>   struct hlsl_ir_resource_load *hlsl_new_resource_load(struct hlsl_ctx *ctx, struct hlsl_type *data_type,
> @@ -1705,7 +1983,7 @@ static void free_ir_jump(struct hlsl_ir_jump *jump)
>   
>   static void free_ir_load(struct hlsl_ir_load *load)
>   {
> -    cleanup_deref(&load->src);
> +    hlsl_cleanup_deref(&load->src);
>       vkd3d_free(load);
>   }
>   
> @@ -1718,8 +1996,8 @@ static void free_ir_loop(struct hlsl_ir_loop *loop)
>   static void free_ir_resource_load(struct hlsl_ir_resource_load *load)
>   {
>       hlsl_src_remove(&load->coords);
> -    cleanup_deref(&load->sampler);
> -    cleanup_deref(&load->resource);
> +    hlsl_cleanup_deref(&load->sampler);
> +    hlsl_cleanup_deref(&load->resource);
>       hlsl_src_remove(&load->texel_offset);
>       vkd3d_free(load);
>   }
> @@ -1727,7 +2005,7 @@ static void free_ir_resource_load(struct hlsl_ir_resource_load *load)
>   static void free_ir_store(struct hlsl_ir_store *store)
>   {
>       hlsl_src_remove(&store->rhs);
> -    cleanup_deref(&store->lhs);
> +    hlsl_cleanup_deref(&store->lhs);
>       vkd3d_free(store);
>   }
>   
> diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h
> index 546c87f3..3a6af2a3 100644
> --- a/libs/vkd3d-shader/hlsl.h
> +++ b/libs/vkd3d-shader/hlsl.h
> @@ -374,6 +374,10 @@ struct hlsl_ir_swizzle
>   struct hlsl_deref
>   {
>       struct hlsl_ir_var *var;
> +
> +    unsigned int path_len;
> +    struct hlsl_src *path;
> +
>       struct hlsl_src offset;
>   };
>   
> @@ -717,6 +721,8 @@ void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl
>   int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func,
>           enum vkd3d_shader_target_type target_type, struct vkd3d_shader_code *out);
>   
> +void hlsl_cleanup_deref(struct hlsl_deref *deref);
> +
>   void hlsl_replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new);
>   
>   void hlsl_free_instr(struct hlsl_ir_node *node);
> @@ -751,14 +757,29 @@ struct hlsl_ir_if *hlsl_new_if(struct hlsl_ctx *ctx, struct hlsl_ir_node *condit
>   struct hlsl_ir_constant *hlsl_new_int_constant(struct hlsl_ctx *ctx, int n,
>           const struct vkd3d_shader_location *loc);
>   struct hlsl_ir_jump *hlsl_new_jump(struct hlsl_ctx *ctx, enum hlsl_ir_jump_type type, struct vkd3d_shader_location loc);
> -struct hlsl_ir_load *hlsl_new_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, struct hlsl_ir_node *offset,
> -        struct hlsl_type *type, struct vkd3d_shader_location loc);
> -struct hlsl_ir_loop *hlsl_new_loop(struct hlsl_ctx *ctx, struct vkd3d_shader_location loc);
> +
> +void hlsl_init_simple_deref_from_var(struct hlsl_deref *deref, struct hlsl_ir_var *var);
> +
> +struct hlsl_ir_load *hlsl_new_var_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var,
> +        struct vkd3d_shader_location loc);
> +struct hlsl_ir_load *hlsl_new_load_index(struct hlsl_ctx *ctx, const struct hlsl_deref *deref,
> +        struct hlsl_ir_node *idx, const struct vkd3d_shader_location *loc);
> +struct hlsl_ir_load *hlsl_new_load_component(struct hlsl_ctx *ctx, struct hlsl_block *block,
> +        const struct hlsl_deref *deref, unsigned int comp, const struct vkd3d_shader_location *loc);
> +
> +struct hlsl_ir_store *hlsl_new_simple_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *lhs, struct hlsl_ir_node *rhs);
> +
> +struct hlsl_ir_node *hlsl_new_offset_node_from_deref(struct hlsl_ctx *ctx, struct hlsl_block *block,
> +        const struct hlsl_deref *deref, const struct vkd3d_shader_location *loc);
> +
>   struct hlsl_ir_resource_load *hlsl_new_resource_load(struct hlsl_ctx *ctx, struct hlsl_type *data_type,
>           enum hlsl_resource_load_type type, struct hlsl_ir_var *resource, struct hlsl_ir_node *resource_offset,
>           struct hlsl_ir_var *sampler, struct hlsl_ir_node *sampler_offset, struct hlsl_ir_node *coords,
>           struct hlsl_ir_node *texel_offset, const struct vkd3d_shader_location *loc);
> -struct hlsl_ir_store *hlsl_new_simple_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *lhs, struct hlsl_ir_node *rhs);
> +
> +struct hlsl_ir_load *hlsl_new_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, struct hlsl_ir_node *offset,
> +        struct hlsl_type *type, struct vkd3d_shader_location loc);
> +struct hlsl_ir_loop *hlsl_new_loop(struct hlsl_ctx *ctx, struct vkd3d_shader_location loc);
>   struct hlsl_ir_store *hlsl_new_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, struct hlsl_ir_node *offset,
>           struct hlsl_ir_node *rhs, unsigned int writemask, struct vkd3d_shader_location loc);
>   struct hlsl_type *hlsl_new_struct_type(struct hlsl_ctx *ctx, const char *name,
> @@ -775,8 +796,6 @@ struct hlsl_ir_node *hlsl_new_unary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr
>   struct hlsl_ir_var *hlsl_new_var(struct hlsl_ctx *ctx, const char *name, struct hlsl_type *type,
>           const struct vkd3d_shader_location loc, const struct hlsl_semantic *semantic, unsigned int modifiers,
>           const struct hlsl_reg_reservation *reg_reservation);
> -struct hlsl_ir_load *hlsl_new_var_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var,
> -        const struct vkd3d_shader_location loc);
>   
>   void hlsl_error(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc,
>           enum vkd3d_shader_error error, const char *fmt, ...) VKD3D_PRINTF_FUNC(4, 5);
> @@ -794,10 +813,12 @@ bool hlsl_scope_add_type(struct hlsl_scope *scope, struct hlsl_type *type);
>   
>   struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old,
>           unsigned int default_majority, unsigned int modifiers);
> -unsigned int hlsl_type_component_count(struct hlsl_type *type);
> +unsigned int hlsl_type_component_count(const struct hlsl_type *type);
>   unsigned int hlsl_type_get_array_element_reg_size(const struct hlsl_type *type);
>   unsigned int hlsl_compute_component_offset(struct hlsl_ctx *ctx, struct hlsl_type *type,
>           unsigned int idx, struct hlsl_type **comp_type);
> +struct hlsl_type *hlsl_type_get_component_type(struct hlsl_ctx *ctx, struct hlsl_type *type,
> +        unsigned int index);
>   bool hlsl_type_is_row_major(const struct hlsl_type *type);
>   unsigned int hlsl_type_minor_size(const struct hlsl_type *type);
>   unsigned int hlsl_type_major_size(const struct hlsl_type *type);
> diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y
> index 5cdd6418..710d5748 100644
> --- a/libs/vkd3d-shader/hlsl.y
> +++ b/libs/vkd3d-shader/hlsl.y
> @@ -352,7 +352,7 @@ static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct list *instrs,
>               list_add_tail(instrs, &store->node.entry);
>           }
>   
> -        if (!(load = hlsl_new_load(ctx, var, NULL, dst_type, *loc)))
> +        if (!(load = hlsl_new_var_load(ctx, var, *loc)))
>               return NULL;
>           list_add_tail(instrs, &load->node.entry);
>   
> @@ -625,31 +625,18 @@ static struct hlsl_ir_jump *add_return(struct hlsl_ctx *ctx, struct list *instrs
>   static struct hlsl_ir_load *add_load_index(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *var_node,
>           struct hlsl_ir_node *idx, const struct vkd3d_shader_location *loc)
>   {
> -    struct hlsl_type *elem_type;
> -    struct hlsl_ir_node *offset;
> +    const struct hlsl_deref *src;
>       struct hlsl_ir_load *load;
> -    struct hlsl_block block;
> -    struct hlsl_ir_var *var;
> -
> -    elem_type = hlsl_get_type_from_path_index(ctx, var_node->data_type, idx);
>   
>       if (var_node->type == HLSL_IR_LOAD)
>       {
> -        const struct hlsl_deref *src = &hlsl_ir_load(var_node)->src;
> -
> -        var = src->var;
> -        if (!(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);
> +        src = &hlsl_ir_load(var_node)->src;
>       }
>       else
>       {
>           struct vkd3d_string_buffer *name;
>           struct hlsl_ir_store *store;
> -
> -        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);
> +        struct hlsl_ir_var *var;
>   
>           if (!(name = hlsl_get_string_buffer(ctx)))
>               return NULL;
> @@ -662,9 +649,11 @@ static struct hlsl_ir_load *add_load_index(struct hlsl_ctx *ctx, struct list *in
>           if (!(store = hlsl_new_simple_store(ctx, var, var_node)))
>               return NULL;
>           list_add_tail(instrs, &store->node.entry);
> +
> +        src = &store->lhs;
>       }
>   
> -    if (!(load = hlsl_new_load(ctx, var, offset, elem_type, *loc)))
> +    if (!(load = hlsl_new_load_index(ctx, src, idx, loc)))
>           return NULL;
>       list_add_tail(instrs, &load->node.entry);
>   
> @@ -674,39 +663,19 @@ static struct hlsl_ir_load *add_load_index(struct hlsl_ctx *ctx, struct list *in
>   static struct hlsl_ir_load *add_load_component(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *var_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;
> +    const struct hlsl_deref *src;
>       struct hlsl_ir_load *load;
> -    unsigned int comp_offset;
> -    struct hlsl_ir_var *var;
> -
> -    comp_offset = hlsl_compute_component_offset(ctx, var_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;
> -        }
> +        src = &hlsl_ir_load(var_node)->src;
>       }
>       else
>       {
>           struct vkd3d_string_buffer *name;
>           struct hlsl_ir_store *store;
> +        struct hlsl_ir_var *var;
>   
>           if (!(name = hlsl_get_string_buffer(ctx)))
>               return NULL;
> @@ -719,11 +688,13 @@ static struct hlsl_ir_load *add_load_component(struct hlsl_ctx *ctx, struct list
>           if (!(store = hlsl_new_simple_store(ctx, var, var_node)))
>               return NULL;
>           list_add_tail(instrs, &store->node.entry);
> +
> +        src = &store->lhs;
>       }
>   
> -    if (!(load = hlsl_new_load(ctx, var, offset, comp_type, *loc)))
> +    if (!(load = hlsl_new_load_component(ctx, &block, src, comp, loc)))
>           return NULL;
> -    list_add_tail(instrs, &load->node.entry);
> +    list_move_tail(instrs, &block.instrs);
>   
>       return load;
>   }
> @@ -1277,7 +1248,7 @@ static struct hlsl_ir_node *add_expr(struct hlsl_ctx *ctx, struct list *instrs,
>               list_add_tail(instrs, &store->node.entry);
>           }
>   
> -        if (!(load = hlsl_new_load(ctx, var, NULL, type, *loc)))
> +        if (!(load = hlsl_new_var_load(ctx, var, *loc)))
>               return NULL;
>           list_add_tail(instrs, &load->node.entry);
>   
> @@ -1634,8 +1605,10 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct list *in
>   {
>       struct hlsl_type *lhs_type = lhs->data_type;
>       struct hlsl_ir_store *store;
> +    struct hlsl_ir_node *offset;
>       struct hlsl_ir_expr *copy;
>       unsigned int writemask = 0;
> +    struct hlsl_block block;
>   
>       if (assign_op == ASSIGN_OP_SUB)
>       {
> @@ -1704,10 +1677,13 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct list *in
>           }
>       }
>   
> +    offset = hlsl_new_offset_node_from_deref(ctx, &block, &hlsl_ir_load(lhs)->src, &lhs->loc);
> +    list_move_tail(instrs, &block.instrs);
> +
>       init_node(&store->node, HLSL_IR_STORE, NULL, lhs->loc);
>       store->writemask = writemask;
>       store->lhs.var = hlsl_ir_load(lhs)->src.var;
> -    hlsl_src_from_node(&store->lhs.offset, hlsl_ir_load(lhs)->src.offset.node);
> +    hlsl_src_from_node(&store->lhs.offset, offset);
>       hlsl_src_from_node(&store->rhs, rhs);
>       list_add_tail(instrs, &store->node.entry);
>   
> @@ -2238,7 +2214,7 @@ static bool intrinsic_mul(struct hlsl_ctx *ctx,
>               list_add_tail(params->instrs, &store->node.entry);
>           }
>   
> -    if (!(load = hlsl_new_load(ctx, var, NULL, matrix_type, *loc)))
> +    if (!(load = hlsl_new_var_load(ctx, var, *loc)))
>           return false;
>       list_add_tail(params->instrs, &load->node.entry);
>   
> @@ -2447,8 +2423,10 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl
>               && object_type->sampler_dim != HLSL_SAMPLER_DIM_CUBEARRAY)
>       {
>           const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim);
> +        struct hlsl_ir_node *object_load_offset;
>           struct hlsl_ir_resource_load *load;
>           struct hlsl_ir_node *coords;
> +        struct hlsl_block block;
>   
>           if (object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMS
>                   || object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMSARRAY)
> @@ -2473,8 +2451,11 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl
>                   hlsl_get_vector_type(ctx, HLSL_TYPE_INT, sampler_dim + 1), loc)))
>               return false;
>   
> +        object_load_offset = hlsl_new_offset_node_from_deref(ctx, &block, &object_load->src, loc);
> +        list_move_tail(instrs, &block.instrs);
> +
>           if (!(load = hlsl_new_resource_load(ctx, object_type->e.resource_format, HLSL_RESOURCE_LOAD,
> -                object_load->src.var, object_load->src.offset.node, NULL, NULL, coords, NULL, loc)))
> +                object_load->src.var, object_load_offset, NULL, NULL, coords, NULL, loc)))
>               return false;
>           list_add_tail(instrs, &load->node.entry);
>           return true;
> @@ -2484,11 +2465,13 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl
>               && object_type->sampler_dim != HLSL_SAMPLER_DIM_2DMSARRAY)
>       {
>           const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim);
> +        struct hlsl_ir_node *object_load_offset, *sampler_load_offset;
>           const struct hlsl_type *sampler_type;
>           struct hlsl_ir_resource_load *load;
>           struct hlsl_ir_node *offset = NULL;
>           struct hlsl_ir_load *sampler_load;
>           struct hlsl_ir_node *coords;
> +        struct hlsl_block block;
>   
>           if (params->args_count != 2 && params->args_count != 3)
>           {
> @@ -2524,11 +2507,18 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl
>                   return false;
>           }
>   
> +        object_load_offset = hlsl_new_offset_node_from_deref(ctx, &block, &object_load->src, loc);
> +        list_move_tail(instrs, &block.instrs);
> +
> +        sampler_load_offset = hlsl_new_offset_node_from_deref(ctx, &block, &sampler_load->src, loc);
> +        list_move_tail(instrs, &block.instrs);
> +
>           if (!(load = hlsl_new_resource_load(ctx, object_type->e.resource_format,
> -                HLSL_RESOURCE_SAMPLE, object_load->src.var, object_load->src.offset.node,
> -                sampler_load->src.var, sampler_load->src.offset.node, coords, offset, loc)))
> +                HLSL_RESOURCE_SAMPLE, object_load->src.var, object_load_offset,
> +                sampler_load->src.var, sampler_load_offset, coords, offset, loc)))
>               return false;
>           list_add_tail(instrs, &load->node.entry);
> +
>           return true;
>       }
>       else if ((!strcmp(name, "Gather") || !strcmp(name, "GatherRed") || !strcmp(name, "GatherBlue")
> @@ -2539,6 +2529,7 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl
>               || object_type->sampler_dim == HLSL_SAMPLER_DIM_CUBEARRAY))
>       {
>           const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim);
> +        struct hlsl_ir_node *object_load_offset, *sampler_load_offset;
>           enum hlsl_resource_load_type load_type;
>           const struct hlsl_type *sampler_type;
>           struct hlsl_ir_resource_load *load;
> @@ -2547,6 +2538,7 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl
>           struct hlsl_type *result_type;
>           struct hlsl_ir_node *coords;
>           unsigned int read_channel;
> +        struct hlsl_block block;
>   
>           if (!strcmp(name, "GatherGreen"))
>           {
> @@ -2628,9 +2620,15 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl
>                   hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc)))
>               return false;
>   
> +        object_load_offset = hlsl_new_offset_node_from_deref(ctx, &block, &object_load->src, loc);
> +        list_move_tail(instrs, &block.instrs);
> +
> +        sampler_load_offset = hlsl_new_offset_node_from_deref(ctx, &block, &sampler_load->src, loc);
> +        list_move_tail(instrs, &block.instrs);
> +
>           if (!(load = hlsl_new_resource_load(ctx, result_type,
> -                load_type, object_load->src.var, object_load->src.offset.node,
> -                sampler_load->src.var, sampler_load->src.offset.node, coords, offset, loc)))
> +                load_type, object_load->src.var, object_load_offset,
> +                sampler_load->src.var, sampler_load_offset, coords, offset, loc)))
>               return false;
>           list_add_tail(instrs, &load->node.entry);
>           return true;
> diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c
> index 373439af..0b577f54 100644
> --- a/libs/vkd3d-shader/hlsl_codegen.c
> +++ b/libs/vkd3d-shader/hlsl_codegen.c
> @@ -21,6 +21,48 @@
>   #include "hlsl.h"
>   #include <stdio.h>
>   
> +/* TODO: remove when no longer needed, only used for transform_deref_paths_into_offsets() */
> +static void replace_deref_path_with_offset(struct hlsl_ctx *ctx, struct hlsl_deref *deref,
> +        struct hlsl_ir_node *instr)
> +{
> +    struct hlsl_ir_node *offset;
> +    struct hlsl_block block;
> +
> +    if (!deref->var)
> +        return;
> +
> +    if (!(offset = hlsl_new_offset_node_from_deref(ctx, &block, deref, &instr->loc)))
> +        return;
> +    list_move_before(&instr->entry, &block.instrs);
> +
> +    hlsl_cleanup_deref(deref);
> +    hlsl_src_from_node(&deref->offset, offset);
> +}
> +
> +/* TODO: remove when no longer needed. */
> +static bool transform_deref_paths_into_offsets(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
> +{
> +    switch(instr->type)
> +    {
> +        case HLSL_IR_LOAD:
> +            replace_deref_path_with_offset(ctx, &hlsl_ir_load(instr)->src, instr);
> +            return true;
> +
> +        case HLSL_IR_STORE:
> +            replace_deref_path_with_offset(ctx, &hlsl_ir_store(instr)->lhs, instr);
> +            return true;
> +
> +        case HLSL_IR_RESOURCE_LOAD:
> +            replace_deref_path_with_offset(ctx, &hlsl_ir_resource_load(instr)->resource, instr);
> +            replace_deref_path_with_offset(ctx, &hlsl_ir_resource_load(instr)->sampler, instr);
> +            return true;
> +
> +        default:
> +            return false;
> +    }
> +    return false;
> +}
> +
>   /* Split uniforms into two variables representing the constant and temp
>    * registers, and copy the former to the latter, so that writes to uniforms
>    * work. */
> @@ -1890,6 +1932,8 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry
>   
>       list_move_head(&body->instrs, &ctx->static_initializers);
>   
> +    transform_ir(ctx, transform_deref_paths_into_offsets, body, NULL); /* TODO: move forward, remove when no longer needed */
> +
>       LIST_FOR_EACH_ENTRY(var, &ctx->globals->vars, struct hlsl_ir_var, scope_entry)
>       {
>           if (var->modifiers & HLSL_STORAGE_UNIFORM)



More information about the wine-devel mailing list