[Mesa-dev] [RFC 6/6] nir: Rework the way texture instructions reference samplers

Jason Ekstrand jason at jlekstrand.net
Sat Feb 6 05:10:55 UTC 2016


Originally, NIR texture instructions had a pointer to a deref chain that
represented the sampler.  This commit changes that.  Instead, we now use a
load_var to get the sampler index and then pass that directly into the
sampler_offset source of the instruction.  This mechanism has a couple of
advantages:  First, it gets rid of a bunch of special-casing around handling
variable derefs.  Second, it means that we can now pass samplers into
functions because the load of a sampler is just an integer.  This will make
things a bit easier for SPIR-V.
---
 src/compiler/nir/glsl_to_nir.cpp               | 35 ++++++++-------
 src/compiler/nir/nir.c                         |  5 ---
 src/compiler/nir/nir.h                         |  2 -
 src/compiler/nir/nir_clone.c                   |  2 -
 src/compiler/nir/nir_instr_set.c               | 15 +------
 src/compiler/nir/nir_lower_samplers.c          | 59 +++++++++++++-------------
 src/compiler/nir/nir_opt_constant_folding.c    |  5 +--
 src/compiler/nir/nir_print.c                   |  6 +--
 src/compiler/nir/nir_remove_dead_variables.c   | 13 ------
 src/compiler/nir/nir_validate.c                |  7 +--
 src/gallium/drivers/vc4/vc4_nir_lower_txf_ms.c |  1 -
 11 files changed, 53 insertions(+), 97 deletions(-)

diff --git a/src/compiler/nir/glsl_to_nir.cpp b/src/compiler/nir/glsl_to_nir.cpp
index 365fd4d..7ddf8d2 100644
--- a/src/compiler/nir/glsl_to_nir.cpp
+++ b/src/compiler/nir/glsl_to_nir.cpp
@@ -1753,69 +1753,69 @@ nir_visitor::visit(ir_swizzle *ir)
 void
 nir_visitor::visit(ir_texture *ir)
 {
-   unsigned num_srcs;
+   unsigned num_srcs = 1 /* Texture index */;
    nir_texop op;
    switch (ir->op) {
    case ir_tex:
       op = nir_texop_tex;
-      num_srcs = 1; /* coordinate */
+      num_srcs += 1; /* coordinate */
       break;
 
    case ir_txb:
    case ir_txl:
       op = (ir->op == ir_txb) ? nir_texop_txb : nir_texop_txl;
-      num_srcs = 2; /* coordinate, bias/lod */
+      num_srcs += 2; /* coordinate, bias/lod */
       break;
 
    case ir_txd:
       op = nir_texop_txd; /* coordinate, dPdx, dPdy */
-      num_srcs = 3;
+      num_srcs += 3;
       break;
 
    case ir_txf:
       op = nir_texop_txf;
       if (ir->lod_info.lod != NULL)
-         num_srcs = 2; /* coordinate, lod */
+         num_srcs += 2; /* coordinate, lod */
       else
-         num_srcs = 1; /* coordinate */
+         num_srcs += 1; /* coordinate */
       break;
 
    case ir_txf_ms:
       op = nir_texop_txf_ms;
-      num_srcs = 2; /* coordinate, sample_index */
+      num_srcs += 2; /* coordinate, sample_index */
       break;
 
    case ir_txs:
       op = nir_texop_txs;
       if (ir->lod_info.lod != NULL)
-         num_srcs = 1; /* lod */
+         num_srcs += 1; /* lod */
       else
-         num_srcs = 0;
+         num_srcs += 0;
       break;
 
    case ir_lod:
       op = nir_texop_lod;
-      num_srcs = 1; /* coordinate */
+      num_srcs += 1; /* coordinate */
       break;
 
    case ir_tg4:
       op = nir_texop_tg4;
-      num_srcs = 1; /* coordinate */
+      num_srcs += 1; /* coordinate */
       break;
 
    case ir_query_levels:
       op = nir_texop_query_levels;
-      num_srcs = 0;
+      num_srcs += 0;
       break;
 
    case ir_texture_samples:
       op = nir_texop_texture_samples;
-      num_srcs = 0;
+      num_srcs += 0;
       break;
 
    case ir_samples_identical:
       op = nir_texop_samples_identical;
-      num_srcs = 1; /* coordinate */
+      num_srcs += 1; /* coordinate */
       break;
 
    default:
@@ -1853,9 +1853,12 @@ nir_visitor::visit(ir_texture *ir)
       unreachable("not reached");
    }
 
-   instr->sampler = evaluate_deref(&instr->instr, ir->sampler);
+   nir_deref_var *sampler_deref = evaluate_deref(&instr->instr, ir->sampler);
+   instr->src[0].src = nir_src_for_ssa(nir_load_deref_var(&b, sampler_deref));
+   instr->src[0].src_type = nir_tex_src_sampler_offset;
+   instr->sampler_index = 0;
 
-   unsigned src_number = 0;
+   unsigned src_number = 1;
 
    if (ir->coordinate != NULL) {
       instr->coord_components = ir->coordinate->type->vector_elements;
diff --git a/src/compiler/nir/nir.c b/src/compiler/nir/nir.c
index 805c72d..f10fe6a 100644
--- a/src/compiler/nir/nir.c
+++ b/src/compiler/nir/nir.c
@@ -488,7 +488,6 @@ nir_tex_instr_create(nir_shader *shader, unsigned num_srcs)
 
    instr->sampler_index = 0;
    instr->max_sampler_index = 0;
-   instr->sampler = NULL;
 
    return instr;
 }
@@ -1005,10 +1004,6 @@ visit_tex_src(nir_tex_instr *instr, nir_foreach_src_cb cb, void *state)
       if (!visit_src(&instr->src[i].src, cb, state))
          return false;
 
-   if (instr->sampler != NULL)
-      if (!visit_deref_src(instr->sampler, cb, state))
-         return false;
-
    return true;
 }
 
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index b077f5a..645f71d 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -982,8 +982,6 @@ typedef struct {
 
    /** The maximum total sampler index including base and indirect*/
    unsigned max_sampler_index;
-
-   nir_deref_var *sampler; /* if this is NULL, use sampler_index instead */
 } nir_tex_instr;
 
 static inline unsigned
diff --git a/src/compiler/nir/nir_clone.c b/src/compiler/nir/nir_clone.c
index fc2e2d1..3f2d65f 100644
--- a/src/compiler/nir/nir_clone.c
+++ b/src/compiler/nir/nir_clone.c
@@ -359,8 +359,6 @@ clone_tex(clone_state *state, const nir_tex_instr *tex)
    ntex->component = tex->component;
    ntex->sampler_index = tex->sampler_index;
    ntex->max_sampler_index = tex->max_sampler_index;
-   if (tex->sampler)
-      ntex->sampler = clone_deref_var(state, tex->sampler, &ntex->instr);
 
    return ntex;
 }
diff --git a/src/compiler/nir/nir_instr_set.c b/src/compiler/nir/nir_instr_set.c
index 32c7318..66f7bbc 100644
--- a/src/compiler/nir/nir_instr_set.c
+++ b/src/compiler/nir/nir_instr_set.c
@@ -158,8 +158,6 @@ hash_tex(uint32_t hash, const nir_tex_instr *instr)
    hash = HASH(hash, instr->sampler_index);
    hash = HASH(hash, instr->max_sampler_index);
 
-   assert(!instr->sampler);
-
    return hash;
 }
 
@@ -310,9 +308,6 @@ nir_instrs_equal(const nir_instr *instr1, const nir_instr *instr2)
          return false;
       }
 
-      /* Don't support un-lowered sampler derefs currently. */
-      assert(!tex1->sampler && !tex2->sampler);
-
       return true;
    }
    case nir_instr_type_load_const: {
@@ -417,16 +412,8 @@ instr_can_rewrite(nir_instr *instr)
    case nir_instr_type_alu:
    case nir_instr_type_load_const:
    case nir_instr_type_phi:
+   case nir_instr_type_tex:
       return true;
-   case nir_instr_type_tex: {
-      nir_tex_instr *tex = nir_instr_as_tex(instr);
-
-      /* Don't support un-lowered sampler derefs currently. */
-      if (tex->sampler)
-         return false;
-
-      return true;
-   }
    case nir_instr_type_intrinsic: {
       const nir_intrinsic_info *info =
          &nir_intrinsic_infos[nir_instr_as_intrinsic(instr)->intrinsic];
diff --git a/src/compiler/nir/nir_lower_samplers.c b/src/compiler/nir/nir_lower_samplers.c
index c889df0..d51932d 100644
--- a/src/compiler/nir/nir_lower_samplers.c
+++ b/src/compiler/nir/nir_lower_samplers.c
@@ -59,9 +59,6 @@ calc_sampler_offsets(nir_deref *tail, nir_tex_instr *instr,
             nir_imul(b, nir_imm_int(b, *array_elements),
                      nir_ssa_for_src(b, deref_array->indirect, 1));
 
-         nir_instr_rewrite_src(&instr->instr, &deref_array->indirect,
-                               NIR_SRC_INIT);
-
          if (*indirect) {
             *indirect = nir_iadd(b, *indirect, mul);
          } else {
@@ -91,40 +88,46 @@ static void
 lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_program,
               gl_shader_stage stage, nir_builder *builder)
 {
-   if (instr->sampler == NULL)
+   unsigned src_idx;
+   for (src_idx = 0; src_idx < instr->num_srcs; src_idx++) {
+      if (instr->src[src_idx].src_type == nir_tex_src_sampler_offset)
+         break;
+   }
+   if (src_idx >= instr->num_srcs)
       return;
 
+   assert(instr->src[src_idx].src_type == nir_tex_src_sampler_offset);
+   assert(instr->src[src_idx].src.is_ssa);
+   assert(instr->src[src_idx].src.ssa->parent_instr->type ==
+          nir_instr_type_intrinsic);
+
+   nir_intrinsic_instr *offset_load =
+      nir_instr_as_intrinsic(instr->src[src_idx].src.ssa->parent_instr);
+
+   assert(offset_load->intrinsic == nir_intrinsic_load_var);
+   assert(glsl_get_base_type(nir_deref_tail(&offset_load->variables[0]->deref)->type) == GLSL_TYPE_SAMPLER);
+
    instr->sampler_index = 0;
-   unsigned location = instr->sampler->var->data.location;
+   unsigned location = offset_load->variables[0]->var->data.location;
    unsigned array_elements = 1;
    nir_ssa_def *indirect = NULL;
 
    builder->cursor = nir_before_instr(&instr->instr);
-   calc_sampler_offsets(&instr->sampler->deref, instr, &array_elements,
-                        &indirect, builder, &location);
+   calc_sampler_offsets(&offset_load->variables[0]->deref, instr,
+                        &array_elements, &indirect, builder, &location);
 
    if (indirect) {
-      /* First, we have to resize the array of texture sources */
-      nir_tex_src *new_srcs = rzalloc_array(instr, nir_tex_src,
-                                            instr->num_srcs + 1);
-
-      for (unsigned i = 0; i < instr->num_srcs; i++) {
-         new_srcs[i].src_type = instr->src[i].src_type;
-         nir_instr_move_src(&instr->instr, &new_srcs[i].src,
-                            &instr->src[i].src);
-      }
-
-      ralloc_free(instr->src);
-      instr->src = new_srcs;
-
-      /* Now we can go ahead and move the source over to being a
-       * first-class texture source.
-       */
-      instr->src[instr->num_srcs].src_type = nir_tex_src_sampler_offset;
-      instr->num_srcs++;
-      nir_instr_rewrite_src(&instr->instr,
-                            &instr->src[instr->num_srcs - 1].src,
+      nir_instr_rewrite_src(&instr->instr, &instr->src[src_idx].src,
                             nir_src_for_ssa(indirect));
+   } else {
+      nir_instr_rewrite_src(&instr->instr, &instr->src[src_idx].src,
+                            NIR_SRC_INIT);
+      for (unsigned i = src_idx + 1; i < instr->num_srcs; i++) {
+         instr->src[i-1].src_type = instr->src[i].src_type;
+         nir_instr_move_src(&instr->instr,
+                            &instr->src[i-1].src, &instr->src[i].src);
+      }
+      instr->num_srcs--;
    }
 
    if (location > shader_program->NumUniformStorage - 1 ||
@@ -137,8 +140,6 @@ lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_progr
       shader_program->UniformStorage[location].opaque[stage].index;
 
    instr->max_sampler_index = instr->sampler_index + array_elements - 1;
-
-   instr->sampler = NULL;
 }
 
 typedef struct {
diff --git a/src/compiler/nir/nir_opt_constant_folding.c b/src/compiler/nir/nir_opt_constant_folding.c
index 28a73f8..fc9f0c3 100644
--- a/src/compiler/nir/nir_opt_constant_folding.c
+++ b/src/compiler/nir/nir_opt_constant_folding.c
@@ -136,10 +136,7 @@ constant_fold_intrinsic_instr(nir_intrinsic_instr *instr)
 static bool
 constant_fold_tex_instr(nir_tex_instr *instr)
 {
-   if (instr->sampler)
-      return constant_fold_deref(&instr->instr, instr->sampler);
-   else
-      return false;
+   return false;
 }
 
 static bool
diff --git a/src/compiler/nir/nir_print.c b/src/compiler/nir/nir_print.c
index 48ecb48..cb1a90d 100644
--- a/src/compiler/nir/nir_print.c
+++ b/src/compiler/nir/nir_print.c
@@ -630,11 +630,7 @@ print_tex_instr(nir_tex_instr *instr, print_state *state)
       fprintf(fp, "%u (gather_component), ", instr->component);
    }
 
-   if (instr->sampler) {
-      print_deref(instr->sampler, state);
-   } else {
-      fprintf(fp, "%u", instr->sampler_index);
-   }
+   fprintf(fp, "%u", instr->sampler_index);
 
    fprintf(fp, " (sampler)");
 }
diff --git a/src/compiler/nir/nir_remove_dead_variables.c b/src/compiler/nir/nir_remove_dead_variables.c
index db754e5..5c8b3a1 100644
--- a/src/compiler/nir/nir_remove_dead_variables.c
+++ b/src/compiler/nir/nir_remove_dead_variables.c
@@ -51,15 +51,6 @@ add_var_use_call(nir_call_instr *instr, struct set *live)
    }
 }
 
-static void
-add_var_use_tex(nir_tex_instr *instr, struct set *live)
-{
-   if (instr->sampler != NULL) {
-      nir_variable *var = instr->sampler->var;
-      _mesa_set_add(live, var);
-   }
-}
-
 static bool
 add_var_use_block(nir_block *block, void *state)
 {
@@ -75,10 +66,6 @@ add_var_use_block(nir_block *block, void *state)
          add_var_use_call(nir_instr_as_call(instr), live);
          break;
 
-      case nir_instr_type_tex:
-         add_var_use_tex(nir_instr_as_tex(instr), live);
-         break;
-
       default:
          break;
       }
diff --git a/src/compiler/nir/nir_validate.c b/src/compiler/nir/nir_validate.c
index e4db68d..6092813 100644
--- a/src/compiler/nir/nir_validate.c
+++ b/src/compiler/nir/nir_validate.c
@@ -401,9 +401,7 @@ validate_intrinsic_instr(nir_intrinsic_instr *instr, validate_state *state)
    case nir_intrinsic_load_var: {
       const struct glsl_type *type =
          nir_deref_tail(&instr->variables[0]->deref)->type;
-      assert(glsl_type_is_vector_or_scalar(type) ||
-             (instr->variables[0]->var->data.mode == nir_var_uniform &&
-              glsl_get_base_type(type) == GLSL_TYPE_SUBROUTINE));
+      assert(!glsl_type_is_matrix(type));
       assert(instr->num_components == glsl_get_vector_elements(type));
       break;
    }
@@ -445,9 +443,6 @@ validate_tex_instr(nir_tex_instr *instr, validate_state *state)
       validate_src(&instr->src[i].src, state);
    }
 
-   if (instr->sampler != NULL)
-      validate_deref_var(instr, instr->sampler, state);
-
    validate_dest(&instr->dest, state);
 }
 
diff --git a/src/gallium/drivers/vc4/vc4_nir_lower_txf_ms.c b/src/gallium/drivers/vc4/vc4_nir_lower_txf_ms.c
index 6a952c6..d662f8f 100644
--- a/src/gallium/drivers/vc4/vc4_nir_lower_txf_ms.c
+++ b/src/gallium/drivers/vc4/vc4_nir_lower_txf_ms.c
@@ -47,7 +47,6 @@ vc4_nir_lower_txf_ms_instr(struct vc4_compile *c, nir_builder *b,
 
         nir_tex_instr *txf = nir_tex_instr_create(c->s, 1);
         txf->op = nir_texop_txf;
-        txf->sampler = txf_ms->sampler;
         txf->sampler_index = txf_ms->sampler_index;
         txf->coord_components = txf_ms->coord_components;
         txf->is_shadow = txf_ms->is_shadow;
-- 
2.5.0.400.gff86faf



More information about the mesa-dev mailing list