From 0a4aea0e86a897d9afb9f2a0ec27f03faf8f1b21 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Mon, 2 Jun 2008 12:59:16 +0100 Subject: [PATCH] draw: respect driver's max vertex buffer size --- src/gallium/auxiliary/draw/draw_pipe_vbuf.c | 6 ++++++ src/gallium/auxiliary/draw/draw_private.h | 1 + src/gallium/auxiliary/draw/draw_pt.h | 8 ++++++-- src/gallium/auxiliary/draw/draw_pt_emit.c | 6 +++++- src/gallium/auxiliary/draw/draw_pt_fetch_emit.c | 6 +++++- .../auxiliary/draw/draw_pt_fetch_shade_emit.c | 17 ++++++++++------- .../draw/draw_pt_fetch_shade_pipeline.c | 16 ++++++++++++---- src/gallium/auxiliary/draw/draw_pt_varray.c | 5 ++++- .../auxiliary/draw/draw_pt_varray_tmp_linear.h | 11 +++++++---- src/gallium/auxiliary/draw/draw_pt_vcache.c | 13 ++++++++----- 10 files changed, 64 insertions(+), 25 deletions(-) diff --git a/src/gallium/auxiliary/draw/draw_pipe_vbuf.c b/src/gallium/auxiliary/draw/draw_pipe_vbuf.c index d514e28b77f..9e5597c32c4 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_vbuf.c +++ b/src/gallium/auxiliary/draw/draw_pipe_vbuf.c @@ -387,6 +387,12 @@ vbuf_alloc_vertices( struct vbuf_stage *vbuf ) /* Allocate a new vertex buffer */ vbuf->max_vertices = vbuf->render->max_vertex_buffer_bytes / vbuf->vertex_size; + + /* Must always succeed -- driver gives us a + * 'max_vertex_buffer_bytes' which it guarantees it can allocate, + * and it will flush itself if necessary to do so. If this does + * fail, we are basically without usable hardware. + */ vbuf->vertices = (uint *) vbuf->render->allocate_vertices(vbuf->render, (ushort) vbuf->vertex_size, (ushort) vbuf->max_vertices); diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h index 423f64262b8..1865601cc04 100644 --- a/src/gallium/auxiliary/draw/draw_private.h +++ b/src/gallium/auxiliary/draw/draw_private.h @@ -265,6 +265,7 @@ void draw_pipeline_destroy( struct draw_context *draw ); * These flags expected at first vertex of lines & triangles when * unfilled and/or line stipple modes are operational. */ +#define DRAW_PIPE_MAX_VERTICES (0x1<<12) #define DRAW_PIPE_EDGE_FLAG_0 (0x1<<12) #define DRAW_PIPE_EDGE_FLAG_1 (0x2<<12) #define DRAW_PIPE_EDGE_FLAG_2 (0x4<<12) diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h index 6b8ba1d171b..3d2a9c78b70 100644 --- a/src/gallium/auxiliary/draw/draw_pt.h +++ b/src/gallium/auxiliary/draw/draw_pt.h @@ -84,7 +84,8 @@ struct draw_pt_front_end { struct draw_pt_middle_end { void (*prepare)( struct draw_pt_middle_end *, unsigned prim, - unsigned opt ); + unsigned opt, + unsigned *max_vertices ); void (*run)( struct draw_pt_middle_end *, const unsigned *fetch_elts, @@ -105,6 +106,8 @@ struct draw_pt_middle_end { const ushort *draw_elts, unsigned draw_count ); + int (*get_max_vertex_count)( struct draw_pt_middle_end * ); + void (*finish)( struct draw_pt_middle_end * ); void (*destroy)( struct draw_pt_middle_end * ); }; @@ -158,7 +161,8 @@ boolean draw_pt_get_edgeflag( struct draw_context *draw, struct pt_emit; void draw_pt_emit_prepare( struct pt_emit *emit, - unsigned prim ); + unsigned prim, + unsigned *max_vertices ); void draw_pt_emit( struct pt_emit *emit, const float (*vertex_data)[4], diff --git a/src/gallium/auxiliary/draw/draw_pt_emit.c b/src/gallium/auxiliary/draw/draw_pt_emit.c index cf87cde9965..a02f1f46fed 100644 --- a/src/gallium/auxiliary/draw/draw_pt_emit.c +++ b/src/gallium/auxiliary/draw/draw_pt_emit.c @@ -46,7 +46,8 @@ struct pt_emit { }; void draw_pt_emit_prepare( struct pt_emit *emit, - unsigned prim ) + unsigned prim, + unsigned *max_vertices ) { struct draw_context *draw = emit->draw; const struct vertex_info *vinfo; @@ -139,6 +140,9 @@ void draw_pt_emit_prepare( struct pt_emit *emit, translate_key_sanitize(&hw_key); emit->translate = translate_cache_find(emit->cache, &hw_key); } + + *max_vertices = (draw->render->max_vertex_buffer_bytes / + (vinfo->size * 4)); } diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c index 09bdc5fb5e1..083ce105bfd 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c @@ -90,7 +90,8 @@ struct fetch_emit_middle_end { static void fetch_emit_prepare( struct draw_pt_middle_end *middle, unsigned prim, - unsigned opt ) + unsigned opt, + unsigned *max_vertices ) { struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle; struct draw_context *draw = feme->draw; @@ -196,6 +197,9 @@ static void fetch_emit_prepare( struct draw_pt_middle_end *middle, draw->pt.vertex_buffer[i].buffer_offset), draw->pt.vertex_buffer[i].pitch ); } + + *max_vertices = (draw->render->max_vertex_buffer_bytes / + (vinfo->size * 4)); } diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c index efa6dddbda8..5a1d79d996e 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c @@ -70,7 +70,8 @@ struct fetch_shade_emit { static void fse_prepare( struct draw_pt_middle_end *middle, unsigned prim, - unsigned opt ) + unsigned opt, + unsigned *max_vertices ) { struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle; struct draw_context *draw = fse->draw; @@ -189,6 +190,11 @@ static void fse_prepare( struct draw_pt_middle_end *middle, draw->pt.vertex_buffer[buf].pitch ); } + *max_vertices = (draw->render->max_vertex_buffer_bytes / + (vinfo->size * 4)); + + + //return TRUE; } @@ -204,7 +210,6 @@ static void fse_run_linear( struct draw_pt_middle_end *middle, { struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle; struct draw_context *draw = fse->draw; - unsigned alloc_count = align(count, 4); char *hw_verts; /* XXX: need to flush to get prim_vbuf.c to release its allocation?? @@ -213,7 +218,7 @@ static void fse_run_linear( struct draw_pt_middle_end *middle, hw_verts = draw->render->allocate_vertices( draw->render, (ushort)fse->key.output_stride, - (ushort)alloc_count ); + (ushort)count ); if (!hw_verts) { assert(0); @@ -264,7 +269,6 @@ fse_run(struct draw_pt_middle_end *middle, { struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle; struct draw_context *draw = fse->draw; - unsigned alloc_count = align(fetch_count, 4); void *hw_verts; /* XXX: need to flush to get prim_vbuf.c to release its allocation?? @@ -273,7 +277,7 @@ fse_run(struct draw_pt_middle_end *middle, hw_verts = draw->render->allocate_vertices( draw->render, (ushort)fse->key.output_stride, - (ushort)alloc_count ); + (ushort)fetch_count ); if (!hw_verts) { assert(0); return; @@ -319,7 +323,6 @@ static void fse_run_linear_elts( struct draw_pt_middle_end *middle, { struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle; struct draw_context *draw = fse->draw; - unsigned alloc_count = align(count, 4); char *hw_verts; /* XXX: need to flush to get prim_vbuf.c to release its allocation?? @@ -328,7 +331,7 @@ static void fse_run_linear_elts( struct draw_pt_middle_end *middle, hw_verts = draw->render->allocate_vertices( draw->render, (ushort)fse->key.output_stride, - (ushort)alloc_count ); + (ushort)count ); if (!hw_verts) { assert(0); diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c index eb6988ff03b..25118712a66 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c @@ -51,7 +51,8 @@ struct fetch_pipeline_middle_end { static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle, unsigned prim, - unsigned opt ) + unsigned opt, + unsigned *max_vertices ) { struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle; struct draw_context *draw = fpme->draw; @@ -86,14 +87,21 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle, (boolean)draw->rasterizer->gl_rasterization_rules ); - if (!(opt & PT_PIPELINE)) + if (!(opt & PT_PIPELINE)) { draw_pt_emit_prepare( fpme->emit, - prim ); + prim, + max_vertices ); + + *max_vertices = MAX2( *max_vertices, + DRAW_PIPE_MAX_VERTICES ); + } + else { + *max_vertices = DRAW_PIPE_MAX_VERTICES; + } /* No need to prepare the shader. */ vs->prepare(vs, draw); - } diff --git a/src/gallium/auxiliary/draw/draw_pt_varray.c b/src/gallium/auxiliary/draw/draw_pt_varray.c index f19e8850b3e..f5495a80c78 100644 --- a/src/gallium/auxiliary/draw/draw_pt_varray.c +++ b/src/gallium/auxiliary/draw/draw_pt_varray.c @@ -45,6 +45,9 @@ struct varray_frontend { unsigned fetch_start; + unsigned driver_fetch_max; + unsigned fetch_max; + struct draw_pt_middle_end *middle; unsigned input_prim; @@ -183,7 +186,7 @@ static void varray_prepare(struct draw_pt_front_end *frontend, varray->output_prim = decompose_prim[prim]; varray->middle = middle; - middle->prepare(middle, varray->output_prim, opt); + middle->prepare(middle, varray->output_prim, opt, &varray->fetch_max ); } diff --git a/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h b/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h index 114ed371a06..6e5e30f38e5 100644 --- a/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h +++ b/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h @@ -40,7 +40,7 @@ static void FUNC(struct draw_pt_front_end *frontend, case PIPE_PRIM_QUAD_STRIP: for (j = 0; j < count;) { unsigned remaining = count - j; - unsigned nr = trim( MIN2(FETCH_MAX, remaining), first, incr ); + unsigned nr = trim( MIN2(varray->fetch_max, remaining), first, incr ); varray_flush_linear(varray, start + j, nr); j += nr; if (nr != remaining) @@ -50,8 +50,9 @@ static void FUNC(struct draw_pt_front_end *frontend, case PIPE_PRIM_LINE_LOOP: if (count >= 2) { + unsigned fetch_max = MIN2(FETCH_MAX, varray->fetch_max); for (j = 0; j + first <= count; j += i) { - unsigned end = MIN2(FETCH_MAX, count - j); + unsigned end = MIN2(fetch_max, count - j); end -= (end % incr); for (i = 1; i < end; i++) { LINE(varray, i - 1, i); @@ -66,9 +67,10 @@ static void FUNC(struct draw_pt_front_end *frontend, case PIPE_PRIM_POLYGON: - case PIPE_PRIM_TRIANGLE_FAN: + case PIPE_PRIM_TRIANGLE_FAN: { + unsigned fetch_max = MIN2(FETCH_MAX, varray->fetch_max); for (j = 0; j + first <= count; j += i) { - unsigned end = MIN2(FETCH_MAX, count - j); + unsigned end = MIN2(fetch_max, count - j); end -= (end % incr); for (i = 2; i < end; i++) { TRIANGLE(varray, 0, i - 1, i); @@ -78,6 +80,7 @@ static void FUNC(struct draw_pt_front_end *frontend, varray_flush(varray); } break; + } default: assert(0); diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache.c b/src/gallium/auxiliary/draw/draw_pt_vcache.c index ad86ab42925..2eafe270bc0 100644 --- a/src/gallium/auxiliary/draw/draw_pt_vcache.c +++ b/src/gallium/auxiliary/draw/draw_pt_vcache.c @@ -36,8 +36,8 @@ #include "draw/draw_pt.h" -#define CACHE_MAX 1024 -#define FETCH_MAX 4096 +#define CACHE_MAX 256 +#define FETCH_MAX 256 #define DRAW_MAX (16*1024) struct vcache_frontend { @@ -52,6 +52,7 @@ struct vcache_frontend { unsigned draw_count; unsigned fetch_count; + unsigned fetch_max; struct draw_pt_middle_end *middle; @@ -296,10 +297,12 @@ static void vcache_check_run( struct draw_pt_front_end *frontend, ushort *storage = NULL; - if (0) debug_printf("fetch_count %d draw_count %d\n", fetch_count, draw_count); + if (0) debug_printf("fetch_count %d fetch_max %d draw_count %d\n", fetch_count, + vcache->fetch_max, + draw_count); if (max_index == 0xffffffff || - fetch_count >= FETCH_MAX || + fetch_count >= vcache->fetch_max || fetch_count > draw_count) { if (0) debug_printf("fail\n"); goto fail; @@ -409,7 +412,7 @@ static void vcache_prepare( struct draw_pt_front_end *frontend, vcache->output_prim = draw_pt_reduced_prim(prim); vcache->middle = middle; - middle->prepare( middle, vcache->output_prim, opt ); + middle->prepare( middle, vcache->output_prim, opt, &vcache->fetch_max ); } -- 2.30.2