[Mesa-dev] [PATCH 5/6] nir/lower_tex: add support to clamp texture coords

Kenneth Graunke kenneth at whitecape.org
Fri Sep 18 11:03:20 PDT 2015


On Friday, September 18, 2015 12:24:37 PM Rob Clark wrote:
> On Fri, Sep 18, 2015 at 11:55 AM, Kenneth Graunke <kenneth at whitecape.org> wrote:
> > On Friday, September 18, 2015 10:55:08 AM Rob Clark wrote:
> >> From: Rob Clark <robclark at freedesktop.org>
> >>
> >> Some hardware needs to clamp texture coordinates to [0.0, 1.0] in the
> >> shader to emulate GL_CLAMP.  This is added to lower_tex_proj since, in
> >> the case of projected coords, the clamping needs to happen *after*
> >> projection.
> >>
> >> v2: comments/suggestions from Ilia and Eric, use txs to get texture size
> >> and clamp RECT textures to their dimensions rather than [0.0, 1.0] to
> >> avoid having to lower RECT textures to 2D.
> >>
> >> Signed-off-by: Rob Clark <robclark at freedesktop.org>
> >> ---
> >>  src/glsl/nir/nir.h           | 18 ++++++++++
> >>  src/glsl/nir/nir_lower_tex.c | 86 +++++++++++++++++++++++++++++++++++++++++++-
> >>  2 files changed, 103 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/src/glsl/nir/nir.h b/src/glsl/nir/nir.h
> >> index 3c908b9..255d455 100644
> >> --- a/src/glsl/nir/nir.h
> >> +++ b/src/glsl/nir/nir.h
> >> @@ -1850,6 +1850,24 @@ typedef struct nir_lower_tex_options {
> >>      * texture dims to normalize.
> >>      */
> >>     bool lower_rect;
> >> +
> >> +   /**
> >> +    * To emulate certain texture wrap modes, this can be used
> >> +    * to saturate the specified tex coord to [0.0, 1.0].  The
> >> +    * bits are according to sampler #, ie. if, for example:
> >> +    *
> >> +    *   (conf->saturate_s & (1 << n))
> >> +    *
> >> +    * is true, then the s coord for sampler n is saturated.
> >> +    *
> >> +    * Note that clamping must happen *after* projector lowering
> >> +    * so any projected texture sample instruction with a clamped
> >> +    * coordinate gets automatically lowered, regardless of the
> >> +    * 'lower_txp' setting.
> >> +    */
> >> +   unsigned saturate_s;
> >> +   unsigned saturate_t;
> >> +   unsigned saturate_r;
> >>  } nir_lower_tex_options;
> >>
> >>  void nir_lower_tex(nir_shader *shader,
> >> diff --git a/src/glsl/nir/nir_lower_tex.c b/src/glsl/nir/nir_lower_tex.c
> >> index a71a5c5..7c7a077 100644
> >> --- a/src/glsl/nir/nir_lower_tex.c
> >> +++ b/src/glsl/nir/nir_lower_tex.c
> >> @@ -29,6 +29,10 @@
> >>   *     asking the texture operation to do so.
> >>   *   + lowering RECT: converts the un-normalized RECT texture coordinates
> >>   *     to normalized coordinates with txs plus ALU instructions
> >> + *   + saturate s/t/r coords: to emulate certain texture clamp/wrap modes,
> >> + *     inserts instructions to clamp specified coordinates to [0.0, 1.0].
> >> + *     Note that this automatically triggers texture projector lowering if
> >> + *     needed, since clamping must happen after projector lowering.
> >>   */
> >>
> >>  #include "nir.h"
> >> @@ -164,6 +168,70 @@ lower_rect(nir_builder *b, nir_tex_instr *tex)
> >>     tex->sampler_dim = GLSL_SAMPLER_DIM_2D;
> >>  }
> >>
> >> +static void
> >> +saturate_src(nir_builder *b, nir_tex_instr *tex, unsigned sat_mask)
> >> +{
> >> +   b->cursor = nir_before_instr(&tex->instr);
> >> +
> >> +   /* Walk through the sources saturating the requested arguments. */
> >> +   for (unsigned i = 0; i < tex->num_srcs; i++) {
> >> +      if (tex->src[i].src_type != nir_tex_src_coord)
> >> +         continue;
> >> +
> >> +      nir_ssa_def *src =
> >> +         nir_ssa_for_src(b, tex->src[i].src, tex->coord_components);
> >> +
> >> +      /* split src into components: */
> >> +      nir_ssa_def *comp[4];
> >> +
> >> +      for (unsigned j = 0; j < tex->coord_components; j++)
> >> +         comp[j] = nir_channel(b, src, j);
> >> +
> >> +      /* clamp requested components, array index does not get clamped: */
> >> +      unsigned ncomp = tex->coord_components;
> >> +      if (tex->is_array)
> >> +         ncomp--;
> >> +
> >> +      for (unsigned j = 0; j < ncomp; j++) {
> >> +         if ((1 << j) & sat_mask) {
> >> +            if (tex->sampler_dim == GLSL_SAMPLER_DIM_RECT) {
> >> +               /* non-normalized texture coords, so clamp to texture
> >> +                * size rather than [0.0, 1.0]
> >> +                */
> >> +               nir_ssa_def *txs = get_texture_size(b, tex);
> >> +               comp[j] = nir_fmax(b, comp[j], nir_imm_float(b, 0.0));
> >> +               comp[j] = nir_fmin(b, comp[j], nir_channel(b, txs, j));
> >> +            } else {
> >> +               comp[j] = nir_fsat(b, comp[j]);
> >> +            }
> >> +         }
> >> +      }
> >
> > You might be able to do this with vector operations instead of
> > scalarizing...but I'm not sure if it would actually be better.  *shrug*
> 
> the problem is that sat_mask might not have all bits set.. I suppose
> with a bit more logic I could handle the case that all components are
> clamped, but I think everyone is converting to scalar (and then
> possibly converting back), so I wasn't really thinking that it was
> worth the extra logic..

Good point...I'd forgotten to consider that when making the comment.
Nevermind, your current code is fine :)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20150918/39a60838/attachment.sig>


More information about the mesa-dev mailing list