diff options
author | Iago Toral Quiroga <[email protected]> | 2016-11-30 11:31:01 +0100 |
---|---|---|
committer | Iago Toral Quiroga <[email protected]> | 2016-12-13 10:32:52 +0100 |
commit | 5be2e785b1df2160424eb73e53cca340e0130020 (patch) | |
tree | 9f3766b1975786ebbb3b0529099de34be499784e /src/compiler/nir/nir_lower_tex.c | |
parent | f90da64fc65d8da99a5a5a140be7b64c8cf5ee6a (diff) |
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 <[email protected]> (v3)
Diffstat (limited to 'src/compiler/nir/nir_lower_tex.c')
-rw-r--r-- | src/compiler/nir/nir_lower_tex.c | 60 |
1 files changed, 60 insertions, 0 deletions
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; |