diff options
author | Jakob Bornecrantz <[email protected]> | 2011-01-24 02:11:59 +0100 |
---|---|---|
committer | Stéphane Marchesin <[email protected]> | 2012-01-26 01:38:46 -0800 |
commit | b6d3a435a0e0e53a9e8cc4c4249dc7c2f897a83d (patch) | |
tree | 8fc2f5bc0bb3f0213308adb2643f491fcdbf3247 /src/gallium/auxiliary/draw/draw_pt.c | |
parent | eb65ccbc21670d16813b53e0f8d94cb4e037d39c (diff) |
draw: Only run prepare when state, prim and opt changes
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 <[email protected]>
Tested-by: Stéphane Marchesin <[email protected]>
Diffstat (limited to 'src/gallium/auxiliary/draw/draw_pt.c')
-rw-r--r-- | src/gallium/auxiliary/draw/draw_pt.c | 49 |
1 files changed, 44 insertions, 5 deletions
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c index 9a017fd0567..025d53989e4 100644 --- a/src/gallium/auxiliary/draw/draw_pt.c +++ b/src/gallium/auxiliary/draw/draw_pt.c @@ -52,7 +52,7 @@ DEBUG_GET_ONCE_BOOL_OPTION(draw_no_fse, "DRAW_NO_FSE", FALSE) * - backend -- the vbuf_render provided by the driver. */ static boolean -draw_pt_arrays(struct draw_context *draw, +draw_pt_arrays(struct draw_context *draw, unsigned prim, unsigned start, unsigned count) @@ -106,17 +106,56 @@ draw_pt_arrays(struct draw_context *draw, middle = draw->pt.middle.general; } - frontend = draw->pt.front.vsplit; + frontend = draw->pt.frontend; + + if (frontend ) { + if (draw->pt.prim != prim || draw->pt.opt != opt) { + /* In certain conditions switching primitives requires us to flush + * and validate the different stages. One example is when smooth + * lines are active but first drawn with triangles and then with + * lines. + */ + draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); + frontend = NULL; + } else if (draw->pt.eltSize != draw->pt.user.eltSize) { + /* Flush draw state if eltSize changed. + * This could be improved so only the frontend is flushed since it + * converts all indices to ushorts and the fetch part of the middle + * always perpares both linear and indexed. + */ + frontend->flush( frontend, DRAW_FLUSH_STATE_CHANGE ); + frontend = NULL; + } + } - frontend->prepare( frontend, prim, middle, opt ); + if (!frontend) { + frontend = draw->pt.front.vsplit; - frontend->run(frontend, start, count); + frontend->prepare( frontend, prim, middle, opt ); - frontend->finish( frontend ); + draw->pt.frontend = frontend; + draw->pt.eltSize = draw->pt.user.eltSize; + draw->pt.prim = prim; + draw->pt.opt = opt; + } + + 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 ) { |