draw: make pt run pipeline when need_pipeline is true, not just when clipped
authorKeith Whitwell <keith@tungstengraphics.com>
Wed, 16 Apr 2008 09:03:18 +0000 (10:03 +0100)
committerKeith Whitwell <keith@tungstengraphics.com>
Wed, 16 Apr 2008 11:22:20 +0000 (12:22 +0100)
src/gallium/auxiliary/draw/draw_private.h
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_pipeline.c
src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
src/gallium/auxiliary/draw/draw_pt_vcache.c

index c8cb96c8ba0083b20ecf89d3239387790b5a3b26..8ac061cc9f899968e10dd46a1df2cc2e81e4c4c4 100644 (file)
@@ -182,6 +182,12 @@ typedef void (*pt_fetch_func)( struct draw_context *draw,
 
 struct vbuf_render;
 
+
+#define PT_SHADE      0x1
+#define PT_CLIPTEST   0x2
+#define PT_PIPELINE   0x4
+#define PT_MAX_MIDDLE 0x8
+
 /**
  * Private context for the drawing module.
  */
@@ -219,15 +225,10 @@ struct draw_context
       unsigned hw_vertex_size; /* XXX: to be removed */
 
       struct {
-         struct draw_pt_middle_end *fetch_emit;
-         struct draw_pt_middle_end *fetch_pipeline;
-         struct draw_pt_middle_end *fetch_shade_emit;
-         struct draw_pt_middle_end *fetch_shade_cliptest_pipeline_or_emit;
+         struct draw_pt_middle_end *opt[PT_MAX_MIDDLE];
       } middle;
 
       struct {
-         struct draw_pt_front_end *noop;
-         struct draw_pt_front_end *split_arrays;
          struct draw_pt_front_end *vcache;
       } front;
 
index 3d2e7bf7b82b86b09b24196091e4cf2953b5212f..895224c9527184d073ff17c8d13b21d1906bd015 100644 (file)
 #include "draw/draw_pt.h"
 
 
-#if 0
-static boolean too_many_elts( struct draw_context *draw,
-                              unsigned elts )
-{
-   return elts > (8 * 1024);
-}
-#endif
-
-static INLINE unsigned reduced_prim(unsigned prim)
-{
-   /*FIXME*/
-   return prim;
-}
 
-static INLINE boolean good_prim(unsigned prim)
-{
-   /*FIXME*/
-   return FALSE;
-}
 
+/* Overall we split things into:
+ *     - frontend -- prepare fetch_elts, draw_elts - eg vcache
+ *     - middle   -- fetch, shade, cliptest, viewport
+ *     - pipeline -- the prim pipeline: clipping, wide lines, etc 
+ *     - backend  -- the vbuf_render provided by the driver.
+ */
 boolean
 draw_pt_arrays(struct draw_context *draw, 
                unsigned prim,
                unsigned start, 
                unsigned count)
 {
-   const boolean pipeline = draw_need_pipeline(draw, prim);
-   const boolean cliptest = !draw->rasterizer->bypass_clipping;
-   const boolean shading  = !draw->rasterizer->bypass_vs;
    struct draw_pt_front_end *frontend = NULL;
    struct draw_pt_middle_end *middle = NULL;
+   unsigned opt = 0;
 
    if (!draw->render)
       return FALSE;
    /*debug_printf("XXXXXXXXXX needs_pipeline = %d\n", pipeline);*/
 
-   /* Overall we do:
-    *     - frontend -- prepare fetch_elts, draw_elts - eg vcache
-    *     - middle   -- fetch, shade, cliptest, viewport
-    *     - pipeline -- the prim pipeline: clipping, wide lines, etc 
-    *     - backend  -- the vbuf_render provided by the driver.
-    */
-
-   if (shading && !draw->use_pt_shaders)
-      return FALSE;
 
-
-   if (!cliptest && !pipeline && !shading) {
-      /* This is the 'passthrough' path:
-       */
-      /* Fetch user verts, emit hw verts:
-       */
-      middle = draw->pt.middle.fetch_emit;
-   }
-   else if (!cliptest && !shading) {
-      /* This is the 'passthrough' path targetting the pipeline backend.
-       */
-      /* Fetch user verts, emit pipeline verts, run pipeline:
-       */
-      middle = draw->pt.middle.fetch_pipeline;
-   }
-   else if (!cliptest && !pipeline) {
-      /* Fetch user verts, run vertex shader, emit hw verts:
-       */
-      middle = draw->pt.middle.fetch_shade_emit;
-   }
-   else if (!pipeline) {
-      /* Even though !pipeline, we have to run it to get clipping.  We
-       * do know that the pipeline is just the clipping operation, but
-       * that probably doesn't help much.
-       *
-       * This is going to be the most important path for a lot of
-       * swtnl cards.
-       */
-      /* Fetch user verts, 
-       *    run vertex shader, 
-       *    cliptest and viewport trasform
-       *    if no clipped vertices,
-       *        emit hw verts
-       *    else
-       *        run pipline
-       */
-      middle = draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit;
-   }
-   else {
-      /* This is what we're currently always doing:
-       */
-      /* Fetch user verts, run vertex shader, cliptest, run pipeline
-       * or
-       * Fetch user verts, run vertex shader, run pipeline
-       */
-      middle = draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit;
+   if (draw_need_pipeline(draw, prim)) {
+      opt |= PT_PIPELINE;
    }
 
+   if (!draw->rasterizer->bypass_clipping) {
+      opt |= PT_CLIPTEST;
+   }
 
-   /* If !pipeline, need to make sure we respect the driver's limited
-    * capabilites to receive blocks of vertex data and elements.
-    */
-#if 0
-   if (!pipeline) {
-      unsigned vertex_mode = passthrough;
-      unsigned nr_verts = count_vertices( draw, start, count );
-      unsigned hw_prim = prim;
-
-      if (is_elts(draw)) {
-         frontend = draw->pt.front.vcache;
-         hw_prim = reduced_prim(prim);
-      }
-#if 0
-      if (too_many_verts(nr_verts)) {
-         /* if (is_verts(draw) && can_split(prim)) {
-            draw = draw_arrays_split;
-         }
-         else */ {
-            frontend = draw->pt.front.vcache;
-            hw_prim = reduced_prim(prim);
-         }
-      }
-#endif
+   if (!draw->rasterizer->bypass_vs) {
+      opt |= PT_SHADE;
 
-      if (too_many_elts(count)) {
+      if (!draw->use_pt_shaders)
+        return FALSE;
+   }
 
-         /* if (is_elts(draw) && can_split(prim)) {
-            draw = draw_elts_split;
-         }
-         else */ {
-            frontend = draw->pt.front.vcache;
-            hw_prim = reduced_prim(prim);
-         }
-      }
 
-      if (!good_prim(hw_prim)) {
-         frontend = draw->pt.front.vcache;
-      }
+   if (draw->pt.middle.opt[opt] == NULL) {
+      opt = PT_PIPELINE | PT_CLIPTEST | PT_SHADE;
    }
-#else
+
+   middle = draw->pt.middle.opt[opt];
+   assert(middle);
+
+   /* May create a short-circuited version of this for small primitives:
+    */
    frontend = draw->pt.front.vcache;
-#endif   
 
-   frontend->prepare( frontend, prim, middle );
+
+   frontend->prepare( frontend, prim, middle, opt );
 
    frontend->run( frontend,
                   draw_pt_elt_func( draw ),
@@ -190,21 +102,19 @@ draw_pt_arrays(struct draw_context *draw,
 
 boolean draw_pt_init( struct draw_context *draw )
 {
-   draw->pt.middle.fetch_emit = draw_pt_fetch_emit( draw );
-   if (!draw->pt.middle.fetch_emit)
-      return FALSE;
-
-   draw->pt.middle.fetch_pipeline = draw_pt_fetch_pipeline( draw );
-   if (!draw->pt.middle.fetch_pipeline)
+   draw->pt.front.vcache = draw_pt_vcache( draw );
+   if (!draw->pt.front.vcache)
       return FALSE;
 
-   draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit =
+   draw->pt.middle.opt[0] = draw_pt_fetch_emit( draw );
+   draw->pt.middle.opt[PT_PIPELINE] = draw_pt_fetch_pipeline( draw );
+//   draw->pt.middle.opt[PT_SHADE] = draw_pt_shade_emit( draw );
+//   draw->pt.middle.opt[PT_SHADE | PT_PIPELINE] = draw_pt_shade_pipeline( draw );
+//   draw->pt.middle.opt[PT_SHADE | PT_CLIPTEST] = draw_pt_shade_clip_either( draw );
+   draw->pt.middle.opt[PT_SHADE | PT_CLIPTEST | PT_PIPELINE] = 
       draw_pt_fetch_pipeline_or_emit( draw );
-   if (!draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit)
-      return FALSE;
 
-   draw->pt.front.vcache = draw_pt_vcache( draw );
-   if (!draw->pt.front.vcache)
+   if (!draw->pt.middle.opt[PT_SHADE | PT_CLIPTEST | PT_PIPELINE])
       return FALSE;
 
    return TRUE;
@@ -213,21 +123,13 @@ boolean draw_pt_init( struct draw_context *draw )
 
 void draw_pt_destroy( struct draw_context *draw )
 {
-   if (draw->pt.middle.fetch_emit) {
-      draw->pt.middle.fetch_emit->destroy( draw->pt.middle.fetch_emit );
-      draw->pt.middle.fetch_emit = NULL;
-   }
+   int i;
 
-   if (draw->pt.middle.fetch_pipeline) {
-      draw->pt.middle.fetch_pipeline->destroy( draw->pt.middle.fetch_pipeline );
-      draw->pt.middle.fetch_pipeline = NULL;
-   }
-
-   if (draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit) {
-      draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit->destroy(
-         draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit );
-      draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit = NULL;
-   }
+   for (i = 0; i < PT_MAX_MIDDLE; i++)
+      if (draw->pt.middle.opt[i]) {
+        draw->pt.middle.opt[i]->destroy( draw->pt.middle.opt[i] );
+        draw->pt.middle.opt[i] = NULL;
+      }
 
    if (draw->pt.front.vcache) {
       draw->pt.front.vcache->destroy( draw->pt.front.vcache );
index 48413b648a66a0d7d38c0dc73c6ad543d5c6fbcc..08afb606457f760057899742805e840610ba4108 100644 (file)
@@ -64,7 +64,8 @@ struct draw_context;
 struct draw_pt_front_end {
    void (*prepare)( struct draw_pt_front_end *,
                     unsigned prim,
-                    struct draw_pt_middle_end * );
+                    struct draw_pt_middle_end *,
+                   unsigned opt );
 
    void (*run)( struct draw_pt_front_end *,
                 pt_elt_func elt_func,
@@ -90,7 +91,8 @@ struct draw_pt_front_end {
  */
 struct draw_pt_middle_end {
    void (*prepare)( struct draw_pt_middle_end *,
-                    unsigned prim );
+                    unsigned prim,
+                   unsigned opt );
 
    void (*run)( struct draw_pt_middle_end *,
                 const unsigned *fetch_elts,
index 3a26a5d71239db4ad4b0aac69ede267f1a6296c7..1a9d331a06580e4324fb32c9975dda8a80737310 100644 (file)
@@ -164,7 +164,8 @@ fetch_store_general( struct fetch_emit_middle_end *feme,
 
 
 static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
-                                unsigned prim )
+                                unsigned prim,
+                               unsigned opt )
 {
    struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
    struct draw_context *draw = feme->draw;
index a70d129c93c2e888c15cd7bafb68e936b193ea0e..db6d6c76ea7556cc0a8cee2d9c3ceeecd573bca5 100644 (file)
@@ -209,7 +209,8 @@ fetch_store_general( struct fetch_pipeline_middle_end *fpme,
  *
  */
 static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
-                                    unsigned prim )
+                                    unsigned prim,
+                                   unsigned opt )
 {
    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
    struct draw_context *draw = fpme->draw;
index 2d83e11940fd75b53d5fd791b593c2e22f0bd761..52be4a64aa63eb61ac6c74abb1f111f0769b3c6f 100644 (file)
@@ -42,11 +42,13 @@ struct fetch_pipeline_middle_end {
 
    unsigned pipeline_vertex_size;
    unsigned prim;
+   unsigned opt;
 };
 
 
 static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
-                                    unsigned prim )
+                                    unsigned prim,
+                                   unsigned opt )
 {
    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
    struct draw_context *draw = fpme->draw;
@@ -57,6 +59,7 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
    struct translate_key hw_key;
 
    fpme->prim = prim;
+   fpme->opt = opt;
 
    ok = draw->render->set_primitive(draw->render, prim);
    if (!ok) {
@@ -157,6 +160,7 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
    struct draw_context *draw = fpme->draw;
    struct draw_vertex_shader *shader = draw->vertex_shader;
    char *pipeline_verts;
+   unsigned pipeline = PT_PIPELINE;
 
    pipeline_verts = MALLOC(fpme->pipeline_vertex_size *
                           fetch_count);
@@ -170,9 +174,17 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
    /* Shade
     */
    shader->prepare(shader, draw);
+
    if (shader->run(shader, draw, fetch_elts, fetch_count, pipeline_verts,
-                   fpme->pipeline_vertex_size)) {
-      /* Run the pipeline */
+                  fpme->pipeline_vertex_size))
+   {
+      pipeline |= PT_CLIPTEST;
+   }
+
+
+   /* Do we need to run the pipeline?
+    */
+   if (fpme->opt & pipeline) {
       draw_pt_run_pipeline( fpme->draw,
                             fpme->prim,
                             pipeline_verts,
index 107dcfc269c9ed544b5234a92cd595ffcd34839b..5561f2b6fb4ce164c407c710a3ae5b03298b3dc6 100644 (file)
@@ -448,7 +448,8 @@ static unsigned reduced_prim[PIPE_PRIM_POLYGON + 1] = {
 
 static void vcache_prepare( struct draw_pt_front_end *frontend,
                             unsigned prim,
-                            struct draw_pt_middle_end *middle )
+                            struct draw_pt_middle_end *middle,
+                           unsigned opt )
 {
    struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
 
@@ -464,7 +465,7 @@ static void vcache_prepare( struct draw_pt_front_end *frontend,
    vcache->output_prim = reduced_prim[prim];
 
    vcache->middle = middle;
-   middle->prepare( middle, vcache->output_prim );
+   middle->prepare( middle, vcache->output_prim, opt );
 }