[Mesa-dev] [PATCH 8/8] draw: implement proper primitive assembler as a pipeline stage

Roland Scheidegger sroland at vmware.com
Fri Aug 2 09:00:29 PDT 2013


Am 02.08.2013 08:28, schrieb Zack Rusin:
> we used to have a face primitive assembler that we ran after if
> the gs was missing but we had adjacency primitives in the pipeline,
> lets convert it to a pipeline stage, which allows us to use it
> to inject outputs (primitive id) into the vertices. it's also
> a lot cleaner because the decomposition is already handled for us.
> 
> Signed-off-by: Zack Rusin <zackr at vmware.com>
> ---
>  src/gallium/auxiliary/Makefile.sources             |    2 +-
>  src/gallium/auxiliary/draw/draw_context.c          |    1 +
>  src/gallium/auxiliary/draw/draw_pipe.c             |    4 +
>  src/gallium/auxiliary/draw/draw_pipe.h             |    5 +
>  src/gallium/auxiliary/draw/draw_pipe_ia.c          |  253 ++++++++++++++++++++
>  src/gallium/auxiliary/draw/draw_pipe_validate.c    |   15 +-
>  src/gallium/auxiliary/draw/draw_prim_assembler.c   |  225 -----------------
>  src/gallium/auxiliary/draw/draw_prim_assembler.h   |   62 -----
>  .../auxiliary/draw/draw_prim_assembler_tmp.h       |   31 ---
>  src/gallium/auxiliary/draw/draw_private.h          |    1 +
>  .../auxiliary/draw/draw_pt_fetch_shade_pipeline.c  |   18 +-
>  .../draw/draw_pt_fetch_shade_pipeline_llvm.c       |   18 +-
>  12 files changed, 283 insertions(+), 352 deletions(-)
>  create mode 100644 src/gallium/auxiliary/draw/draw_pipe_ia.c
>  delete mode 100644 src/gallium/auxiliary/draw/draw_prim_assembler.c
>  delete mode 100644 src/gallium/auxiliary/draw/draw_prim_assembler.h
>  delete mode 100644 src/gallium/auxiliary/draw/draw_prim_assembler_tmp.h
> 
> diff --git a/src/gallium/auxiliary/Makefile.sources b/src/gallium/auxiliary/Makefile.sources
> index acbcef7..ee93e8b 100644
> --- a/src/gallium/auxiliary/Makefile.sources
> +++ b/src/gallium/auxiliary/Makefile.sources
> @@ -13,6 +13,7 @@ C_SOURCES := \
>  	draw/draw_pipe_clip.c \
>  	draw/draw_pipe_cull.c \
>  	draw/draw_pipe_flatshade.c \
> +        draw/draw_pipe_ia.c \
Formatting looks off here.

>  	draw/draw_pipe_offset.c \
>  	draw/draw_pipe_pstipple.c \
>  	draw/draw_pipe_stipple.c \
> @@ -23,7 +24,6 @@ C_SOURCES := \
>  	draw/draw_pipe_vbuf.c \
>  	draw/draw_pipe_wide_line.c \
>  	draw/draw_pipe_wide_point.c \
> -	draw/draw_prim_assembler.c \
>  	draw/draw_pt.c \
>  	draw/draw_pt_emit.c \
>  	draw/draw_pt_fetch.c \
> diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
> index 8bf3596..bbb2904 100644
> --- a/src/gallium/auxiliary/draw/draw_context.c
> +++ b/src/gallium/auxiliary/draw/draw_context.c
> @@ -555,6 +555,7 @@ draw_get_shader_info(const struct draw_context *draw)
>  void
>  draw_prepare_shader_outputs(struct draw_context *draw)
>  {
> +   draw_ia_prepare_outputs(draw, draw->pipeline.ia);
>     draw_unfilled_prepare_outputs(draw, draw->pipeline.unfilled);
>  }
>  
> diff --git a/src/gallium/auxiliary/draw/draw_pipe.c b/src/gallium/auxiliary/draw/draw_pipe.c
> index f1ee6cb..8140299 100644
> --- a/src/gallium/auxiliary/draw/draw_pipe.c
> +++ b/src/gallium/auxiliary/draw/draw_pipe.c
> @@ -49,6 +49,7 @@ boolean draw_pipeline_init( struct draw_context *draw )
>     draw->pipeline.clip      = draw_clip_stage( draw );
>     draw->pipeline.flatshade = draw_flatshade_stage( draw );
>     draw->pipeline.cull      = draw_cull_stage( draw );
> +   draw->pipeline.ia        = draw_ia_stage( draw );
>     draw->pipeline.validate  = draw_validate_stage( draw );
>     draw->pipeline.first     = draw->pipeline.validate;
>  
> @@ -61,6 +62,7 @@ boolean draw_pipeline_init( struct draw_context *draw )
>         !draw->pipeline.clip ||
>         !draw->pipeline.flatshade ||
>         !draw->pipeline.cull ||
> +       !draw->pipeline.ia ||
>         !draw->pipeline.validate)
>        return FALSE;
>  
> @@ -95,6 +97,8 @@ void draw_pipeline_destroy( struct draw_context *draw )
>        draw->pipeline.flatshade->destroy( draw->pipeline.flatshade );
>     if (draw->pipeline.cull)
>        draw->pipeline.cull->destroy( draw->pipeline.cull );
> +   if (draw->pipeline.ia)
> +      draw->pipeline.ia->destroy( draw->pipeline.ia );
>     if (draw->pipeline.validate)
>        draw->pipeline.validate->destroy( draw->pipeline.validate );
>     if (draw->pipeline.aaline)
> diff --git a/src/gallium/auxiliary/draw/draw_pipe.h b/src/gallium/auxiliary/draw/draw_pipe.h
> index 70c286f..70822a4 100644
> --- a/src/gallium/auxiliary/draw/draw_pipe.h
> +++ b/src/gallium/auxiliary/draw/draw_pipe.h
> @@ -91,7 +91,10 @@ extern struct draw_stage *draw_stipple_stage( struct draw_context *context );
>  extern struct draw_stage *draw_wide_line_stage( struct draw_context *context );
>  extern struct draw_stage *draw_wide_point_stage( struct draw_context *context );
>  extern struct draw_stage *draw_validate_stage( struct draw_context *context );
> +extern struct draw_stage *draw_ia_stage(struct draw_context *context);
>  
> +boolean draw_ia_stage_required(const struct draw_context *context,
> +                               unsigned prim);
>  
>  extern void draw_free_temp_verts( struct draw_stage *stage );
>  extern boolean draw_alloc_temp_verts( struct draw_stage *stage, unsigned nr );
> @@ -105,6 +108,8 @@ void draw_pipe_passthrough_point(struct draw_stage *stage, struct prim_header *h
>  
>  void draw_unfilled_prepare_outputs(struct draw_context *context,
>                                     struct draw_stage *stage);
> +void draw_ia_prepare_outputs(struct draw_context *context,
> +                             struct draw_stage *stage);
>  
>  
>  /**
> diff --git a/src/gallium/auxiliary/draw/draw_pipe_ia.c b/src/gallium/auxiliary/draw/draw_pipe_ia.c
> new file mode 100644
> index 0000000..9bdab8f
> --- /dev/null
> +++ b/src/gallium/auxiliary/draw/draw_pipe_ia.c
> @@ -0,0 +1,253 @@
> +/**************************************************************************
> + *
> + * Copyright 2013 VMware
> + * All Rights Reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the
> + * "Software"), to deal in the Software without restriction, including
> + * without limitation the rights to use, copy, modify, merge, publish,
> + * distribute, sub license, and/or sell copies of the Software, and to
> + * permit persons to whom the Software is furnished to do so, subject to
> + * the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> + * next paragraph) shall be included in all copies or substantial portions
> + * of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
> + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
> + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
> + *
> + **************************************************************************/
> +
> +/**
> + * \brief  Used to decompose adjacency primitives and inject the prim id
> + */
> +
> +#include "util/u_math.h"
> +#include "util/u_memory.h"
> +#include "pipe/p_defines.h"
> +#include "draw_pipe.h"
> +#include "draw_fs.h"
> +#include "draw_gs.h"
> +
> +
> +struct ia_stage {
> +   struct draw_stage stage;
> +   int primid_slot;
> +   unsigned primid;
> +};
> +
> +
> +static INLINE struct ia_stage *ia_stage( struct draw_stage *stage )
> +{
> +   return (struct ia_stage *)stage;
> +}
> +
> +
> +static void
> +inject_primid(struct draw_stage *stage,
> +              struct prim_header *header,
> +              unsigned num_verts)
> +{
> +   struct ia_stage *ia = ia_stage(stage);
> +   unsigned slot = ia->primid_slot;
> +   unsigned i;
> +   unsigned primid = ia->primid;
> +
> +   /* In case the backend doesn't care about it */
> +   if (slot < 0) {
> +      return;
> +   }
> +
> +   for (i = 0; i < num_verts; ++i) {
> +      struct vertex_header *v = header->v[i];
> +      /*memcpy(&v->data[slot][0], &primid, sizeof(primid));
> +      memcpy(&v->data[slot][1], &primid, sizeof(primid));
> +      memcpy(&v->data[slot][2], &primid, sizeof(primid));
> +      memcpy(&v->data[slot][3], &primid, sizeof(primid));*/
> +      v->data[slot][0] = primid;
> +      v->data[slot][1] = primid;
> +      v->data[slot][2] = primid;
> +      v->data[slot][3] = primid;
> +   }
holy crap we're really expecting a float prim id??? How the hell is that
going to work??? Also this is never going to be conformant (as we need a
32bit uint we don't have enough mantissa bits).
And I believe it is a mistake to make those explicitly assign all 4
values - this is a scalar not a vector! We really really need to make
these things scalar at some point so it's better to make some code which
could get away with accepting the wrong component to fail now imho.

> +   ++ia->primid;
> +}
> +
> +
> +static void
> +ia_point(struct draw_stage *stage,
> +         struct prim_header *header)
> +{
> +   inject_primid(stage, header, 1);
> +   stage->next->point(stage->next, header);
> +}
> +
> +static void
> +ia_line(struct draw_stage *stage,
> +        struct prim_header *header)
> +{
> +   inject_primid(stage, header, 2);
> +   stage->next->line(stage->next, header);
> +}
> +
> +static void
> +ia_tri(struct draw_stage *stage,
> +       struct prim_header *header)
> +{
> +   inject_primid(stage, header, 3);
> +   stage->next->tri(stage->next, header);
> +}
> +
> +static void
> +ia_first_point(struct draw_stage *stage,
> +               struct prim_header *header)
> +{
> +   struct ia_stage *ia = ia_stage(stage);
> +
> +   if (ia->primid_slot >= 0) {
> +      stage->point = ia_point;
> +   } else {
> +      stage->point = draw_pipe_passthrough_point;
> +   }
> +
> +   stage->point(stage, header);
> +}
> +
> +static void
> +ia_first_line(struct draw_stage *stage,
> +              struct prim_header *header)
> +{
> +   struct ia_stage *ia = ia_stage(stage);
> +
> +   if (ia->primid_slot >= 0) {
> +      stage->line = ia_line;
> +   } else {
> +      stage->line = draw_pipe_passthrough_line;
> +   }
> +
> +   stage->line(stage, header);
> +}
> +
> +static void
> +ia_first_tri(struct draw_stage *stage,
> +             struct prim_header *header)
> +{
> +   struct ia_stage *ia = ia_stage(stage);
> +
> +   if (ia->primid_slot >= 0) {
> +      stage->tri = ia_tri;
> +   } else {
> +      stage->tri = draw_pipe_passthrough_tri;
> +   }
> +
> +   stage->tri(stage, header);
> +}
> +
> +
> +static void
> +ia_flush(struct draw_stage *stage, unsigned flags)
> +{
> +   stage->point = ia_first_point;
> +   stage->line = ia_first_line;
> +   stage->tri = ia_first_tri;
> +   stage->next->flush(stage->next, flags);
> +}
> +
> +
> +static void
> +ia_reset_stipple_counter(struct draw_stage *stage)
> +{
> +   stage->next->reset_stipple_counter(stage->next);
> +}
> +
> +
> +static void
> +ia_destroy(struct draw_stage *stage)
> +{
> +   draw_free_temp_verts(stage);
> +   FREE(stage);
> +}
> +
> +
> +static boolean
> +needs_primid(const struct draw_context *draw)
> +{
> +   const struct draw_fragment_shader *fs = draw->fs.fragment_shader;
> +   const struct draw_geometry_shader *gs = draw->gs.geometry_shader;
> +   if (fs && fs->info.uses_primid) {
> +      return !gs || !gs->info.uses_primid;
> +   }
> +   return FALSE;
> +}
> +
> +boolean
> +draw_ia_stage_required(const struct draw_context *draw, unsigned prim)
> +{
> +   const struct draw_geometry_shader *gs = draw->gs.geometry_shader;
> +   if (needs_primid(draw)) {
> +      return TRUE;
> +   }
> +
> +   if (gs) {
> +      return FALSE;
> +   }
> +
> +   switch (prim) {
> +   case PIPE_PRIM_LINES_ADJACENCY:
> +   case PIPE_PRIM_LINE_STRIP_ADJACENCY:
> +   case PIPE_PRIM_TRIANGLES_ADJACENCY:
> +   case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
> +      return TRUE;
> +   default:
> +      return FALSE;
> +   }
> +}
> +
> +void
> +draw_ia_prepare_outputs(struct draw_context *draw,
> +                        struct draw_stage *stage)
> +{
> +   struct ia_stage *ia = ia_stage(stage);
> +   if (needs_primid(draw)) {
> +      ia->primid_slot = draw_alloc_extra_vertex_attrib(
> +         stage->draw, TGSI_SEMANTIC_PRIMID, 0);
> +   } else {
> +      ia->primid_slot = -1;
> +   }
> +   ia->primid = 0;
> +}
> +
> +struct draw_stage *
> +draw_ia_stage(struct draw_context *draw)
> +{
> +   struct ia_stage *ia = CALLOC_STRUCT(ia_stage);
> +   if (ia == NULL)
> +      goto fail;
> +
> +   ia->stage.draw = draw;
> +   ia->stage.name = "ia";
> +   ia->stage.next = NULL;
> +   ia->stage.point = ia_first_point;
> +   ia->stage.line = ia_first_line;
> +   ia->stage.tri = ia_first_tri;
> +   ia->stage.flush = ia_flush;
> +   ia->stage.reset_stipple_counter = ia_reset_stipple_counter;
> +   ia->stage.destroy = ia_destroy;
> +
> +   if (!draw_alloc_temp_verts(&ia->stage, 0))
> +      goto fail;
> +
> +   return &ia->stage;
> +
> +fail:
> +   if (ia)
> +      ia->stage.destroy(&ia->stage);
> +
> +   return NULL;
> +}
> diff --git a/src/gallium/auxiliary/draw/draw_pipe_validate.c b/src/gallium/auxiliary/draw/draw_pipe_validate.c
> index 2dbb95c..1ce89eb 100644
> --- a/src/gallium/auxiliary/draw/draw_pipe_validate.c
> +++ b/src/gallium/auxiliary/draw/draw_pipe_validate.c
> @@ -53,6 +53,7 @@ static boolean triangles( unsigned prim )
>     return prim >= PIPE_PRIM_TRIANGLES;
>  }
>  
> +
>  /**
>   * Default version of a function to check if we need any special
>   * pipeline stages, or whether prims/verts can go through untouched.
> @@ -76,6 +77,13 @@ draw_need_pipeline(const struct draw_context *draw,
>                                            prim );
>     }
>  
> +   /* If we need to decompose the primitives or inject
> +    * primitive id information then we have to run 
> +    * the pipeline */
> +   if (draw_ia_stage_required(draw, prim)) {
> +      return TRUE;
> +   }
> +   
>     /* Don't have to worry about triangles turning into lines/points
>      * and triggering the pipeline, because we have to trigger the
>      * pipeline *anyway* if unfilled mode is active.
> @@ -280,7 +288,12 @@ static struct draw_stage *validate_pipeline( struct draw_stage *stage )
>        next = draw->pipeline.clip;
>     }
>  
> -   
> +   /* Input assembler */
> +   if (draw_ia_stage_required(draw, draw->pt.prim)) {
> +      draw->pipeline.ia->next = next;
> +      next = draw->pipeline.ia;
> +   }
> +
>     draw->pipeline.first = next;
>  
>     if (0) {
> diff --git a/src/gallium/auxiliary/draw/draw_prim_assembler.c b/src/gallium/auxiliary/draw/draw_prim_assembler.c
> deleted file mode 100644
> index 9bedeea..0000000
> --- a/src/gallium/auxiliary/draw/draw_prim_assembler.c
> +++ /dev/null
> @@ -1,225 +0,0 @@
> -/**************************************************************************
> - *
> - * Copyright 2013 VMware, Inc.
> - * All Rights Reserved.
> - *
> - * Permission is hereby granted, free of charge, to any person obtaining a
> - * copy of this software and associated documentation files (the
> - * "Software"), to deal in the Software without restriction, including
> - * without limitation the rights to use, copy, modify, merge, publish,
> - * distribute, sub license, and/or sell copies of the Software, and to
> - * permit persons to whom the Software is furnished to do so, subject to
> - * the following conditions:
> - *
> - * The above copyright notice and this permission notice (including the
> - * next paragraph) shall be included in all copies or substantial portions
> - * of the Software.
> - *
> - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
> - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
> - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
> - *
> - **************************************************************************/
> -
> -#include "draw_prim_assembler.h"
> -
> -#include "util/u_debug.h"
> -#include "util/u_memory.h"
> -#include "util/u_prim.h"
> -
> -#include "pipe/p_defines.h"
> -
> -struct draw_assembler
> -{
> -   struct draw_context *draw;
> -
> -   struct draw_prim_info *output_prims;
> -   struct draw_vertex_info *output_verts;
> -
> -   const struct draw_prim_info *input_prims;
> -   const struct draw_vertex_info *input_verts;
> -};
> -
> -boolean
> -draw_prim_assembler_is_required(const struct draw_context *draw,
> -                                const struct draw_prim_info *prim_info,
> -                                const struct draw_vertex_info *vert_info)
> -{
> -   switch (prim_info->prim) {
> -   case PIPE_PRIM_LINES_ADJACENCY:
> -   case PIPE_PRIM_LINE_STRIP_ADJACENCY:
> -   case PIPE_PRIM_TRIANGLES_ADJACENCY:
> -   case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
> -      return TRUE;
> -   default:
> -      return FALSE;
> -   }
> -}
> -
> -/*
> - * Copy the vertex header along with its data from the current
> - * vertex buffer into a buffer holding vertices arranged
> - * into decomposed primitives (i.e. buffer without the
> - * adjacency vertices)
> - */
> -static void
> -copy_verts(struct draw_assembler *asmblr,
> -           unsigned *indices, unsigned num_indices)
> -{
> -   unsigned i;
> -
> -   char *output = (char*)asmblr->output_verts->verts;
> -   const char *input = (const char*)asmblr->input_verts->verts;
> -
> -   for (i = 0; i < num_indices; ++i) {
> -      unsigned idx = indices[i];
> -      unsigned output_offset =
> -         asmblr->output_verts->count * asmblr->output_verts->stride;
> -      unsigned input_offset = asmblr->input_verts->stride * idx;
> -      memcpy(output + output_offset, input + input_offset,
> -             asmblr->input_verts->vertex_size);
> -      asmblr->output_verts->count += 1;
> -   }
> -}
> -
> -static void
> -prim_point(struct draw_assembler *asmblr,
> -           unsigned idx)
> -{
> -   unsigned indices[1];
> -
> -   indices[0] = idx;
> -
> -   copy_verts(asmblr, indices, 1);
> -}
> -
> -static void
> -prim_line(struct draw_assembler *asmblr,
> -          unsigned i0, unsigned i1)
> -{
> -   unsigned indices[2];
> -
> -   indices[0] = i0;
> -   indices[1] = i1;
> -
> -   copy_verts(asmblr, indices, 2);
> -}
> -
> -static void
> -prim_line_adj(struct draw_assembler *asmblr,
> -              unsigned i0, unsigned i1, unsigned i2, unsigned i3)
> -{
> -   unsigned indices[2];
> -
> -   indices[0] = i1;
> -   indices[1] = i2;
> -
> -   copy_verts(asmblr, indices, 2);
> -}
> -
> -static void
> -prim_tri(struct draw_assembler *asmblr,
> -         unsigned i0, unsigned i1, unsigned i2)
> -{
> -   unsigned indices[3];
> -
> -   indices[0] = i0;
> -   indices[1] = i1;
> -   indices[2] = i2;
> -
> -   copy_verts(asmblr, indices, 3);
> -}
> -
> -static void
> -prim_tri_adj(struct draw_assembler *asmblr,
> -             unsigned i0, unsigned i1, unsigned i2,
> -             unsigned i3, unsigned i4, unsigned i5)
> -{
> -   unsigned indices[3];
> -
> -   indices[0] = i0;
> -   indices[1] = i2;
> -   indices[2] = i4;
> -
> -   copy_verts(asmblr, indices, 3);
> -}
> -
> -
> -
> -#define FUNC assembler_run_linear
> -#define GET_ELT(idx) (start + (idx))
> -#include "draw_prim_assembler_tmp.h"
> -
> -#define FUNC assembler_run_elts
> -#define LOCAL_VARS   const ushort *elts = input_prims->elts;
> -#define GET_ELT(idx) (elts[start + (idx)])
> -#include "draw_prim_assembler_tmp.h"
> -
> -
> -
> -/*
> - * Primitive assembler breaks up adjacency primitives and assembles
> - * the base primitives they represent, e.g. vertices forming
> - * PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY
> - * become vertices forming PIPE_PRIM_TRIANGLES 
> - * This is needed because specification says that the adjacency
> - * primitives are only visible in the geometry shader so we need
> - * to get rid of them so that the rest of the pipeline can
> - * process the inputs.
> - */
> -void
> -draw_prim_assembler_run(struct draw_context *draw,
> -                        const struct draw_prim_info *input_prims,
> -                        const struct draw_vertex_info *input_verts,
> -                        struct draw_prim_info *output_prims,
> -                        struct draw_vertex_info *output_verts)
> -{
> -   struct draw_assembler asmblr;
> -   unsigned start, i;
> -   unsigned assembled_prim = u_assembled_prim(input_prims->prim);
> -   unsigned max_primitives = u_decomposed_prims_for_vertices(
> -      input_prims->prim, input_prims->count);
> -   unsigned max_verts = u_vertices_per_prim(assembled_prim) * max_primitives;
> -
> -   asmblr.draw = draw;
> -   asmblr.output_prims = output_prims;
> -   asmblr.output_verts = output_verts;
> -   asmblr.input_prims = input_prims;
> -   asmblr.input_verts = input_verts;
> -
> -   output_prims->linear = TRUE;
> -   output_prims->elts = NULL;
> -   output_prims->start = 0;
> -   output_prims->prim = u_assembled_prim(input_prims->prim);
> -   output_prims->flags = 0x0;
> -   output_prims->primitive_lengths = MALLOC(sizeof(unsigned));
> -   output_prims->primitive_lengths[0] = 0;
> -   output_prims->primitive_count = 1;
> -
> -   output_verts->vertex_size = input_verts->vertex_size;
> -   output_verts->stride = input_verts->stride;
> -   output_verts->verts = (struct vertex_header*)MALLOC(
> -      input_verts->vertex_size * max_verts);
> -   output_verts->count = 0;
> -
> -
> -   for (start = i = 0; i < input_prims->primitive_count;
> -        start += input_prims->primitive_lengths[i], i++)
> -   {
> -      unsigned count = input_prims->primitive_lengths[i];
> -      if (input_prims->linear) {
> -         assembler_run_linear(&asmblr, input_prims, input_verts,
> -                              start, count);
> -      } else {
> -         assembler_run_elts(&asmblr, input_prims, input_verts,
> -                            start, count);
> -      }
> -   }
> -
> -   output_prims->primitive_lengths[0] = output_verts->count;
> -   output_prims->count = output_verts->count;
> -}
> diff --git a/src/gallium/auxiliary/draw/draw_prim_assembler.h b/src/gallium/auxiliary/draw/draw_prim_assembler.h
> deleted file mode 100644
> index 2ef7c51..0000000
> --- a/src/gallium/auxiliary/draw/draw_prim_assembler.h
> +++ /dev/null
> @@ -1,62 +0,0 @@
> -/**************************************************************************
> - *
> - * Copyright 2013 VMware, Inc.
> - * All Rights Reserved.
> - *
> - * Permission is hereby granted, free of charge, to any person obtaining a
> - * copy of this software and associated documentation files (the
> - * "Software"), to deal in the Software without restriction, including
> - * without limitation the rights to use, copy, modify, merge, publish,
> - * distribute, sub license, and/or sell copies of the Software, and to
> - * permit persons to whom the Software is furnished to do so, subject to
> - * the following conditions:
> - *
> - * The above copyright notice and this permission notice (including the
> - * next paragraph) shall be included in all copies or substantial portions
> - * of the Software.
> - *
> - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
> - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
> - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
> - *
> - **************************************************************************/
> -
> -/*
> - * Input assembler needs to be able to decompose adjacency primitives
> - * into something that can be understood by the rest of the pipeline.
> - * The specs say that the adjacency primitives are *only* visible
> - * in the geometry shader, for everything else they need to be
> - * decomposed. Which in most of the cases is not an issue, because the
> - * geometry shader always decomposes them for us, but without geometry
> - * shader we were passing unchanged adjacency primitives to the
> - * rest of the pipeline and causing crashes everywhere.
> - * If geometry shader is missing and the input primitive is one of 
> - * the adjacency primitives we use the code from this file to
> - * decompose them into something that the rest of the pipeline can 
> - * understand.
> - * 
> - */
> -
> -#ifndef DRAW_PRIM_ASSEMBLER_H
> -#define DRAW_PRIM_ASSEMBLER_H
> -
> -#include "draw/draw_private.h"
> -
> -boolean
> -draw_prim_assembler_is_required(const struct draw_context *draw,
> -                                const struct draw_prim_info *prim_info,
> -                                const struct draw_vertex_info *vert_info);
> -
> -void
> -draw_prim_assembler_run(struct draw_context *draw,
> -                        const struct draw_prim_info *in_prim_info,
> -                        const struct draw_vertex_info *in_vert_info,
> -                        struct draw_prim_info *out_prim_info,
> -                        struct draw_vertex_info *out_vert_info);
> -
> -
> -#endif
> diff --git a/src/gallium/auxiliary/draw/draw_prim_assembler_tmp.h b/src/gallium/auxiliary/draw/draw_prim_assembler_tmp.h
> deleted file mode 100644
> index 5bbacff..0000000
> --- a/src/gallium/auxiliary/draw/draw_prim_assembler_tmp.h
> +++ /dev/null
> @@ -1,31 +0,0 @@
> -#define FUNC_VARS                               \
> -   struct draw_assembler *asmblr,               \
> -   const struct draw_prim_info *input_prims,    \
> -   const struct draw_vertex_info *input_verts,  \
> -   unsigned start,                              \
> -   unsigned count
> -
> -#define FUNC_ENTER                                                \
> -   /* declare more local vars */                                  \
> -   const unsigned prim = input_prims->prim;                       \
> -   const unsigned prim_flags = input_prims->flags;                \
> -   const boolean quads_flatshade_last = FALSE;                    \
> -   const boolean last_vertex_last = !asmblr->draw->rasterizer->flatshade_first;  \
> -   switch (prim) {                                                  \
> -   case PIPE_PRIM_QUADS:                                            \
> -   case PIPE_PRIM_QUAD_STRIP:                                       \
> -   case PIPE_PRIM_POLYGON:                                          \
> -      debug_assert(!"unexpected primitive type in prim assembler"); \
> -      return;                                                       \
> -   default:                                                         \
> -      break;                                                        \
> -   }                                                                \
> -
> -
> -#define POINT(i0)                             prim_point(asmblr, i0)
> -#define LINE(flags, i0, i1)                   prim_line(asmblr, i0, i1)
> -#define TRIANGLE(flags, i0, i1, i2)           prim_tri(asmblr, i0, i1, i2)
> -#define LINE_ADJ(flags, i0, i1, i2, i3)       prim_line_adj(asmblr, i0, i1, i2, i3)
> -#define TRIANGLE_ADJ(flags,i0,i1,i2,i3,i4,i5) prim_tri_adj(asmblr,i0,i1,i2,i3,i4,i5)
> -
> -#include "draw_decompose_tmp.h"
> diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
> index 868b6c7..b21e795 100644
> --- a/src/gallium/auxiliary/draw/draw_private.h
> +++ b/src/gallium/auxiliary/draw/draw_private.h
> @@ -130,6 +130,7 @@ struct draw_context
>        struct draw_stage *wide_line;
>        struct draw_stage *wide_point;
>        struct draw_stage *rasterize;
> +      struct draw_stage *ia;
>  
>        float wide_point_threshold; /**< convert pnts to tris if larger than this */
>        float wide_line_threshold;  /**< convert lines to tris if wider than this */
> diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
> index 7f23d0b..71c075f 100644
> --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
> +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
> @@ -31,7 +31,6 @@
>  #include "draw/draw_context.h"
>  #include "draw/draw_vbuf.h"
>  #include "draw/draw_vertex.h"
> -#include "draw/draw_prim_assembler.h"
>  #include "draw/draw_pt.h"
>  #include "draw/draw_vs.h"
>  #include "draw/draw_gs.h"
> @@ -223,8 +222,6 @@ static void fetch_pipeline_generic( struct draw_pt_middle_end *middle,
>     struct draw_vertex_info vs_vert_info;
>     struct draw_vertex_info gs_vert_info;
>     struct draw_vertex_info *vert_info;
> -   struct draw_prim_info ia_prim_info;
> -   struct draw_vertex_info ia_vert_info;
>     const struct draw_prim_info *prim_info = in_prim_info;
>     boolean free_prim_info = FALSE;
>     unsigned opt = fpme->opt;
> @@ -282,21 +279,10 @@ static void fetch_pipeline_generic( struct draw_pt_middle_end *middle,
>        FREE(vert_info->verts);
>        vert_info = &gs_vert_info;
>        prim_info = &gs_prim_info;
> -   } else {
> -      if (draw_prim_assembler_is_required(draw, prim_info, vert_info)) {
> -         draw_prim_assembler_run(draw, prim_info, vert_info,
> -                                 &ia_prim_info, &ia_vert_info);
> -
> -         if (ia_vert_info.count) {
> -            FREE(vert_info->verts);
> -            vert_info = &ia_vert_info;
> -            prim_info = &ia_prim_info;
> -            free_prim_info = TRUE;
> -         }
> -      }
>     }
> +
>     if (prim_info->count == 0) {
> -      debug_printf("GS/IA didn't emit any vertices!\n");
> +      debug_printf("GS didn't emit any vertices!\n");
>        
>        FREE(vert_info->verts);
>        if (free_prim_info) {
> diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
> index f6ef5fd..fc69391 100644
> --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
> +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
> @@ -33,7 +33,6 @@
>  #include "draw/draw_vbuf.h"
>  #include "draw/draw_vertex.h"
>  #include "draw/draw_pt.h"
> -#include "draw/draw_prim_assembler.h"
>  #include "draw/draw_vs.h"
>  #include "draw/draw_llvm.h"
>  #include "gallivm/lp_bld_init.h"
> @@ -316,8 +315,6 @@ llvm_pipeline_generic( struct draw_pt_middle_end *middle,
>     struct draw_vertex_info llvm_vert_info;
>     struct draw_vertex_info gs_vert_info;
>     struct draw_vertex_info *vert_info;
> -   struct draw_prim_info ia_prim_info;
> -   struct draw_vertex_info ia_vert_info;
>     const struct draw_prim_info *prim_info = in_prim_info;
>     boolean free_prim_info = FALSE;
>     unsigned opt = fpme->opt;
> @@ -383,21 +380,10 @@ llvm_pipeline_generic( struct draw_pt_middle_end *middle,
>        FREE(vert_info->verts);
>        vert_info = &gs_vert_info;
>        prim_info = &gs_prim_info;
> -   } else {
> -      if (draw_prim_assembler_is_required(draw, prim_info, vert_info)) {
> -         draw_prim_assembler_run(draw, prim_info, vert_info,
> -                                 &ia_prim_info, &ia_vert_info);
> -
> -         if (ia_vert_info.count) {
> -            FREE(vert_info->verts);
> -            vert_info = &ia_vert_info;
> -            prim_info = &ia_prim_info;
> -            free_prim_info = TRUE;
> -         }
> -      }
>     }
> +
>     if (prim_info->count == 0) {
> -      debug_printf("GS/IA didn't emit any vertices!\n");
> +      debug_printf("GS didn't emit any vertices!\n");
>        
>        FREE(vert_info->verts);
>        if (free_prim_info) {
> 

Otherwise the ia stage looks good to me. I think though we _really_
reached the limits of our vec4 float interface between stages - we just
keep adding more and more d3d10 hacks on top of that legacy inteface.

Roland


More information about the mesa-dev mailing list