draw: don't try to precalculate the pipeline output primitive
authorKeith Whitwell <keithw@vmware.com>
Wed, 23 Jun 2010 17:06:52 +0000 (18:06 +0100)
committerKeith Whitwell <keithw@vmware.com>
Wed, 23 Jun 2010 17:10:20 +0000 (18:10 +0100)
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.

src/gallium/auxiliary/draw/draw_pt.c
src/gallium/auxiliary/draw/draw_pt.h
src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
src/gallium/auxiliary/draw/draw_pt_varray.c
src/gallium/auxiliary/draw/draw_pt_vcache.c

index 02c97fec817302fb1650801d373352c508706a7e..6234272d6ce98a334b716111b9535b3e56df4a0e 100644 (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),
index b6741ca83ce267b67c396eb7cfb7d399479935d9..44356fba4c553f81f553da3bb007e8eeb2a887ae 100644 (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 );
 
index c629d55563699cccf0cbd15069d69036c6012e3d..5c8af17c8e36d6382a0b39e815ab22788fe33592 100644 (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;
index 5483a25f1dc41a80c81f993956c9c0923fab2a05..b8270280b648175edb6055e2779312686cef2ff1 100644 (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;
    }
index 43b08a030cfec71facac8a0db513f3dbf7d97592..047e192d4d11f7ec7de69a2ed63e49acf6061866 100644 (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,
index 7d2de58e733cbf68e9b83d49c6119f29f9d6d858..774fb7bf7a2c55c2681d2ccda1629f2f91d6906f 100644 (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
index 5ea833032f322da20762a4da5988a6b36f458711..d89d5cd20f4f677de3e45c81c81ebcb8549e3ad8 100644 (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);
index 914c87a9dc485a38c8d63c4a6a7f51d8431a8b57..b7e0da7d44eb0f95ad6692fa076ea0f15633fc83 100644 (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 );
 }