nir: Add support for generic pointers
authorJason Ekstrand <jason@jlekstrand.net>
Sat, 15 Aug 2020 05:28:55 +0000 (00:28 -0500)
committerMarge Bot <eric+marge@anholt.net>
Tue, 3 Nov 2020 22:18:28 +0000 (22:18 +0000)
The way they're handled is that deref->modes is treated as a bitfield of
possible modes.  Variables are required to have a specific mode and
derefs with deref_type_var are as well.

Reviewed-by: Jesse Natalie <jenatali@microsoft.com>
Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6332>

src/compiler/nir/nir.h
src/compiler/nir/nir_print.c
src/compiler/nir/nir_validate.c

index 71c8bad..c29ddeb 100644 (file)
@@ -128,6 +128,10 @@ typedef enum {
    nir_var_mem_ssbo        = (1 << 7),
    nir_var_mem_shared      = (1 << 8),
    nir_var_mem_global      = (1 << 9),
+   nir_var_mem_generic     = (nir_var_shader_temp |
+                              nir_var_function_temp |
+                              nir_var_mem_shared |
+                              nir_var_mem_global),
    nir_var_mem_push_const  = (1 << 10), /* not actually used for variables */
    nir_var_mem_constant    = (1 << 11),
    nir_var_read_only_modes = nir_var_shader_in | nir_var_uniform |
index 44aa645..98035c6 100644 (file)
@@ -723,9 +723,14 @@ print_deref_instr(nir_deref_instr *instr, print_state *state)
 
    print_deref_link(instr, false, state);
 
-   fprintf(fp, " (%s %s) ",
-           get_variable_mode_str(instr->modes, true),
-           glsl_get_type_name(instr->type));
+   fprintf(fp, " (");
+   unsigned modes = instr->modes;
+   while (modes) {
+      int m = u_bit_scan(&modes);
+      fprintf(fp, "%s%s", get_variable_mode_str(1 << m, true),
+                          modes ? "|" : "");
+   }
+   fprintf(fp, " %s) ", glsl_get_type_name(instr->type));
 
    if (instr->deref_type != nir_deref_type_var &&
        instr->deref_type != nir_deref_type_cast) {
index ee1c5c1..e6b4980 100644 (file)
@@ -407,8 +407,6 @@ validate_var_use(nir_variable *var, validate_state *state)
 static void
 validate_deref_instr(nir_deref_instr *instr, validate_state *state)
 {
-   validate_assert(state, util_bitcount(instr->modes) == 1);
-
    if (instr->deref_type == nir_deref_type_var) {
       /* Variable dereferences are stupid simple. */
       validate_assert(state, instr->modes == instr->var->data.mode);
@@ -420,8 +418,22 @@ validate_deref_instr(nir_deref_instr *instr, validate_state *state)
        */
       validate_src(&instr->parent, state, 0, 0);
 
-      /* We just validate that the type and mode are there */
-      validate_assert(state, instr->modes);
+      /* Most variable modes in NIR can only exist by themselves. */
+      if (instr->modes & ~nir_var_mem_generic)
+         validate_assert(state, util_bitcount(instr->modes) == 1);
+
+      nir_deref_instr *parent = nir_src_as_deref(instr->parent);
+      if (parent) {
+         /* Casts can change the mode but it can't change completely.  The new
+          * mode must have some bits in common with the old.
+          */
+         validate_assert(state, instr->modes & parent->modes);
+      } else {
+         /* If our parent isn't a deref, just assert the mode is there */
+         validate_assert(state, instr->modes != 0);
+      }
+
+      /* We just validate that the type is there */
       validate_assert(state, instr->type);
       if (instr->cast.align_mul > 0) {
          validate_assert(state, util_is_power_of_two_nonzero(instr->cast.align_mul));