Mesa (master): nir/lower_tex: add lowering for texture gradient on shadow samplers

Iago Toral Quiroga itoral at kemper.freedesktop.org
Tue Dec 13 10:09:54 UTC 2016


Module: Mesa
Branch: master
Commit: 5be2e785b1df2160424eb73e53cca340e0130020
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=5be2e785b1df2160424eb73e53cca340e0130020

Author: Iago Toral Quiroga <itoral at igalia.com>
Date:   Wed Nov 30 11:31:01 2016 +0100

nir/lower_tex: add lowering for texture gradient on shadow samplers

This is ported from the Intel lowering pass that we use with GLSL IR.
This takes care of lowering texture gradients on shadow samplers other
than cube maps. Intel hardware requires this for gen < 8.

v2 (Ken):
 - Use the helper function to retrieve ddx/ddy
 - Swizzle away size components we are not interested in

v3:
- Get rid of the ddx/ddy helper and use nir_tex_instr_src_index
  instead (Ken, Eric)

v4:
- Add a 'continue' statement if the lowering makes progress because it
  replaces the original texture instruction

Reviewed-by: Kenneth Graunke <kenneth at whitecape.org> (v3)

---

 src/compiler/nir/nir.h           |  7 +++++
 src/compiler/nir/nir_lower_tex.c | 60 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 67 insertions(+)

diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index 826410d..ba88a24 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -2399,6 +2399,13 @@ typedef struct nir_lower_tex_options {
     * If true, lower nir_texop_txd on cube maps with nir_texop_txl.
     */
    bool lower_txd_cube_map;
+
+   /**
+    * If true, lower nir_texop_txd on shadow samplers (except cube maps)
+    * with nir_texop_txl. Notice that cube map shadow samplers are lowered
+    * with lower_txd_cube_map.
+    */
+   bool lower_txd_shadow;
 } nir_lower_tex_options;
 
 bool nir_lower_tex(nir_shader *shader,
diff --git a/src/compiler/nir/nir_lower_tex.c b/src/compiler/nir/nir_lower_tex.c
index 11773cb..91aa9e1 100644
--- a/src/compiler/nir/nir_lower_tex.c
+++ b/src/compiler/nir/nir_lower_tex.c
@@ -506,6 +506,59 @@ lower_gradient_cube_map(nir_builder *b, nir_tex_instr *tex)
 }
 
 static void
+lower_gradient_shadow(nir_builder *b, nir_tex_instr *tex)
+{
+   assert(tex->sampler_dim != GLSL_SAMPLER_DIM_CUBE);
+   assert(tex->is_shadow);
+   assert(tex->op == nir_texop_txd);
+   assert(tex->dest.is_ssa);
+
+   /* Use textureSize() to get the width and height of LOD 0 */
+   unsigned component_mask;
+   switch (tex->sampler_dim) {
+   case GLSL_SAMPLER_DIM_3D:
+      component_mask = 7;
+      break;
+   case GLSL_SAMPLER_DIM_1D:
+      component_mask = 1;
+      break;
+   default:
+      component_mask = 3;
+      break;
+   }
+
+   nir_ssa_def *size =
+      nir_channels(b, get_texture_size(b, tex), component_mask);
+
+   /* Scale the gradients by width and height.  Effectively, the incoming
+    * gradients are s'(x,y), t'(x,y), and r'(x,y) from equation 3.19 in the
+    * GL 3.0 spec; we want u'(x,y), which is w_t * s'(x,y).
+    */
+   nir_ssa_def *ddx =
+      tex->src[nir_tex_instr_src_index(tex, nir_tex_src_ddx)].src.ssa;
+   nir_ssa_def *ddy =
+      tex->src[nir_tex_instr_src_index(tex, nir_tex_src_ddy)].src.ssa;
+
+   nir_ssa_def *dPdx = nir_fmul(b, ddx, size);
+   nir_ssa_def *dPdy = nir_fmul(b, ddy, size);
+
+   nir_ssa_def *rho;
+   if (dPdx->num_components == 1) {
+      rho = nir_fmax(b, nir_fabs(b, dPdx), nir_fabs(b, dPdy));
+   } else {
+      rho = nir_fmax(b,
+                     nir_fsqrt(b, nir_fdot(b, dPdx, dPdx)),
+                     nir_fsqrt(b, nir_fdot(b, dPdy, dPdy)));
+   }
+
+   /* lod = log2(rho).  We're ignoring GL state biases for now. */
+   nir_ssa_def *lod = nir_flog2(b, rho);
+
+   /* Replace the gradient instruction with an equivalent lod instruction */
+   replace_gradient_with_lod(b, lod, tex);
+}
+
+static void
 saturate_src(nir_builder *b, nir_tex_instr *tex, unsigned sat_mask)
 {
    b->cursor = nir_before_instr(&tex->instr);
@@ -737,6 +790,13 @@ nir_lower_tex_block(nir_block *block, nir_builder *b,
          progress = true;
          continue;
       }
+
+      if (tex->op == nir_texop_txd && options->lower_txd_shadow &&
+          tex->is_shadow && tex->sampler_dim != GLSL_SAMPLER_DIM_CUBE) {
+         lower_gradient_shadow(b, tex);
+         progress = true;
+         continue;
+      }
    }
 
    return progress;




More information about the mesa-commit mailing list