[Mesa-dev] [PATCH 3/6] draw: Only run prepare when state, prim and opt changes

Stéphane Marchesin marcheu at chromium.org
Tue Jan 24 00:55:48 PST 2012


From: Jakob Bornecrantz <wallbraker at gmail.com>

In bad applications like ipers which does a lot of draw calls with
no state changes this helps to greatly reduce time spent in prepare.
In ipers around 7% of CPU was spent in various prepare functions
after this commit no prepare function show on the profile.

This commit also has the added benefit of now grouping all pipelined
drawing into a single draw call if the driver uses vbuf_render.

Reviewed-by: Stéphane Marchesin <marcheu at chromium.org>
Tested-by: Stéphane Marchesin <marcheu at chromium.org>
---
 src/gallium/auxiliary/draw/draw_context.c   |    2 +
 src/gallium/auxiliary/draw/draw_private.h   |    7 ++++++
 src/gallium/auxiliary/draw/draw_pt.c        |   31 +++++++++++++++++++++++---
 src/gallium/auxiliary/draw/draw_pt.h        |    2 +-
 src/gallium/auxiliary/draw/draw_pt_vsplit.c |   11 ++++++---
 5 files changed, 44 insertions(+), 9 deletions(-)

diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
index 4ce4445..7b33017 100644
--- a/src/gallium/auxiliary/draw/draw_context.c
+++ b/src/gallium/auxiliary/draw/draw_context.c
@@ -654,6 +654,8 @@ void draw_do_flush( struct draw_context *draw, unsigned flags )
 
       draw_pipeline_flush( draw, flags );
 
+      draw_pt_flush( draw, flags );
+
       draw->flushing = FALSE;
    }
 }
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index 1a0286d..f53c16d 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -63,6 +63,7 @@ struct draw_stage;
 struct vbuf_render;
 struct tgsi_exec_machine;
 struct tgsi_sampler;
+struct draw_pt_front_end;
 
 
 /**
@@ -137,6 +138,11 @@ struct draw_context
    /* Support prototype passthrough path:
     */
    struct {
+      /* Current active frontend */
+      struct draw_pt_front_end *frontend;
+      unsigned prim;
+      unsigned opt;
+
       struct {
          struct draw_pt_middle_end *fetch_emit;
          struct draw_pt_middle_end *fetch_shade_emit;
@@ -391,6 +397,7 @@ void draw_remove_extra_vertex_attribs(struct draw_context *draw);
 boolean draw_pt_init( struct draw_context *draw );
 void draw_pt_destroy( struct draw_context *draw );
 void draw_pt_reset_vertex_ids( struct draw_context *draw );
+void draw_pt_flush( struct draw_context *draw, unsigned flags );
 
 
 /*******************************************************************************
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
index 9a017fd..3554ca1 100644
--- a/src/gallium/auxiliary/draw/draw_pt.c
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -106,17 +106,40 @@ draw_pt_arrays(struct draw_context *draw,
          middle = draw->pt.middle.general;
    }
 
-   frontend = draw->pt.front.vsplit;
+   frontend = draw->pt.frontend;
 
-   frontend->prepare( frontend, prim, middle, opt );
+   if (frontend && (draw->pt.prim != prim || opt != draw->pt.opt)) {
+      frontend->flush( frontend, DRAW_FLUSH_STATE_CHANGE );
+      frontend = NULL;
+   }
+
+   if (!frontend) {
+      frontend = draw->pt.front.vsplit;
 
-   frontend->run(frontend, start, count);
+      frontend->prepare( frontend, prim, middle, opt );
 
-   frontend->finish( frontend );
+      draw->pt.prim = prim;
+      draw->pt.opt = opt;
+      draw->pt.frontend = frontend;
+   }
+
+   frontend->run( frontend, start, count );
 
    return TRUE;
 }
 
+void draw_pt_flush( struct draw_context *draw, unsigned flags )
+{
+   if (draw->pt.frontend) {
+      draw->pt.frontend->flush( draw->pt.frontend, flags );
+
+      /* don't prepare if we only are flushing the backend */
+      if (flags != DRAW_FLUSH_BACKEND)
+         draw->pt.frontend = NULL;
+   }
+}
+
+
 
 boolean draw_pt_init( struct draw_context *draw )
 {
diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h
index 9a45845..2c2efdc 100644
--- a/src/gallium/auxiliary/draw/draw_pt.h
+++ b/src/gallium/auxiliary/draw/draw_pt.h
@@ -73,7 +73,7 @@ struct draw_pt_front_end {
                 unsigned start,
                 unsigned count );
 
-   void (*finish)( struct draw_pt_front_end * );
+   void (*flush)( struct draw_pt_front_end *, unsigned flags );
    void (*destroy)( struct draw_pt_front_end * );
 };
 
diff --git a/src/gallium/auxiliary/draw/draw_pt_vsplit.c b/src/gallium/auxiliary/draw/draw_pt_vsplit.c
index c19dcd9..7e19bd9 100644
--- a/src/gallium/auxiliary/draw/draw_pt_vsplit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_vsplit.c
@@ -178,11 +178,14 @@ static void vsplit_prepare(struct draw_pt_front_end *frontend,
 }
 
 
-static void vsplit_finish(struct draw_pt_front_end *frontend)
+static void vsplit_flush(struct draw_pt_front_end *frontend, unsigned flags)
 {
    struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend;
-   vsplit->middle->finish(vsplit->middle);
-   vsplit->middle = NULL;
+
+   if (flags != DRAW_FLUSH_BACKEND) {
+      vsplit->middle->finish(vsplit->middle);
+      vsplit->middle = NULL;
+   }
 }
 
 
@@ -202,7 +205,7 @@ struct draw_pt_front_end *draw_pt_vsplit(struct draw_context *draw)
 
    vsplit->base.prepare = vsplit_prepare;
    vsplit->base.run     = NULL;
-   vsplit->base.finish  = vsplit_finish;
+   vsplit->base.flush   = vsplit_flush;
    vsplit->base.destroy = vsplit_destroy;
    vsplit->draw = draw;
 
-- 
1.7.6.5



More information about the mesa-dev mailing list