[Mesa-dev] [PATCH V3 4/5] i965 Gen4/5: clip: Add support for noperspective varyings

Paul Berry stereotype441 at gmail.com
Tue Jul 30 14:44:20 PDT 2013


On 14 July 2013 02:39, Chris Forbes <chrisf at ijw.co.nz> wrote:

> Adds support for interpolating noperspective varyings linearly in screen
> space when clipping.
>
> Based on Olivier Galibert's patch from last year:
> http://lists.freedesktop.org/archives/mesa-dev/2012-July/024341.html
>
> At this point all -fixed and -vertex interpolation tests work.
>
> [V1-2]: Signed-off-by: Olivier Galibert <galibert at pobox.com>
> Signed-off-by: Chris Forbes <chrisf at ijw.co.nz>
> ---
>  src/mesa/drivers/dri/i965/brw_clip.c      |   8 ++
>  src/mesa/drivers/dri/i965/brw_clip.h      |   1 +
>  src/mesa/drivers/dri/i965/brw_clip_util.c | 120
> +++++++++++++++++++++++++++---
>  3 files changed, 119 insertions(+), 10 deletions(-)
>
> diff --git a/src/mesa/drivers/dri/i965/brw_clip.c
> b/src/mesa/drivers/dri/i965/brw_clip.c
> index 7df4b18..6dd3759 100644
> --- a/src/mesa/drivers/dri/i965/brw_clip.c
> +++ b/src/mesa/drivers/dri/i965/brw_clip.c
> @@ -211,6 +211,14 @@ brw_upload_clip_prog(struct brw_context *brw)
>        }
>     }
>
> +   key.has_noperspective_shading = 0;
> +   for (i = 0; i < brw->vue_map_geom_out.num_slots; i++) {
> +      if (key.interpolation_mode[i] == INTERP_QUALIFIER_NOPERSPECTIVE) {
> +         key.has_noperspective_shading = 1;
> +         break;
> +      }
> +   }
> +
>

As with key.has_flat_shading, I'd prefer to see this moved to
compile_clip_prog() and brw_clip_compile.


>     key.pv_first = (ctx->Light.ProvokingVertex ==
> GL_FIRST_VERTEX_CONVENTION);
>     /* _NEW_TRANSFORM (also part of VUE map)*/
>     key.nr_userclip = _mesa_bitcount_64(ctx->Transform.ClipPlanesEnabled);
> diff --git a/src/mesa/drivers/dri/i965/brw_clip.h
> b/src/mesa/drivers/dri/i965/brw_clip.h
> index 656254b..90e3e33 100644
> --- a/src/mesa/drivers/dri/i965/brw_clip.h
> +++ b/src/mesa/drivers/dri/i965/brw_clip.h
> @@ -47,6 +47,7 @@ struct brw_clip_prog_key {
>     GLuint primitive:4;
>     GLuint nr_userclip:4;
>     GLuint has_flat_shading:1;
> +   GLuint has_noperspective_shading:1;
>     GLuint pv_first:1;
>     GLuint do_unfilled:1;
>     GLuint fill_cw:2;           /* includes cull information */
> diff --git a/src/mesa/drivers/dri/i965/brw_clip_util.c
> b/src/mesa/drivers/dri/i965/brw_clip_util.c
> index 8a21c1f..56c9ccd 100644
> --- a/src/mesa/drivers/dri/i965/brw_clip_util.c
> +++ b/src/mesa/drivers/dri/i965/brw_clip_util.c
> @@ -128,6 +128,8 @@ static void brw_clip_project_vertex( struct
> brw_clip_compile *c,
>
>  /* Interpolate between two vertices and put the result into a0.0.
>   * Increment a0.0 accordingly.
> + *
> + * Beware that dest_ptr can be equal to v0_ptr!
>   */
>  void brw_clip_interp_vertex( struct brw_clip_compile *c,
>                              struct brw_indirect dest_ptr,
> @@ -137,7 +139,7 @@ void brw_clip_interp_vertex( struct brw_clip_compile
> *c,
>                              bool force_edgeflag)
>  {
>     struct brw_compile *p = &c->func;
> -   struct brw_reg tmp = get_tmp(c);
> +   struct brw_reg t_nopersp, v0_ndc_copy;
>     GLuint slot;
>
>     /* Just copy the vertex header:
> @@ -148,12 +150,107 @@ void brw_clip_interp_vertex( struct
> brw_clip_compile *c,
>      */
>     brw_copy_indirect_to_indirect(p, dest_ptr, v0_ptr, 1);
>
> -   /* Iterate over each attribute (could be done in pairs?)
> +
> +   /* First handle the 3D and NDC interpolation, in case we
> +    * need noperspective interpolation. Doing it early has no
> +    * performance impact in any case.
> +    */
> +
> +   /* Take a copy of the v0 NDC coordinates, in case dest == v0. */
> +   if (c->key.has_noperspective_shading) {
> +      GLuint offset = brw_varying_to_offset(&c->vue_map,
> +                                                 BRW_VARYING_SLOT_NDC);
> +      v0_ndc_copy = get_tmp(c);
> +      brw_MOV(p, v0_ndc_copy, deref_4f(v0_ptr, offset));
> +   }
> +
> +   /* Compute the new 3D position
> +    *
> +    * dest_hpos = v0_hpos * (1 - t0) + v1_hpos * t0
> +    */
> +   {
> +      GLuint delta = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS);
> +      struct brw_reg tmp = get_tmp(c);
> +      brw_MUL(p, vec4(brw_null_reg()), deref_4f(v1_ptr, delta), t0);
> +      brw_MAC(p, tmp, negate(deref_4f(v0_ptr, delta)), t0);
> +      brw_ADD(p, deref_4f(dest_ptr, delta), deref_4f(v0_ptr, delta), tmp);
> +      release_tmp(c, tmp);
> +   }
> +
> +   /* Recreate the projected (NDC) coordinate in the new vertex header */
> +   brw_clip_project_vertex(c, dest_ptr);
> +
> +   /* If we have noperspective attributes,
> +    * we need to compute the screen-space t
> +    */
> +   if (c->key.has_noperspective_shading) {
> +      GLuint delta = brw_varying_to_offset(&c->vue_map,
> +                                                BRW_VARYING_SLOT_NDC);
> +      struct brw_reg tmp = get_tmp(c);
> +      t_nopersp = get_tmp(c);
> +
> +      /* t_nopersp = vec4(v1.xy, dest.xy) */
> +      brw_MOV(p, t_nopersp, deref_4f(v1_ptr, delta));
> +      brw_MOV(p, tmp, deref_4f(dest_ptr, delta));
> +      brw_set_access_mode(p, BRW_ALIGN_16);
> +      brw_MOV(p,
> +              brw_writemask(t_nopersp, WRITEMASK_ZW),
> +              brw_swizzle(tmp, 0, 1, 0, 1));
> +
> +      /* t_nopersp = vec4(v1.xy, dest.xy) - v0.xyxy */
> +      brw_ADD(p, t_nopersp, t_nopersp,
> +              negate(brw_swizzle(v0_ndc_copy, 0, 1, 0, 1)));
> +
> +      /* Add the absolute values of the X and Y deltas so that if
> +       * the points aren't in the same place on the screen we get
> +       * nonzero values to divide.
> +       *
> +       * After that, we have vert1 - vert0 in t_nopersp.x and
> +       * vertnew - vert0 in t_nopersp.y
> +       *
> +       * t_nopersp = vec2(|v1.x  -v0.x| + |v1.y  -v0.y|,
> +       *                  |dest.x-v0.x| + |dest.y-v0.y|)
> +       */
> +      brw_ADD(p,
> +              brw_writemask(t_nopersp, WRITEMASK_XY),
> +              brw_abs(brw_swizzle(t_nopersp, 0, 2, 0, 0)),
> +              brw_abs(brw_swizzle(t_nopersp, 1, 3, 0, 0)));
> +      brw_set_access_mode(p, BRW_ALIGN_1);
> +
> +      /* If the points are in the same place, just substitute a
> +       * value to avoid divide-by-zero
> +       */
> +      brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ,
> +              vec1(t_nopersp),
> +              brw_imm_f(0));
> +      brw_IF(p, BRW_EXECUTE_1);
> +      brw_MOV(p, t_nopersp, brw_imm_vf4(VF_ONE, VF_ZERO, VF_ZERO,
> VF_ZERO));
> +      brw_ENDIF(p);
> +
> +      /* Now compute t_nopersp = t_nopersp.y/t_nopersp.x and broadcast
> it. */
> +      brw_math_invert(p, get_element(t_nopersp, 0),
> get_element(t_nopersp, 0));
> +      brw_MUL(p, vec1(t_nopersp), vec1(t_nopersp),
> +            vec1(suboffset(t_nopersp, 1)));
> +      brw_set_access_mode(p, BRW_ALIGN_16);
> +      brw_MOV(p, t_nopersp, brw_swizzle(t_nopersp, 0, 0, 0, 0));
> +      brw_set_access_mode(p, BRW_ALIGN_1);
> +
> +      release_tmp(c, tmp);
> +      release_tmp(c, v0_ndc_copy);
> +   }
>

I haven't had a chance to work through all the math above, but I trust that
the piglit tests are adequate, so for this I'm just going to say

Acked-by: Paul Berry <stereotype441 at gmail.com>


> +
> +   /* Now we can iterate over each attribute
> +    * (could be done in pairs?)
>      */
>     for (slot = 0; slot < c->vue_map.num_slots; slot++) {
>        int varying = c->vue_map.slot_to_varying[slot];
>        GLuint delta = brw_vue_slot_to_offset(slot);
>
> +      /* HPOS is already handled above */
> +      if (varying == VARYING_SLOT_POS)
> +         continue;
> +
> +
>        if (varying == VARYING_SLOT_EDGE) {
>          if (force_edgeflag)
>             brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(1));
> @@ -173,20 +270,27 @@ void brw_clip_interp_vertex( struct brw_clip_compile
> *c,
>           *
>           *        New = attr0 + t*attr1 - t*attr0
>           */
> +         struct brw_reg tmp = get_tmp(c);
> +         struct brw_reg t =
> +            c->key.interpolation_mode[slot] ==
> INTERP_QUALIFIER_NOPERSPECTIVE ?
> +            t_nopersp : t0;
> +
>          brw_MUL(p,
>                  vec4(brw_null_reg()),
>                  deref_4f(v1_ptr, delta),
> -                t0);
> +                t);
>
>          brw_MAC(p,
>                  tmp,
>                  negate(deref_4f(v0_ptr, delta)),
> -                t0);
> +                t);
>
>          brw_ADD(p,
>                  deref_4f(dest_ptr, delta),
>                  deref_4f(v0_ptr, delta),
>                  tmp);
> +
> +         release_tmp(c, tmp);
>        }
>     }
>
> @@ -196,12 +300,8 @@ void brw_clip_interp_vertex( struct brw_clip_compile
> *c,
>        brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(0));
>     }
>
> -   release_tmp(c, tmp);
> -
> -   /* Recreate the projected (NDC) coordinate in the new vertex
> -    * header:
> -    */
> -   brw_clip_project_vertex(c, dest_ptr );
> +   if (c->key.has_noperspective_shading)
> +      release_tmp(c, t_nopersp);
>  }
>
>  void brw_clip_emit_vue(struct brw_clip_compile *c,
> --
> 1.8.3.2
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20130730/206db565/attachment-0001.html>


More information about the mesa-dev mailing list