From 7acc81056f7ac6a869ef6403573b2572c77dbecf Mon Sep 17 00:00:00 2001 From: Arcady Goldmints-Orlov Date: Tue, 10 Dec 2019 15:37:53 -0500 Subject: [PATCH] compiler/nir: Add support for variable initialization from a pointer Add a pointer_initializer field to nir_variable analogous to constant_initializer, which can be used to initialize the nir_variable to a pointer to another nir_variable. Just like the constant_initializer, the pointer_initializer gets eliminated in the nir_lower_constant_initializers pass. Reviewed-by: Caio Marcelo de Oliveira Filho Part-of: --- src/compiler/nir/nir.h | 8 ++++++++ .../nir/nir_lower_constant_initializers.c | 20 +++++++++++++------ .../nir/nir_lower_io_to_temporaries.c | 2 +- src/compiler/nir/nir_lower_locals_to_regs.c | 3 ++- src/compiler/nir/nir_lower_vars_to_ssa.c | 3 ++- src/compiler/nir/nir_print.c | 2 ++ src/compiler/nir/nir_serialize.c | 12 ++++++++++- .../nir/nir_split_per_member_structs.c | 2 +- 8 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index c9edcadaaef..969fbac60e5 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -578,6 +578,14 @@ typedef struct nir_variable { */ nir_constant *constant_initializer; + /** + * Global variable assigned in the initializer of the variable + * This field should only be used temporarily by creators of NIR shaders + * and then lower_constant_initializers can be used to get rid of them. + * Most of the rest of NIR ignores this field or asserts that it's NULL. + */ + struct nir_variable *pointer_initializer; + /** * For variables that are in an interface block or are an instance of an * interface block, this is the \c GLSL_TYPE_INTERFACE type for that block. diff --git a/src/compiler/nir/nir_lower_constant_initializers.c b/src/compiler/nir/nir_lower_constant_initializers.c index d373c2336d2..03f5a2f404c 100644 --- a/src/compiler/nir/nir_lower_constant_initializers.c +++ b/src/compiler/nir/nir_lower_constant_initializers.c @@ -61,15 +61,23 @@ lower_const_initializer(struct nir_builder *b, struct exec_list *var_list) b->cursor = nir_before_cf_list(&b->impl->body); nir_foreach_variable(var, var_list) { - if (!var->constant_initializer) - continue; + if (var->constant_initializer) { + build_constant_load(b, nir_build_deref_var(b, var), + var->constant_initializer); - progress = true; + progress = true; + var->constant_initializer = NULL; + } else if (var->pointer_initializer) { + nir_deref_instr *src_deref = nir_build_deref_var(b, var->pointer_initializer); + nir_deref_instr *dst_deref = nir_build_deref_var(b, var); + + /* Note that this stores a pointer to src into dst */ + nir_store_deref(b, dst_deref, &src_deref->dest.ssa, ~0); - build_constant_load(b, nir_build_deref_var(b, var), - var->constant_initializer); + progress = true; + var->pointer_initializer = NULL; + } - var->constant_initializer = NULL; } return progress; diff --git a/src/compiler/nir/nir_lower_io_to_temporaries.c b/src/compiler/nir/nir_lower_io_to_temporaries.c index 1ede0238e4f..a3ee6e4ed6a 100644 --- a/src/compiler/nir/nir_lower_io_to_temporaries.c +++ b/src/compiler/nir/nir_lower_io_to_temporaries.c @@ -297,7 +297,7 @@ create_shadow_temp(struct lower_io_state *state, nir_variable *var) /* Reparent the name to the new variable */ ralloc_steal(nvar, nvar->name); - assert(nvar->constant_initializer == NULL); + assert(nvar->constant_initializer == NULL && nvar->pointer_initializer == NULL); /* Give the original a new name with @-temp appended */ const char *mode = (temp->data.mode == nir_var_shader_in) ? "in" : "out"; diff --git a/src/compiler/nir/nir_lower_locals_to_regs.c b/src/compiler/nir/nir_lower_locals_to_regs.c index 37e17d5b980..e417c6419fa 100644 --- a/src/compiler/nir/nir_lower_locals_to_regs.c +++ b/src/compiler/nir/nir_lower_locals_to_regs.c @@ -101,7 +101,8 @@ get_reg_for_deref(nir_deref_instr *deref, struct locals_to_regs_state *state) { uint32_t hash = hash_deref(deref); - assert(nir_deref_instr_get_variable(deref)->constant_initializer == NULL); + assert(nir_deref_instr_get_variable(deref)->constant_initializer == NULL && + nir_deref_instr_get_variable(deref)->pointer_initializer == NULL); struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(state->regs_table, hash, deref); diff --git a/src/compiler/nir/nir_lower_vars_to_ssa.c b/src/compiler/nir/nir_lower_vars_to_ssa.c index c685b7ffa0c..0077ddf50f3 100644 --- a/src/compiler/nir/nir_lower_vars_to_ssa.c +++ b/src/compiler/nir/nir_lower_vars_to_ssa.c @@ -779,7 +779,8 @@ nir_lower_vars_to_ssa_impl(nir_function_impl *impl) memset(store_blocks, 0, BITSET_WORDS(state.impl->num_blocks) * sizeof(*store_blocks)); - assert(node->path.path[0]->var->constant_initializer == NULL); + assert(node->path.path[0]->var->constant_initializer == NULL && + node->path.path[0]->var->pointer_initializer == NULL); if (node->stores) { set_foreach(node->stores, store_entry) { diff --git a/src/compiler/nir/nir_print.c b/src/compiler/nir/nir_print.c index cdab71430a7..d4bc70a6aef 100644 --- a/src/compiler/nir/nir_print.c +++ b/src/compiler/nir/nir_print.c @@ -558,6 +558,8 @@ print_var_decl(nir_variable *var, print_state *state) print_constant(var->constant_initializer, var->type, state); fprintf(fp, " }"); } + if (var->pointer_initializer) + fprintf(fp, " = &%s", get_var_name(var->pointer_initializer, state)); fprintf(fp, "\n"); print_annotation(state, var); diff --git a/src/compiler/nir/nir_serialize.c b/src/compiler/nir/nir_serialize.c index 7b6ed5e31a1..0be80faf9a1 100644 --- a/src/compiler/nir/nir_serialize.c +++ b/src/compiler/nir/nir_serialize.c @@ -206,12 +206,13 @@ union packed_var { struct { unsigned has_name:1; unsigned has_constant_initializer:1; + unsigned has_pointer_initializer:1; unsigned has_interface_type:1; unsigned num_state_slots:7; unsigned data_encoding:2; unsigned type_same_as_last:1; unsigned interface_type_same_as_last:1; - unsigned _pad:2; + unsigned _pad:1; unsigned num_members:16; } u; }; @@ -238,6 +239,7 @@ write_variable(write_ctx *ctx, const nir_variable *var) flags.u.has_name = !ctx->strip && var->name; flags.u.has_constant_initializer = !!(var->constant_initializer); + flags.u.has_pointer_initializer = !!(var->pointer_initializer); flags.u.has_interface_type = !!(var->interface_type); flags.u.type_same_as_last = var->type == ctx->last_type; flags.u.interface_type_same_as_last = @@ -322,6 +324,8 @@ write_variable(write_ctx *ctx, const nir_variable *var) } if (var->constant_initializer) write_constant(ctx, var->constant_initializer); + if (var->pointer_initializer) + write_lookup_object(ctx, var->pointer_initializer); if (var->num_members > 0) { blob_write_bytes(ctx->blob, (uint8_t *) var->members, var->num_members * sizeof(*var->members)); @@ -392,6 +396,12 @@ read_variable(read_ctx *ctx) var->constant_initializer = read_constant(ctx, var); else var->constant_initializer = NULL; + + if (flags.u.has_pointer_initializer) + var->pointer_initializer = read_object(ctx); + else + var->pointer_initializer = NULL; + var->num_members = flags.u.num_members; if (var->num_members > 0) { var->members = ralloc_array(var, struct nir_variable_data, diff --git a/src/compiler/nir/nir_split_per_member_structs.c b/src/compiler/nir/nir_split_per_member_structs.c index 592225ba644..9148902b27c 100644 --- a/src/compiler/nir/nir_split_per_member_structs.c +++ b/src/compiler/nir/nir_split_per_member_structs.c @@ -66,7 +66,7 @@ split_variable(struct nir_variable *var, nir_shader *shader, assert(var->state_slots == NULL); /* Constant initializers are currently not handled */ - assert(var->constant_initializer == NULL); + assert(var->constant_initializer == NULL && var->pointer_initializer == NULL); nir_variable **members = ralloc_array(dead_ctx, nir_variable *, var->num_members); -- 2.30.2