draw: respect driver's max vertex buffer size
authorKeith Whitwell <keith@tungstengraphics.com>
Mon, 2 Jun 2008 11:59:16 +0000 (12:59 +0100)
committerKeith Whitwell <keith@tungstengraphics.com>
Wed, 4 Jun 2008 10:25:54 +0000 (11:25 +0100)
src/gallium/auxiliary/draw/draw_pipe_vbuf.c
src/gallium/auxiliary/draw/draw_private.h
src/gallium/auxiliary/draw/draw_pt.h
src/gallium/auxiliary/draw/draw_pt_emit.c
src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
src/gallium/auxiliary/draw/draw_pt_varray.c
src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h
src/gallium/auxiliary/draw/draw_pt_vcache.c

index d514e28..9e5597c 100644 (file)
@@ -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);
index 423f642..1865601 100644 (file)
@@ -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)
index 6b8ba1d..3d2a9c7 100644 (file)
@@ -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],
index cf87cde..a02f1f4 100644 (file)
@@ -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));
 }
 
 
index 09bdc5f..083ce10 100644 (file)
@@ -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));
 }
 
 
index efa6ddd..5a1d79d 100644 (file)
@@ -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);
index eb6988f..2511871 100644 (file)
@@ -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);
-
 }
 
 
index f19e885..f5495a8 100644 (file)
@@ -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 );
 }
 
 
index 114ed37..6e5e30f 100644 (file)
@@ -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);
index ad86ab4..2eafe27 100644 (file)
@@ -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 );
 }