compiler/nir: Add support for variable initialization from a pointer
authorArcady Goldmints-Orlov <agoldmints@igalia.com>
Tue, 10 Dec 2019 20:37:53 +0000 (15:37 -0500)
committerCaio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
Wed, 12 Feb 2020 15:41:49 +0000 (15:41 +0000)
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 <caio.oliveira@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3047>

src/compiler/nir/nir.h
src/compiler/nir/nir_lower_constant_initializers.c
src/compiler/nir/nir_lower_io_to_temporaries.c
src/compiler/nir/nir_lower_locals_to_regs.c
src/compiler/nir/nir_lower_vars_to_ssa.c
src/compiler/nir/nir_print.c
src/compiler/nir/nir_serialize.c
src/compiler/nir/nir_split_per_member_structs.c

index c9edcadaaef278290009b037648a0d88483b470d..969fbac60e5c4b0dd1b60ca392a3c55d4eaccdb9 100644 (file)
@@ -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.
index d373c2336d2b265ab64a3029a2f6c2206f75191d..03f5a2f404c5393a38f0d5f373d458babf45143d 100644 (file)
@@ -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;
index 1ede0238e4f63122553a6e6b22028661a0dbe179..a3ee6e4ed6a19fdd5182b04f222a09d73b14ad2d 100644 (file)
@@ -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 @<mode>-temp appended */
    const char *mode = (temp->data.mode == nir_var_shader_in) ? "in" : "out";
index 37e17d5b9804f5852de4aefdb7a75301a3d08b7a..e417c6419faa59a2190fac6b075e579f08901b79 100644 (file)
@@ -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);
index c685b7ffa0cbffddee650d31b75c05720d0540f8..0077ddf50f3680af30097cdb9f00f4ded32d7ca6 100644 (file)
@@ -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) {
index cdab71430a71f4621584b5b2a6e6e721d2774ca3..d4bc70a6aef59f7f95f8826497aa30761f7cbe4a 100644 (file)
@@ -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);
index 7b6ed5e31a11b3a468ba7ad50d51284efda982c1..0be80faf9a1763866a0b9ceb60b115ab39174bce 100644 (file)
@@ -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,
index 592225ba644607f2722d72cb9442c243933941e7..9148902b27ca197b65f0ed090369dea9126f44d5 100644 (file)
@@ -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);