nir/lower_tex: Add lowering for some min_lod cases
authorJason Ekstrand <jason.ekstrand@intel.com>
Thu, 11 Oct 2018 19:14:29 +0000 (14:14 -0500)
committerJason Ekstrand <jason.ekstrand@intel.com>
Wed, 12 Dec 2018 03:26:23 +0000 (21:26 -0600)
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
src/compiler/nir/nir.h
src/compiler/nir/nir_lower_tex.c

index 376211d5e74db8ff88a25b852b0274e3767ffab1..5d9c96fe11e693e623a9ef2b750ed2fb303709c2 100644 (file)
@@ -3013,6 +3013,24 @@ typedef struct nir_lower_tex_options {
     * Implies lower_txd_cube_map and lower_txd_shadow.
     */
    bool lower_txd;
+
+   /**
+    * If true, lower nir_texop_txb that try to use shadow compare and min_lod
+    * at the same time to a nir_texop_lod, some math, and nir_texop_tex.
+    */
+   bool lower_txb_shadow_clamp;
+
+   /**
+    * If true, lower nir_texop_txd on shadow samplers when it uses min_lod
+    * with nir_texop_txl.  This includes cube maps.
+    */
+   bool lower_txd_shadow_clamp;
+
+   /**
+    * If true, lower nir_texop_txd on when it uses both offset and min_lod
+    * with nir_texop_txl.  This includes cube maps.
+    */
+   bool lower_txd_offset_clamp;
 } nir_lower_tex_options;
 
 bool nir_lower_tex(nir_shader *shader,
index cd93c4f174908be748c571d49a351fb1d6c2df36..6a6b6c41a7ba37f68a18a677695f8f8a040fd097 100644 (file)
@@ -150,6 +150,54 @@ get_texture_size(nir_builder *b, nir_tex_instr *tex)
    return nir_i2f32(b, &txs->dest.ssa);
 }
 
+static nir_ssa_def *
+get_texture_lod(nir_builder *b, nir_tex_instr *tex)
+{
+   b->cursor = nir_before_instr(&tex->instr);
+
+   nir_tex_instr *tql;
+
+   unsigned num_srcs = 0;
+   for (unsigned i = 0; i < tex->num_srcs; i++) {
+      if (tex->src[i].src_type == nir_tex_src_coord ||
+          tex->src[i].src_type == nir_tex_src_texture_deref ||
+          tex->src[i].src_type == nir_tex_src_sampler_deref ||
+          tex->src[i].src_type == nir_tex_src_texture_offset ||
+          tex->src[i].src_type == nir_tex_src_sampler_offset)
+         num_srcs++;
+   }
+
+   tql = nir_tex_instr_create(b->shader, num_srcs);
+   tql->op = nir_texop_lod;
+   tql->coord_components = tex->coord_components;
+   tql->sampler_dim = tex->sampler_dim;
+   tql->is_array = tex->is_array;
+   tql->is_shadow = tex->is_shadow;
+   tql->is_new_style_shadow = tex->is_new_style_shadow;
+   tql->texture_index = tex->texture_index;
+   tql->sampler_index = tex->sampler_index;
+   tql->dest_type = nir_type_float;
+
+   unsigned idx = 0;
+   for (unsigned i = 0; i < tex->num_srcs; i++) {
+      if (tex->src[i].src_type == nir_tex_src_coord ||
+          tex->src[i].src_type == nir_tex_src_texture_deref ||
+          tex->src[i].src_type == nir_tex_src_sampler_deref ||
+          tex->src[i].src_type == nir_tex_src_texture_offset ||
+          tex->src[i].src_type == nir_tex_src_sampler_offset) {
+         nir_src_copy(&tql->src[idx].src, &tex->src[i].src, tql);
+         tql->src[idx].src_type = tex->src[i].src_type;
+         idx++;
+      }
+   }
+
+   nir_ssa_dest_init(&tql->instr, &tql->dest, 2, 32, NULL);
+   nir_builder_instr_insert(b, &tql->instr);
+
+   /* The LOD is the y component of the result */
+   return nir_channel(b, &tql->dest.ssa, 1);
+}
+
 static bool
 lower_offset(nir_builder *b, nir_tex_instr *tex)
 {
@@ -227,6 +275,36 @@ lower_rect(nir_builder *b, nir_tex_instr *tex)
    tex->sampler_dim = GLSL_SAMPLER_DIM_2D;
 }
 
+static void
+lower_implicit_lod(nir_builder *b, nir_tex_instr *tex)
+{
+   assert(tex->op == nir_texop_tex || tex->op == nir_texop_txb);
+   assert(nir_tex_instr_src_index(tex, nir_tex_src_lod) < 0);
+   assert(nir_tex_instr_src_index(tex, nir_tex_src_ddx) < 0);
+   assert(nir_tex_instr_src_index(tex, nir_tex_src_ddy) < 0);
+
+   b->cursor = nir_before_instr(&tex->instr);
+
+   nir_ssa_def *lod = get_texture_lod(b, tex);
+
+   int bias_idx = nir_tex_instr_src_index(tex, nir_tex_src_bias);
+   if (bias_idx >= 0) {
+      /* If we have a bias, add it in */
+      lod = nir_fadd(b, lod, nir_ssa_for_src(b, tex->src[bias_idx].src, 1));
+      nir_tex_instr_remove_src(tex, bias_idx);
+   }
+
+   int min_lod_idx = nir_tex_instr_src_index(tex, nir_tex_src_min_lod);
+   if (min_lod_idx >= 0) {
+      /* If we have a minimum LOD, clamp LOD accordingly */
+      lod = nir_fmax(b, lod, nir_ssa_for_src(b, tex->src[min_lod_idx].src, 1));
+      nir_tex_instr_remove_src(tex, min_lod_idx);
+   }
+
+   nir_tex_instr_add_src(tex, nir_tex_src_lod, nir_src_for_ssa(lod));
+   tex->op = nir_texop_txl;
+}
+
 static nir_ssa_def *
 sample_plane(nir_builder *b, nir_tex_instr *tex, int plane)
 {
@@ -374,6 +452,13 @@ replace_gradient_with_lod(nir_builder *b, nir_ssa_def *lod, nir_tex_instr *tex)
    nir_tex_instr_remove_src(tex, nir_tex_instr_src_index(tex, nir_tex_src_ddx));
    nir_tex_instr_remove_src(tex, nir_tex_instr_src_index(tex, nir_tex_src_ddy));
 
+   int min_lod_idx = nir_tex_instr_src_index(tex, nir_tex_src_min_lod);
+   if (min_lod_idx >= 0) {
+      /* If we have a minimum LOD, clamp LOD accordingly */
+      lod = nir_fmax(b, lod, nir_ssa_for_src(b, tex->src[min_lod_idx].src, 1));
+      nir_tex_instr_remove_src(tex, min_lod_idx);
+   }
+
    nir_tex_instr_add_src(tex, nir_tex_src_lod, nir_src_for_ssa(lod));
    tex->op = nir_texop_txl;
 }
@@ -803,9 +888,22 @@ nir_lower_tex_block(nir_block *block, nir_builder *b,
          progress = true;
       }
 
+      const bool has_min_lod =
+         nir_tex_instr_src_index(tex, nir_tex_src_min_lod) >= 0;
+      const bool has_offset =
+         nir_tex_instr_src_index(tex, nir_tex_src_offset) >= 0;
+
+      if (tex->op == nir_texop_txb && tex->is_shadow && has_min_lod &&
+          options->lower_txb_shadow_clamp) {
+         lower_implicit_lod(b, tex);
+         progress = true;
+      }
+
       if (tex->op == nir_texop_txd &&
           (options->lower_txd ||
            (options->lower_txd_shadow && tex->is_shadow) ||
+           (options->lower_txd_shadow_clamp && tex->is_shadow && has_min_lod) ||
+           (options->lower_txd_offset_clamp && has_offset && has_min_lod) ||
            (options->lower_txd_cube_map &&
             tex->sampler_dim == GLSL_SAMPLER_DIM_CUBE))) {
          lower_gradient(b, tex);