[Mesa-dev] [PATCH v2 2/8] nir: Separate texture from sampler in nir_tex_instr

Jason Ekstrand jason at jlekstrand.net
Sat Feb 6 18:19:46 UTC 2016


This commit adds the capability to NIR to support separate textures and
samplers.  As it currently stands, glsl_to_nir only sets the texture deref
and leaves the sampler deref alone as it did before and nir_lower_samplers
assumes this.  Backends can still assume that they are combined and only
look at only at the texture index.  Or, if they wish, they can assume that
they are separate because nir_lower_samplers, tgsi_to_nir, and prog_to_nir
all set both texture and sampler index whenever a sampler is required (the
two indices are the same in this case).
---
 src/compiler/nir/nir.c                       |  6 ++++++
 src/compiler/nir/nir.h                       | 31 +++++++++++++++++++++++++++-
 src/compiler/nir/nir_clone.c                 |  7 ++++++-
 src/compiler/nir/nir_instr_set.c             | 15 ++++++++------
 src/compiler/nir/nir_lower_samplers.c        | 13 +++++++++++-
 src/compiler/nir/nir_lower_tex.c             |  6 +++---
 src/compiler/nir/nir_opt_constant_folding.c  | 11 +++++++---
 src/compiler/nir/nir_print.c                 | 14 ++++++++++---
 src/compiler/nir/nir_remove_dead_variables.c |  5 +++++
 src/compiler/nir/nir_validate.c              |  3 +++
 src/gallium/auxiliary/nir/tgsi_to_nir.c      |  1 +
 src/mesa/drivers/dri/i965/brw_fs_nir.cpp     |  3 +++
 src/mesa/drivers/dri/i965/brw_vec4_nir.cpp   |  3 +++
 src/mesa/program/prog_to_nir.c               |  1 +
 14 files changed, 101 insertions(+), 18 deletions(-)

diff --git a/src/compiler/nir/nir.c b/src/compiler/nir/nir.c
index b8cc84d..cd22a5c 100644
--- a/src/compiler/nir/nir.c
+++ b/src/compiler/nir/nir.c
@@ -489,6 +489,8 @@ nir_tex_instr_create(nir_shader *shader, unsigned num_srcs)
    instr->texture_index = 0;
    instr->texture_array_size = 0;
    instr->texture = NULL;
+   instr->sampler_index = 0;
+   instr->sampler = NULL;
 
    return instr;
 }
@@ -1009,6 +1011,10 @@ visit_tex_src(nir_tex_instr *instr, nir_foreach_src_cb cb, void *state)
       if (!visit_deref_src(instr->texture, 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 372d308..7813f84 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -924,6 +924,7 @@ typedef enum {
    nir_tex_src_ddx,
    nir_tex_src_ddy,
    nir_tex_src_texture_offset, /* < dynamically uniform indirect offset */
+   nir_tex_src_sampler_offset, /* < dynamically uniform indirect offset */
    nir_num_tex_src_types
 } nir_tex_src_type;
 
@@ -983,7 +984,35 @@ typedef struct {
    /** The size of the texture array or 0 if it's not an array */
    unsigned texture_array_size;
 
-   nir_deref_var *texture; /* if this is NULL, use texture_index instead */
+   /** The texture deref
+    *
+    * If this is null, use texture_index instead.
+    */
+   nir_deref_var *texture;
+
+   /** The sampler index
+    *
+    * The following operations do not require a sampler and, as such, this
+    * field should be ignored:
+    *    - nir_texop_txf
+    *    - nir_texop_txf_ms
+    *    - nir_texop_txs
+    *    - nir_texop_lod
+    *    - nir_texop_tg4
+    *    - nir_texop_query_levels
+    *    - nir_texop_texture_samples
+    *    - nir_texop_samples_identical
+    *
+    * If this texture instruction has a nir_tex_src_sampler_offset source,
+    * then the sampler index is given by sampler_index + sampler_offset.
+    */
+   unsigned sampler_index;
+
+   /** The sampler deref
+    *
+    * If this is null, use sampler_index instead.
+    */
+   nir_deref_var *sampler;
 } nir_tex_instr;
 
 static inline unsigned
diff --git a/src/compiler/nir/nir_clone.c b/src/compiler/nir/nir_clone.c
index d9c190d..a666d8e 100644
--- a/src/compiler/nir/nir_clone.c
+++ b/src/compiler/nir/nir_clone.c
@@ -357,10 +357,15 @@ clone_tex(clone_state *state, const nir_tex_instr *tex)
    ntex->is_new_style_shadow = tex->is_new_style_shadow;
    memcpy(ntex->const_offset, tex->const_offset, sizeof(ntex->const_offset));
    ntex->component = tex->component;
+
    ntex->texture_index = tex->texture_index;
-   ntex->texture_array_size = tex->texture_array_size;
    if (tex->texture)
       ntex->texture = clone_deref_var(state, tex->texture, &ntex->instr);
+   ntex->texture_array_size = tex->texture_array_size;
+
+   ntex->sampler_index = tex->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 4489a88..c3cf257 100644
--- a/src/compiler/nir/nir_instr_set.c
+++ b/src/compiler/nir/nir_instr_set.c
@@ -157,8 +157,9 @@ hash_tex(uint32_t hash, const nir_tex_instr *instr)
    hash = HASH(hash, component);
    hash = HASH(hash, instr->texture_index);
    hash = HASH(hash, instr->texture_array_size);
+   hash = HASH(hash, instr->sampler_index);
 
-   assert(!instr->texture);
+   assert(!instr->texture && !instr->sampler);
 
    return hash;
 }
@@ -306,12 +307,14 @@ nir_instrs_equal(const nir_instr *instr1, const nir_instr *instr2)
                  sizeof(tex1->const_offset)) != 0 ||
           tex1->component != tex2->component ||
          tex1->texture_index != tex2->texture_index ||
-         tex1->texture_array_size != tex2->texture_array_size) {
+         tex1->texture_array_size != tex2->texture_array_size ||
+         tex1->sampler_index != tex2->sampler_index) {
          return false;
       }
 
-      /* Don't support un-lowered texture derefs currently. */
-      assert(!tex1->texture && !tex2->texture);
+      /* Don't support un-lowered sampler derefs currently. */
+      assert(!tex1->texture && !tex1->sampler &&
+             !tex2->texture && !tex2->sampler);
 
       return true;
    }
@@ -421,8 +424,8 @@ instr_can_rewrite(nir_instr *instr)
    case nir_instr_type_tex: {
       nir_tex_instr *tex = nir_instr_as_tex(instr);
 
-      /* Don't support un-lowered texture derefs currently. */
-      if (tex->texture)
+      /* Don't support un-lowered sampler derefs currently. */
+      if (tex->texture || tex->sampler)
          return false;
 
       return true;
diff --git a/src/compiler/nir/nir_lower_samplers.c b/src/compiler/nir/nir_lower_samplers.c
index bccb544..f5d3e59 100644
--- a/src/compiler/nir/nir_lower_samplers.c
+++ b/src/compiler/nir/nir_lower_samplers.c
@@ -94,6 +94,9 @@ lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_progr
    if (instr->texture == NULL)
       return;
 
+   /* In GLSL, we only fill out the texture field.  The sampler is inferred */
+   assert(instr->sampler == NULL);
+
    instr->texture_index = 0;
    unsigned location = instr->texture->var->data.location;
    unsigned array_elements = 1;
@@ -106,7 +109,7 @@ lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_progr
    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);
+                                            instr->num_srcs + 2);
 
       for (unsigned i = 0; i < instr->num_srcs; i++) {
          new_srcs[i].src_type = instr->src[i].src_type;
@@ -126,6 +129,12 @@ lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_progr
                             &instr->src[instr->num_srcs - 1].src,
                             nir_src_for_ssa(indirect));
 
+      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_src_for_ssa(indirect));
+
       instr->texture_array_size = array_elements;
    }
 
@@ -138,6 +147,8 @@ lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_progr
    instr->texture_index +=
       shader_program->UniformStorage[location].opaque[stage].index;
 
+   instr->sampler_index = instr->texture_index;
+
    instr->texture = NULL;
 }
 
diff --git a/src/compiler/nir/nir_lower_tex.c b/src/compiler/nir/nir_lower_tex.c
index 4c0759b..806acd8 100644
--- a/src/compiler/nir/nir_lower_tex.c
+++ b/src/compiler/nir/nir_lower_tex.c
@@ -291,11 +291,11 @@ nir_lower_tex_block(nir_block *block, void *void_state)
       /* mask of src coords to saturate (clamp): */
       unsigned sat_mask = 0;
 
-      if ((1 << tex->texture_index) & state->options->saturate_r)
+      if ((1 << tex->sampler_index) & state->options->saturate_r)
          sat_mask |= (1 << 2);    /* .z */
-      if ((1 << tex->texture_index) & state->options->saturate_t)
+      if ((1 << tex->sampler_index) & state->options->saturate_t)
          sat_mask |= (1 << 1);    /* .y */
-      if ((1 << tex->texture_index) & state->options->saturate_s)
+      if ((1 << tex->sampler_index) & state->options->saturate_s)
          sat_mask |= (1 << 0);    /* .x */
 
       /* If we are clamping any coords, we must lower projector first
diff --git a/src/compiler/nir/nir_opt_constant_folding.c b/src/compiler/nir/nir_opt_constant_folding.c
index 20b31a8..04876a4 100644
--- a/src/compiler/nir/nir_opt_constant_folding.c
+++ b/src/compiler/nir/nir_opt_constant_folding.c
@@ -136,10 +136,15 @@ constant_fold_intrinsic_instr(nir_intrinsic_instr *instr)
 static bool
 constant_fold_tex_instr(nir_tex_instr *instr)
 {
+   bool progress = false;
+
    if (instr->texture)
-      return constant_fold_deref(&instr->instr, instr->texture);
-   else
-      return false;
+      progress |= constant_fold_deref(&instr->instr, instr->texture);
+
+   if (instr->sampler)
+      progress |= constant_fold_deref(&instr->instr, instr->sampler);
+
+   return progress;
 }
 
 static bool
diff --git a/src/compiler/nir/nir_print.c b/src/compiler/nir/nir_print.c
index c960796..b10a48a 100644
--- a/src/compiler/nir/nir_print.c
+++ b/src/compiler/nir/nir_print.c
@@ -603,6 +603,9 @@ print_tex_instr(nir_tex_instr *instr, print_state *state)
       case nir_tex_src_texture_offset:
          fprintf(fp, "(texture_offset)");
          break;
+      case nir_tex_src_sampler_offset:
+         fprintf(fp, "(sampler_offset)");
+         break;
 
       default:
          unreachable("Invalid texture source type");
@@ -632,11 +635,16 @@ print_tex_instr(nir_tex_instr *instr, print_state *state)
 
    if (instr->texture) {
       print_deref(instr->texture, state);
+      fprintf(fp, " (texture)");
+      if (instr->sampler) {
+         print_deref(instr->sampler, state);
+         fprintf(fp, " (sampler)");
+      }
    } else {
-      fprintf(fp, "%u", instr->texture_index);
+      assert(instr->sampler == NULL);
+      fprintf(fp, "%u (texture) %u (sampler)",
+              instr->texture_index, instr->sampler_index);
    }
-
-   fprintf(fp, " (texture)");
 }
 
 static void
diff --git a/src/compiler/nir/nir_remove_dead_variables.c b/src/compiler/nir/nir_remove_dead_variables.c
index 24bae46..6519268 100644
--- a/src/compiler/nir/nir_remove_dead_variables.c
+++ b/src/compiler/nir/nir_remove_dead_variables.c
@@ -58,6 +58,11 @@ add_var_use_tex(nir_tex_instr *instr, struct set *live)
       nir_variable *var = instr->texture->var;
       _mesa_set_add(live, var);
    }
+
+   if (instr->sampler != NULL) {
+      nir_variable *var = instr->sampler->var;
+      _mesa_set_add(live, var);
+   }
 }
 
 static bool
diff --git a/src/compiler/nir/nir_validate.c b/src/compiler/nir/nir_validate.c
index fcc72cb..3728c5b 100644
--- a/src/compiler/nir/nir_validate.c
+++ b/src/compiler/nir/nir_validate.c
@@ -448,6 +448,9 @@ validate_tex_instr(nir_tex_instr *instr, validate_state *state)
    if (instr->texture != NULL)
       validate_deref_var(instr, instr->texture, state);
 
+   if (instr->sampler != NULL)
+      validate_deref_var(instr, instr->sampler, state);
+
    validate_dest(&instr->dest, state);
 }
 
diff --git a/src/gallium/auxiliary/nir/tgsi_to_nir.c b/src/gallium/auxiliary/nir/tgsi_to_nir.c
index fab0b37..11e7cd4 100644
--- a/src/gallium/auxiliary/nir/tgsi_to_nir.c
+++ b/src/gallium/auxiliary/nir/tgsi_to_nir.c
@@ -1310,6 +1310,7 @@ ttn_tex(struct ttn_compile *c, nir_alu_dest dest, nir_ssa_def **src)
 
    assert(tgsi_inst->Src[samp].Register.File == TGSI_FILE_SAMPLER);
    instr->texture_index = tgsi_inst->Src[samp].Register.Index;
+   instr->sampler_index = tgsi_inst->Src[samp].Register.Index;
 
    /* TODO if we supported any opc's which take an explicit SVIEW
     * src, we would use that here instead.  But for the "legacy"
diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
index ecca3ef..1a2c39f 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
@@ -3024,6 +3024,9 @@ fs_visitor::nir_emit_texture(const fs_builder &bld, nir_tex_instr *instr)
          break;
       }
 
+      case nir_tex_src_sampler_offset:
+         break; /* Ignored for now */
+
       default:
          unreachable("unknown texture source");
       }
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
index a7d6e97..2200f3d 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
@@ -1738,6 +1738,9 @@ vec4_visitor::nir_emit_texture(nir_tex_instr *instr)
          break;
       }
 
+      case nir_tex_src_sampler_offset:
+         break; /* Ignored for now */
+
       case nir_tex_src_projector:
          unreachable("Should be lowered by do_lower_texture_projection");
 
diff --git a/src/mesa/program/prog_to_nir.c b/src/mesa/program/prog_to_nir.c
index d0092d0..f8659f6 100644
--- a/src/mesa/program/prog_to_nir.c
+++ b/src/mesa/program/prog_to_nir.c
@@ -610,6 +610,7 @@ ptn_tex(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src,
    instr->dest_type = nir_type_float;
    instr->is_shadow = prog_inst->TexShadow;
    instr->texture_index = prog_inst->TexSrcUnit;
+   instr->sampler_index = prog_inst->TexSrcUnit;
 
    switch (prog_inst->TexSrcTarget) {
    case TEXTURE_1D_INDEX:
-- 
2.5.0.400.gff86faf



More information about the mesa-dev mailing list