draw: don't try to precalculate the pipeline output primitive

We were previously calculating a value which was either the geometry
shader output primitive or the application's input primitive, and
passing that to the various front/middle/back components for use as
the ultimate rendering primtive.

Unfortunately, this was not correct -- if the vcache decomposition
path is active and geometry shaders are *not* active, we can end up
with a third primitive -- specifically the decomposed version of the
input primitive.

Rather than trying to precalculate this, just let the individual
components inform their successors about which primitive type they are
recieving.
This commit is contained in:
Keith Whitwell 2010-06-23 18:06:52 +01:00
parent 292eecca8c
commit 64682da8ab
8 changed files with 46 additions and 34 deletions

View file

@ -69,7 +69,6 @@ draw_pt_arrays(struct draw_context *draw,
struct draw_pt_front_end *frontend = NULL;
struct draw_pt_middle_end *middle = NULL;
unsigned opt = 0;
unsigned out_prim = prim;
/* Sanitize primitive length:
*/
@ -80,18 +79,19 @@ draw_pt_arrays(struct draw_context *draw,
if (count < first)
return TRUE;
}
if (draw->gs.geometry_shader) {
out_prim = draw->gs.geometry_shader->output_primitive;
}
if (!draw->force_passthrough) {
unsigned gs_out_prim = (draw->gs.geometry_shader ?
draw->gs.geometry_shader->output_primitive :
prim);
if (!draw->render) {
opt |= PT_PIPELINE;
}
if (draw_need_pipeline(draw,
draw->rasterizer,
out_prim)) {
gs_out_prim)) {
opt |= PT_PIPELINE;
}
@ -122,7 +122,7 @@ draw_pt_arrays(struct draw_context *draw,
frontend = draw->pt.front.varray;
}
frontend->prepare( frontend, prim, out_prim, middle, opt );
frontend->prepare( frontend, prim, middle, opt );
frontend->run(frontend,
draw_pt_elt_func(draw),

View file

@ -62,8 +62,7 @@ struct draw_vertex_info;
*/
struct draw_pt_front_end {
void (*prepare)( struct draw_pt_front_end *,
unsigned input_prim,
unsigned output_prim,
unsigned prim,
struct draw_pt_middle_end *,
unsigned opt );
@ -87,8 +86,7 @@ struct draw_pt_front_end {
*/
struct draw_pt_middle_end {
void (*prepare)( struct draw_pt_middle_end *,
unsigned input_prim,
unsigned output_prim,
unsigned prim,
unsigned opt,
unsigned *max_vertices );

View file

@ -36,6 +36,7 @@
#include "draw/draw_vbuf.h"
#include "draw/draw_vertex.h"
#include "draw/draw_pt.h"
#include "draw/draw_gs.h"
#include "translate/translate.h"
#include "translate/translate_cache.h"
@ -90,7 +91,6 @@ struct fetch_emit_middle_end {
static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
unsigned prim,
unsigned out_prim,
unsigned opt,
unsigned *max_vertices )
{
@ -101,9 +101,14 @@ static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
boolean ok;
struct translate_key key;
unsigned gs_out_prim = (draw->gs.geometry_shader ?
draw->gs.geometry_shader->output_primitive :
prim);
ok = draw->render->set_primitive( draw->render,
out_prim );
gs_out_prim );
if (!ok) {
assert(0);
return;

View file

@ -68,8 +68,7 @@ struct fetch_shade_emit {
static void fse_prepare( struct draw_pt_middle_end *middle,
unsigned in_prim,
unsigned out_prim,
unsigned prim,
unsigned opt,
unsigned *max_vertices )
{
@ -80,9 +79,12 @@ static void fse_prepare( struct draw_pt_middle_end *middle,
unsigned i;
unsigned nr_vbs = 0;
/* Can't support geometry shader on this path.
*/
assert(!draw->gs.geometry_shader);
if (!draw->render->set_primitive( draw->render,
out_prim )) {
prim )) {
assert(0);
return;
}

View file

@ -48,13 +48,11 @@ struct fetch_pipeline_middle_end {
unsigned vertex_data_offset;
unsigned vertex_size;
unsigned input_prim;
unsigned output_prim;
unsigned opt;
};
static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
unsigned in_prim,
unsigned out_prim,
unsigned prim,
unsigned opt,
unsigned *max_vertices )
{
@ -64,6 +62,10 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
unsigned i;
unsigned instance_id_index = ~0;
unsigned gs_out_prim = (draw->gs.geometry_shader ?
draw->gs.geometry_shader->output_primitive :
prim);
/* Add one to num_outputs because the pipeline occasionally tags on
* an additional texcoord, eg for AA lines.
*/
@ -79,8 +81,7 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
}
}
fpme->input_prim = in_prim;
fpme->output_prim = out_prim;
fpme->input_prim = prim;
fpme->opt = opt;
/* Always leave room for the vertex header whether we need it or
@ -108,7 +109,7 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
if (!(opt & PT_PIPELINE)) {
draw_pt_emit_prepare( fpme->emit,
out_prim,
gs_out_prim,
max_vertices );
*max_vertices = MAX2( *max_vertices,

View file

@ -49,7 +49,6 @@ struct llvm_middle_end {
unsigned vertex_data_offset;
unsigned vertex_size;
unsigned input_prim;
unsigned output_prim;
unsigned opt;
struct draw_llvm *llvm;
@ -62,7 +61,6 @@ struct llvm_middle_end {
static void
llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
unsigned in_prim,
unsigned out_prim,
unsigned opt,
unsigned *max_vertices )
{
@ -74,6 +72,11 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
unsigned i;
unsigned instance_id_index = ~0;
unsigned out_prim = (draw->gs.geometry_shader ?
draw->gs.geometry_shader->output_primitive :
in_prim);
/* Add one to num_outputs because the pipeline occasionally tags on
* an additional texcoord, eg for AA lines.
*/
@ -90,7 +93,6 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
}
fpme->input_prim = in_prim;
fpme->output_prim = out_prim;
fpme->opt = opt;
/* Always leave room for the vertex header whether we need it or

View file

@ -137,7 +137,6 @@ static unsigned decompose_prim[PIPE_PRIM_POLYGON + 1] = {
static void varray_prepare(struct draw_pt_front_end *frontend,
unsigned in_prim,
unsigned out_prim,
struct draw_pt_middle_end *middle,
unsigned opt)
{
@ -146,11 +145,12 @@ static void varray_prepare(struct draw_pt_front_end *frontend,
varray->base.run = varray_run;
varray->input_prim = in_prim;
varray->output_prim = decompose_prim[out_prim];
varray->output_prim = decompose_prim[in_prim];
varray->middle = middle;
middle->prepare(middle, varray->input_prim,
varray->output_prim, opt, &varray->driver_fetch_max );
middle->prepare(middle,
varray->output_prim,
opt, &varray->driver_fetch_max );
/* check that the max is even */
assert((varray->driver_fetch_max & 1) == 0);

View file

@ -70,7 +70,6 @@ vcache_flush( struct vcache_frontend *vcache )
if (vcache->middle_prim != vcache->output_prim) {
vcache->middle_prim = vcache->output_prim;
vcache->middle->prepare( vcache->middle,
vcache->input_prim,
vcache->middle_prim,
vcache->opt,
&vcache->fetch_max );
@ -368,7 +367,6 @@ vcache_check_run( struct draw_pt_front_end *frontend,
if (vcache->middle_prim != vcache->input_prim) {
vcache->middle_prim = vcache->input_prim;
vcache->middle->prepare( vcache->middle,
vcache->input_prim,
vcache->middle_prim,
vcache->opt,
&vcache->fetch_max );
@ -472,7 +470,6 @@ vcache_check_run( struct draw_pt_front_end *frontend,
static void
vcache_prepare( struct draw_pt_front_end *frontend,
unsigned in_prim,
unsigned out_prim,
struct draw_pt_middle_end *middle,
unsigned opt )
{
@ -487,8 +484,14 @@ vcache_prepare( struct draw_pt_front_end *frontend,
vcache->base.run = vcache_check_run;
}
/* VCache will always emit the reduced version of its input
* primitive, ie STRIP/FANS become TRIS, etc.
*
* This is not to be confused with what the GS might be up to,
* which is a separate issue.
*/
vcache->input_prim = in_prim;
vcache->output_prim = u_reduced_prim(out_prim);
vcache->output_prim = u_reduced_prim(in_prim);
vcache->middle = middle;
vcache->opt = opt;
@ -497,8 +500,9 @@ vcache_prepare( struct draw_pt_front_end *frontend,
* doing so:
*/
vcache->middle_prim = (opt & PT_PIPELINE) ? vcache->output_prim : vcache->input_prim;
middle->prepare( middle, vcache->input_prim,
vcache->middle_prim, opt, &vcache->fetch_max );
middle->prepare( middle,
vcache->middle_prim,
opt, &vcache->fetch_max );
}