summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/compiler/nir/nir.h7
-rw-r--r--src/compiler/nir/nir_lower_tex.c60
2 files changed, 67 insertions, 0 deletions
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index 826410d5ac3..ba88a249ae8 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 11773cbee57..91aa9e17431 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;