[Mesa-dev] [PATCH 4/4] softpipe: clipdistance support (v1)

Brian Paul brianp at vmware.com
Tue Jan 10 07:53:00 PST 2012


The check-in message should probably be "draw: clipdistance support 
(v1)", not "softpipe".


On 01/10/2012 06:55 AM, Dave Airlie wrote:
> From: Dave Airlie<airlied at redhat.com>
>
> Add support for using the clipdistance instead of clip plane.
>
> Passes all piglit clipdistance tests.
>
> Signed-off-by: Dave Airlie<airlied at redhat.com>
> ---
>   src/gallium/auxiliary/draw/draw_cliptest_tmp.h |   25 ++++++++++++++--
>   src/gallium/auxiliary/draw/draw_context.c      |    6 ++++
>   src/gallium/auxiliary/draw/draw_pipe_clip.c    |   36 ++++++++++++++++++------
>   src/gallium/auxiliary/draw/draw_private.h      |    5 ++-
>   src/gallium/auxiliary/draw/draw_pt_post_vs.c   |    4 +-
>   src/gallium/auxiliary/draw/draw_vs.c           |    7 ++++
>   src/gallium/auxiliary/draw/draw_vs.h           |    2 +-
>   7 files changed, 68 insertions(+), 17 deletions(-)
>
> diff --git a/src/gallium/auxiliary/draw/draw_cliptest_tmp.h b/src/gallium/auxiliary/draw/draw_cliptest_tmp.h
> index 7dba49b..438d2d8 100644
> --- a/src/gallium/auxiliary/draw/draw_cliptest_tmp.h
> +++ b/src/gallium/auxiliary/draw/draw_cliptest_tmp.h
> @@ -36,12 +36,19 @@ static boolean TAG(do_cliptest)( struct pt_post_vs *pvs,
>      /* const */ float (*plane)[4] = pvs->draw->plane;
>      const unsigned pos = draw_current_shader_position_output(pvs->draw);
>      const unsigned cv = draw_current_shader_clipvertex_output(pvs->draw);
> +   unsigned cd[2];
>      const unsigned ef = pvs->draw->vs.edgeflag_output;
>      const unsigned ucp_enable = pvs->draw->rasterizer->clip_plane_enable;
>      const unsigned flags = (FLAGS);
>      unsigned need_pipeline = 0;
>      unsigned j;
>      unsigned i;
> +   bool have_cd = false;
> +   cd[0] = draw_current_shader_clipdistance_output(pvs->draw, 0);
> +   cd[1] = draw_current_shader_clipdistance_output(pvs->draw, 1);
> +
> +   if (cd[0] != pos || cd[1] != pos)
> +     have_cd = true;
>
>      for (j = 0; j<  info->count; j++) {
>         float *position = out->data[pos];
> @@ -89,14 +96,26 @@ static boolean TAG(do_cliptest)( struct pt_post_vs *pvs,
>
>            if (flags&  DO_CLIP_USER) {
>               unsigned ucp_mask = ucp_enable;
> -
> +            int num_clipdistance = pvs->draw->vs.vertex_shader->info.num_clipdistance;
>               while (ucp_mask) {
>                  unsigned plane_idx = ffs(ucp_mask)-1;
> +               float clipval;
>                  ucp_mask&= ~(1<<  plane_idx);
>                  plane_idx += 6;
>
> -               if (dot4(clipvertex, plane[plane_idx])<  0) {
> -                  mask |= 1<<  plane_idx;

Could you add some comments on the following code?  Maybe it's just 
me, but I think it's a bit hard to follow.


> +               if (have_cd&&  num_clipdistance) {
> +                  i = plane_idx - 6;
> +                  out->have_clipdist = 1;
> +                  if (i<  4)
> +                     clipval = out->data[cd[0]][i];
> +                  else
> +                     clipval = out->data[cd[1]][i-4];
> +                  if (clipval<  0)
> +                     mask |= (1<<  plane_idx);
> +               } else {
> +                  if (dot4(clipvertex, plane[plane_idx])<  0) {
> +                     mask |= 1<<  plane_idx;
> +                  }
>                  }
>               }
>            }
> diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
> index 6d7075e..7e554dc 100644
> --- a/src/gallium/auxiliary/draw/draw_context.c
> +++ b/src/gallium/auxiliary/draw/draw_context.c
> @@ -701,6 +701,12 @@ draw_current_shader_clipvertex_output(const struct draw_context *draw)
>      return draw->vs.clipvertex_output;
>   }
>
> +uint
> +draw_current_shader_clipdistance_output(const struct draw_context *draw, int index)
> +{
> +   return draw->vs.clipdistance_output[index];
> +}
> +
>   /**
>    * Return a pointer/handle for a driver/CSO rasterizer object which
>    * disabled culling, stippling, unfilled tris, etc.
> diff --git a/src/gallium/auxiliary/draw/draw_pipe_clip.c b/src/gallium/auxiliary/draw/draw_pipe_clip.c
> index fbc8f67..265b755 100644
> --- a/src/gallium/auxiliary/draw/draw_pipe_clip.c
> +++ b/src/gallium/auxiliary/draw/draw_pipe_clip.c
> @@ -119,13 +119,17 @@ static void interp( const struct clip_stage *clip,
>      const unsigned nr_attrs = draw_current_shader_outputs(clip->stage.draw);
>      const unsigned pos_attr = draw_current_shader_position_output(clip->stage.draw);
>      const unsigned clip_attr = draw_current_shader_clipvertex_output(clip->stage.draw);
> +   unsigned clip_dist[2];
>      unsigned j;
>
> +   clip_dist[0] = draw_current_shader_clipdistance_output(clip->stage.draw, 0);
> +   clip_dist[1] = draw_current_shader_clipdistance_output(clip->stage.draw, 1);
> +
>      /* Vertex header.
>       */
>      dst->clipmask = 0;
>      dst->edgeflag = 0;        /* will get overwritten later */
> -   dst->pad = 0;
> +   dst->have_clipdist = in->have_clipdist;
>      dst->vertex_id = UNDEFINED_VERTEX_ID;
>
>      /* Interpolate the clip-space coords.
> @@ -241,6 +245,23 @@ dot4(const float *a, const float *b)
>              a[3] * b[3]);
>   }
>


Comments on this function would be helpful too.  And we're still using 
INLINE in the gallium code.


> +static inline float getclipdist(const struct clip_stage *clipper,
> +                                struct vertex_header *vert,
> +                                int plane_idx)
> +{
> +   const float *plane;
> +   float dp;
> +   if (vert->have_clipdist&&  plane_idx>= 6) {
> +      int _idx = plane_idx - 6;
> +      int cdi = _idx>= 4;
> +      int vidx = cdi ? _idx - 4 : _idx;
> +      dp = vert->data[draw_current_shader_clipdistance_output(clipper->stage.draw, cdi)][vidx];
> +   } else {
> +      plane = clipper->plane[plane_idx];
> +      dp = dot4(vert->clip, plane);
> +   }
> +   return dp;
> +}
>
>   /* Clip a triangle against the viewport and user clip planes.
>    */
> @@ -281,12 +302,12 @@ do_clip_tri( struct draw_stage *stage,
>      while (clipmask&&  n>= 3) {
>         const unsigned plane_idx = ffs(clipmask)-1;
>         const boolean is_user_clip_plane = plane_idx>= 6;
> -      const float *plane = clipper->plane[plane_idx];
>         struct vertex_header *vert_prev = inlist[0];
>         boolean *edge_prev =&inEdges[0];
> -      float dp_prev = dot4( vert_prev->clip, plane );
> +      float dp_prev;
>         unsigned outcount = 0;
>
> +      dp_prev = getclipdist(clipper, vert_prev, plane_idx);
>         clipmask&= ~(1<<plane_idx);
>
>         assert(n<  MAX_CLIPPED_VERTICES);
> @@ -299,7 +320,7 @@ do_clip_tri( struct draw_stage *stage,
>   	 struct vertex_header *vert = inlist[i];
>            boolean *edge =&inEdges[i];
>
> -	 float dp = dot4( vert->clip, plane );
> +         float dp = getclipdist(clipper, vert, plane_idx);
>
>   	 if (!IS_NEGATIVE(dp_prev)) {
>               assert(outcount<  MAX_CLIPPED_VERTICES);
> @@ -421,17 +442,14 @@ do_clip_line( struct draw_stage *stage,
>      const struct clip_stage *clipper = clip_stage( stage );
>      struct vertex_header *v0 = header->v[0];
>      struct vertex_header *v1 = header->v[1];
> -   const float *pos0 = v0->clip;
> -   const float *pos1 = v1->clip;
>      float t0 = 0.0F;
>      float t1 = 0.0F;
>      struct prim_header newprim;
>
>      while (clipmask) {
>         const unsigned plane_idx = ffs(clipmask)-1;
> -      const float *plane = clipper->plane[plane_idx];
> -      const float dp0 = dot4( pos0, plane );
> -      const float dp1 = dot4( pos1, plane );
> +      const float dp0 = getclipdist(clipper, v0, plane_idx);
> +      const float dp1 = getclipdist(clipper, v1, plane_idx);
>
>         if (dp1<  0.0F) {
>   	 float t = dp1 / (dp1 - dp0);
> diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
> index aa9b602..31beb4b 100644
> --- a/src/gallium/auxiliary/draw/draw_private.h
> +++ b/src/gallium/auxiliary/draw/draw_private.h
> @@ -72,7 +72,7 @@ struct tgsi_sampler;
>   struct vertex_header {
>      unsigned clipmask:DRAW_TOTAL_CLIP_PLANES;
>      unsigned edgeflag:1;
> -   unsigned pad:1;
> +   unsigned have_clipdist:1;
>      unsigned vertex_id:16;
>
>      float clip[4];
> @@ -232,7 +232,7 @@ struct draw_context
>         uint position_output;
>         uint edgeflag_output;
>         uint clipvertex_output;
> -
> +      uint clipdistance_output[2];
>         /** TGSI program interpreter runtime state */
>         struct tgsi_exec_machine *machine;
>
> @@ -381,6 +381,7 @@ void draw_gs_destroy( struct draw_context *draw );
>   uint draw_current_shader_outputs(const struct draw_context *draw);
>   uint draw_current_shader_position_output(const struct draw_context *draw);
>   uint draw_current_shader_clipvertex_output(const struct draw_context *draw);
> +uint draw_current_shader_clipdistance_output(const struct draw_context *draw, int index);
>   int draw_alloc_extra_vertex_attrib(struct draw_context *draw,
>                                      uint semantic_name, uint semantic_index);
>   void draw_remove_extra_vertex_attribs(struct draw_context *draw);
> diff --git a/src/gallium/auxiliary/draw/draw_pt_post_vs.c b/src/gallium/auxiliary/draw/draw_pt_post_vs.c
> index a8d65fd..a83bb59 100644
> --- a/src/gallium/auxiliary/draw/draw_pt_post_vs.c
> +++ b/src/gallium/auxiliary/draw/draw_pt_post_vs.c
> @@ -31,7 +31,7 @@
>   #include "draw/draw_context.h"
>   #include "draw/draw_private.h"
>   #include "draw/draw_pt.h"
> -
> +#include "draw/draw_vs.h"
>
>   #define DO_CLIP_XY           0x1
>   #define DO_CLIP_FULL_Z       0x2
> @@ -56,7 +56,7 @@ initialize_vertex_header(struct vertex_header *header)
>   {
>      header->clipmask = 0;
>      header->edgeflag = 1;
> -   header->pad = 0;
> +   header->have_clipdist = 0;
>      header->vertex_id = UNDEFINED_VERTEX_ID;
>   }
>
> diff --git a/src/gallium/auxiliary/draw/draw_vs.c b/src/gallium/auxiliary/draw/draw_vs.c
> index 150653c..56c4f88 100644
> --- a/src/gallium/auxiliary/draw/draw_vs.c
> +++ b/src/gallium/auxiliary/draw/draw_vs.c
> @@ -132,6 +132,11 @@ draw_create_vertex_shader(struct draw_context *draw,
>                     vs->info.output_semantic_index[i] == 0) {
>               found_clipvertex = TRUE;
>               vs->clipvertex_output = i;
> +         } else if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_CLIPDIST) {
> +            if (vs->info.output_semantic_index[i] == 0)
> +               vs->clipdistance_output[0] = i;
> +            else
> +               vs->clipdistance_output[1] = i;
>            }
>         }
>         if (!found_clipvertex)
> @@ -156,6 +161,8 @@ draw_bind_vertex_shader(struct draw_context *draw,
>         draw->vs.position_output = dvs->position_output;
>         draw->vs.edgeflag_output = dvs->edgeflag_output;
>         draw->vs.clipvertex_output = dvs->clipvertex_output;
> +      draw->vs.clipdistance_output[0] = dvs->clipdistance_output[0];
> +      draw->vs.clipdistance_output[1] = dvs->clipdistance_output[1];
>         dvs->prepare( dvs, draw );
>      }
>      else {
> diff --git a/src/gallium/auxiliary/draw/draw_vs.h b/src/gallium/auxiliary/draw/draw_vs.h
> index a3b90fa..8a44091 100644
> --- a/src/gallium/auxiliary/draw/draw_vs.h
> +++ b/src/gallium/auxiliary/draw/draw_vs.h
> @@ -112,7 +112,7 @@ struct draw_vertex_shader {
>      unsigned position_output;
>      unsigned edgeflag_output;
>      unsigned clipvertex_output;
> -
> +   unsigned clipdistance_output[2];
>      /* Extracted from shader:
>       */
>      const float (*immediates)[4];

The rest of the series looks OK, AFAICT.

-Brian



More information about the mesa-dev mailing list