[Mesa-dev] [PATCH 8/8] draw: implement proper primitive assembler as a pipeline stage
Zack Rusin
zackr at vmware.com
Fri Aug 2 11:45:44 PDT 2013
Yea, it's quite bonkers, but that's the way it has to be to make it work right now. Personally I'd really like to write a new version of draw, without the 5 emit paths, 4 different vertex shading paths, with interface that is capable of emitting more than just float[4]'s... For now though this works, even if it is very ugly.
z
----- Original Message -----
> 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