[Mesa-dev] Mesa (master): draw: Only run prepare when state, prim and opt changes
Jose Fonseca
jfonseca at vmware.com
Thu Jan 26 03:43:17 PST 2012
Stephane,
This commit caused a segmentation fault on glean texSwizzle test + llvmpipe:
$ gdb --args glean --run results --overwrite --quick --tests texSwizzle
(gdb) r
Starting program: glean --run results --overwrite --quick --tests texSwizzle
[Thread debugging using libthread_db enabled]
Program received signal SIGSEGV, Segmentation fault.
0xfffffffffffffffc in ?? ()
(gdb) bt
#0 0xfffffffffffffffc in ?? ()
#1 0x00007ffff6a26438 in llvm_pipeline_generic (middle=0x76e4a0, fetch_info=0x7fffffffd730, prim_info=0x7fffffffd700)
at src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c:240
#2 0x00007ffff6a266fe in llvm_middle_end_linear_run (middle=0x76e4a0, start=0, count=4, prim_flags=0)
at src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c:358
#3 0x00007ffff697bf23 in vsplit_segment_simple_linear (vsplit=0x76b670, flags=0, istart=0, icount=4) at src/gallium/auxiliary/draw/draw_pt_vsplit_tmp.h:237
#4 0x00007ffff697c228 in vsplit_run_linear (frontend=0x76b670, start=0, count=4) at src/gallium/auxiliary/draw/draw_split_tmp.h:61
#5 0x00007ffff697224e in draw_pt_arrays (draw=0x762510, prim=6, start=0, count=4) at src/gallium/auxiliary/draw/draw_pt.c:142
#6 0x00007ffff6972eb1 in draw_vbo (draw=0x762510, info=0x7fffffffd910) at src/gallium/auxiliary/draw/draw_pt.c:534
#7 0x00007ffff6689f67 in llvmpipe_draw_vbo (pipe=0x72fa10, info=0x7fffffffd910) at src/gallium/drivers/llvmpipe/lp_draw_arrays.c:85
#8 0x00007ffff68037f4 in st_draw_vbo (ctx=0x7c4b30, arrays=0x831c88, prims=0x7fffffffd9e0, nr_prims=1, ib=0x0, index_bounds_valid=1 '\001', min_index=0,
max_index=3, tfb_vertcount=0x0) at src/mesa/state_tracker/st_draw.c:1113
#9 0x00007ffff689d811 in vbo_draw_arrays (ctx=0x7c4b30, mode=6, start=0, count=4, numInstances=1) at src/mesa/vbo/vbo_exec_array.c:635
#10 0x00007ffff689d950 in vbo_exec_DrawArrays (mode=6, start=0, count=4) at src/mesa/vbo/vbo_exec_array.c:667
#11 0x0000000000458205 in GLEAN::TexSwizzleTest::TestSwizzles (this=0x6f10e0) at /var/lib/hudson/jobs/glean-ubuntu64/workspace/src/glean/ttexswizzle.cpp:293
#12 0x0000000000458558 in GLEAN::TexSwizzleTest::runOne (this=0x6f10e0, r=..., w=<optimized out>)
at /var/lib/hudson/jobs/glean-ubuntu64/workspace/src/glean/ttexswizzle.cpp:387
#13 0x0000000000458ec7 in GLEAN::BaseTest<GLEAN::TexSwizzleResult>::run (this=0x6f10e0, environment=<optimized out>)
at /var/lib/hudson/jobs/glean-ubuntu64/workspace/src/glean/tbase.h:317
#14 0x00000000004610b8 in main (argc=7, argv=0x7fffffffdec8) at /var/lib/hudson/jobs/glean-ubuntu64/workspace/src/glean/main.cpp:140
(gdb)
Can you look into it?
Jose
----- Original Message -----
> Module: Mesa
> Branch: master
> Commit: b6d3a435a0e0e53a9e8cc4c4249dc7c2f897a83d
> URL:
> http://cgit.freedesktop.org/mesa/mesa/commit/?id=b6d3a435a0e0e53a9e8cc4c4249dc7c2f897a83d
>
> Author: Jakob Bornecrantz <wallbraker at gmail.com>
> Date: Mon Jan 24 02:11:59 2011 +0100
>
> 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 <marcheu at chromium.org>
> Tested-by: Stéphane Marchesin <marcheu at chromium.org>
>
> ---
>
> src/gallium/auxiliary/draw/draw_context.c | 6 +++
> src/gallium/auxiliary/draw/draw_private.h | 8 ++++
> src/gallium/auxiliary/draw/draw_pt.c | 49
> ++++++++++++++++++++++++---
> src/gallium/auxiliary/draw/draw_pt.h | 2 +-
> src/gallium/auxiliary/draw/draw_pt_vsplit.c | 11 ++++--
> 5 files changed, 66 insertions(+), 10 deletions(-)
>
> diff --git a/src/gallium/auxiliary/draw/draw_context.c
> b/src/gallium/auxiliary/draw/draw_context.c
> index 4ce4445..3c0b1aa 100644
> --- a/src/gallium/auxiliary/draw/draw_context.c
> +++ b/src/gallium/auxiliary/draw/draw_context.c
> @@ -355,6 +355,10 @@ draw_set_vertex_elements(struct draw_context
> *draw,
> {
> assert(count <= PIPE_MAX_ATTRIBS);
>
> + /* We could improve this by only flushing the frontend and the
> fetch part
> + * of the middle. This would avoid recalculating the emit keys.*/
> + draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
> +
> memcpy(draw->pt.vertex_element, elements, count *
> sizeof(elements[0]));
> draw->pt.nr_vertex_elements = count;
> }
> @@ -654,6 +658,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..c3eca97 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,12 @@ struct draw_context
> /* Support prototype passthrough path:
> */
> struct {
> + /* Current active frontend */
> + struct draw_pt_front_end *frontend;
> + unsigned prim;
> + unsigned opt;
> + unsigned eltSize; /* saved eltSize for flushing */
> +
> struct {
> struct draw_pt_middle_end *fetch_emit;
> struct draw_pt_middle_end *fetch_shade_emit;
> @@ -391,6 +398,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..025d539 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 )
> {
> 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..0fed057 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;
>
>
> _______________________________________________
> mesa-commit mailing list
> mesa-commit at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-commit
>
More information about the mesa-dev
mailing list