nir/lower_tex: Add support for lowering coordinate offsets
authorJason Ekstrand <jason.ekstrand@intel.com>
Thu, 21 Jul 2016 03:32:31 +0000 (20:32 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Fri, 22 Jul 2016 23:48:53 +0000 (16:48 -0700)
On i965, we can't support coordinate offsets for texelFetch or rectangle
textures.  Previously, we were doing this with a GLSL pass but we need to
do it in NIR if we want those workarounds for SPIR-V.

Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Cc: "12.0" <mesa-dev@lists.freedesktop.org>
src/compiler/nir/nir.h
src/compiler/nir/nir_lower_tex.c

index 5a69e7858d4a3b2bfeeff8844cceee8e535f6daf..f23d0b256a85268b94d187cf465f0b08cd64a420 100644 (file)
@@ -2408,6 +2408,16 @@ typedef struct nir_lower_tex_options {
     */
    unsigned lower_txp;
 
+   /**
+    * If true, lower away nir_tex_src_offset for all texelfetch instructions.
+    */
+   bool lower_txf_offset;
+
+   /**
+    * If true, lower away nir_tex_src_offset for all rect textures.
+    */
+   bool lower_rect_offset;
+
    /**
     * If true, lower rect textures to 2D, using txs to fetch the
     * texture dimensions and dividing the texture coords by the
index e70a9aa7693f338fad8598477fd90e3fc04e0043..93637a33844556ba3f1f46f3f4792244dc4f0bf5 100644 (file)
@@ -128,6 +128,54 @@ project_src(nir_builder *b, nir_tex_instr *tex)
    tex_instr_remove_src(tex, proj_index);
 }
 
+static bool
+lower_offset(nir_builder *b, nir_tex_instr *tex)
+{
+   int offset_index = tex_instr_find_src(tex, nir_tex_src_offset);
+   if (offset_index < 0)
+      return false;
+
+   int coord_index = tex_instr_find_src(tex, nir_tex_src_coord);
+   assert(coord_index >= 0);
+
+   assert(tex->src[offset_index].src.is_ssa);
+   assert(tex->src[coord_index].src.is_ssa);
+   nir_ssa_def *offset = tex->src[offset_index].src.ssa;
+   nir_ssa_def *coord = tex->src[coord_index].src.ssa;
+
+   b->cursor = nir_before_instr(&tex->instr);
+
+   nir_ssa_def *offset_coord;
+   if (nir_tex_instr_src_type(tex, coord_index) == nir_type_float) {
+      assert(tex->sampler_dim == GLSL_SAMPLER_DIM_RECT);
+      offset_coord = nir_fadd(b, coord, nir_i2f(b, offset));
+   } else {
+      offset_coord = nir_iadd(b, coord, offset);
+   }
+
+   if (tex->is_array) {
+      /* The offset is not applied to the array index */
+      if (tex->coord_components == 2) {
+         offset_coord = nir_vec2(b, nir_channel(b, offset_coord, 0),
+                                    nir_channel(b, coord, 1));
+      } else if (tex->coord_components == 3) {
+         offset_coord = nir_vec3(b, nir_channel(b, offset_coord, 0),
+                                    nir_channel(b, offset_coord, 1),
+                                    nir_channel(b, coord, 2));
+      } else {
+         unreachable("Invalid number of components");
+      }
+   }
+
+   nir_instr_rewrite_src(&tex->instr, &tex->src[coord_index].src,
+                         nir_src_for_ssa(offset_coord));
+
+   tex_instr_remove_src(tex, offset_index);
+
+   return true;
+}
+
+
 static nir_ssa_def *
 get_texture_size(nir_builder *b, nir_tex_instr *tex)
 {
@@ -458,6 +506,12 @@ nir_lower_tex_block(nir_block *block, nir_builder *b,
          progress = true;
       }
 
+      if ((tex->op == nir_texop_txf && options->lower_txf_offset) ||
+          (tex->sampler_dim == GLSL_SAMPLER_DIM_RECT &&
+           options->lower_rect_offset)) {
+         progress = lower_offset(b, tex) || progress;
+      }
+
       if ((tex->sampler_dim == GLSL_SAMPLER_DIM_RECT) && options->lower_rect) {
          lower_rect(b, tex);
          progress = true;