This saves mapping the index buffer to get a bounds on the indices that
drivers just drop on the floor in the VBO case (cache win), saves a bonus
walk of the indices in the CheckArrayBounds case, and other miscellaneous
validation.  On intel it's a particularly a large win (50-100% in my app)
because even though we let the indices stay in both CPU and GPU caches, we
still end up waiting for the GPU to be done with the buffer before reading
from it.

Drivers supporting draw_prims must now handle min_index == ~0 indicating that
min/max_index are not computed, if they want to use these fields.
---
 src/mesa/drivers/dri/i965/brw_draw.c        |   52 +++-------
 src/mesa/drivers/dri/i965/brw_draw_upload.c |    1 +
 src/mesa/drivers/dri/r300/r300_draw.c       |    6 +
 src/mesa/tnl/t_draw.c                       |    3 +
 src/mesa/vbo/vbo.h                          |    5 +-
 src/mesa/vbo/vbo_exec_array.c               |  151 ++++++++++++++-------------
 6 files changed, 107 insertions(+), 111 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_draw.c 
b/src/mesa/drivers/dri/i965/brw_draw.c
index 5152c3f..01e5f36 100644
--- a/src/mesa/drivers/dri/i965/brw_draw.c
+++ b/src/mesa/drivers/dri/i965/brw_draw.c
@@ -422,34 +422,6 @@ static GLboolean brw_try_draw_prims( GLcontext *ctx,
    return retval;
 }
 
-static GLboolean brw_need_rebase( GLcontext *ctx,
-                                 const struct gl_client_array *arrays[],
-                                 const struct _mesa_index_buffer *ib,
-                                 GLuint min_index )
-{
-   if (min_index == 0) 
-      return GL_FALSE;
-
-   if (ib) {
-      if (!vbo_all_varyings_in_vbos(arrays))
-        return GL_TRUE;
-      else
-        return GL_FALSE;
-   }
-   else {
-      /* Hmm.  This isn't quite what I wanted.  BRW can actually
-       * handle the mixed case well enough that we shouldn't need to
-       * rebase.  However, it's probably not very common, nor hugely
-       * expensive to do it this way:
-       */
-      if (!vbo_all_varyings_in_vbos(arrays))
-        return GL_TRUE;
-      else
-        return GL_FALSE;
-   }
-}
-                                 
-
 void brw_draw_prims( GLcontext *ctx,
                     const struct gl_client_array *arrays[],
                     const struct _mesa_prim *prim,
@@ -460,16 +432,20 @@ void brw_draw_prims( GLcontext *ctx,
 {
    GLboolean retval;
 
-   /* Decide if we want to rebase.  If so we end up recursing once
-    * only into this function.
-    */
-   if (brw_need_rebase( ctx, arrays, ib, min_index )) {
-      vbo_rebase_prims( ctx, arrays, 
-                       prim, nr_prims, 
-                       ib, min_index, max_index, 
-                       brw_draw_prims );
-      
-      return;
+   if (!vbo_all_varyings_in_vbos(arrays)) {
+      if (min_index == ~0)
+        vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index);
+
+      /* Decide if we want to rebase.  If so we end up recursing once
+       * only into this function.
+       */
+      if (min_index != 0) {
+        vbo_rebase_prims(ctx, arrays,
+                         prim, nr_prims,
+                         ib, min_index, max_index,
+                         brw_draw_prims );
+        return;
+      }
    }
 
    /* Make a first attempt at drawing:
diff --git a/src/mesa/drivers/dri/i965/brw_draw_upload.c 
b/src/mesa/drivers/dri/i965/brw_draw_upload.c
index 4bdb373..a4457b8 100644
--- a/src/mesa/drivers/dri/i965/brw_draw_upload.c
+++ b/src/mesa/drivers/dri/i965/brw_draw_upload.c
@@ -411,6 +411,7 @@ static void brw_prepare_vertices(struct brw_context *brw)
          */
         assert(input->offset < input->bo->size);
       } else {
+        assert(min_index != ~0);
         input->count = input->glarray->StrideB ? max_index + 1 - min_index : 1;
         if (input->bo != NULL) {
            /* Already-uploaded vertex data is present from a previous
diff --git a/src/mesa/drivers/dri/r300/r300_draw.c 
b/src/mesa/drivers/dri/r300/r300_draw.c
index fcfd309..bc5a234 100644
--- a/src/mesa/drivers/dri/r300/r300_draw.c
+++ b/src/mesa/drivers/dri/r300/r300_draw.c
@@ -476,6 +476,12 @@ static void r300DrawPrims(GLcontext *ctx,
        limits.max_indices = 65535;
        limits.max_vb_size = 1024*1024;
 
+       /* This check should get folded into just the places that
+        * min/max index are really needed.
+        */
+       if (min_index == ~0)
+          vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index);
+
        if (min_index) {
                vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib, min_index, 
max_index, r300DrawPrims );
                return;
diff --git a/src/mesa/tnl/t_draw.c b/src/mesa/tnl/t_draw.c
index 2ec65d5..d093293 100644
--- a/src/mesa/tnl/t_draw.c
+++ b/src/mesa/tnl/t_draw.c
@@ -388,6 +388,9 @@ void _tnl_draw_prims( GLcontext *ctx,
                      prim[i].count);
    }
 
+   if (min_index == ~0)
+      vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index);
+
    if (min_index) {
       /* We always translate away calls with min_index != 0. 
        */
diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h
index 5362226..9052ce3 100644
--- a/src/mesa/vbo/vbo.h
+++ b/src/mesa/vbo/vbo.h
@@ -112,7 +112,10 @@ void vbo_rebase_prims( GLcontext *ctx,
                       GLuint min_index,
                       GLuint max_index,
                       vbo_draw_func draw );
-
+void
+vbo_get_minmax_index(GLcontext *ctx, const struct _mesa_prim *prim,
+                    const struct _mesa_index_buffer *ib,
+                    GLuint *min_index, GLuint *max_index);
 
 void vbo_use_buffer_objects(GLcontext *ctx);
 
diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c
index f4b9b2f..9ea3e4a 100644
--- a/src/mesa/vbo/vbo_exec_array.c
+++ b/src/mesa/vbo/vbo_exec_array.c
@@ -41,15 +41,29 @@
 /**
  * Compute min and max elements for glDraw[Range]Elements() calls.
  */
-static void
-get_minmax_index(GLuint count, GLuint type, const GLvoid *indices,
-                 GLuint *min_index, GLuint *max_index)
+void
+vbo_get_minmax_index(GLcontext *ctx,
+                    const struct _mesa_prim *prim,
+                    const struct _mesa_index_buffer *ib,
+                    GLuint *min_index, GLuint *max_index)
 {
    GLuint i;
+   GLsizei count = prim->count;
+   const void *indices;
+
+   if (ib->obj->Name) {
+      const GLvoid *map = ctx->Driver.MapBuffer(ctx,
+                                                GL_ELEMENT_ARRAY_BUFFER_ARB,
+                                                GL_READ_ONLY,
+                                                ib->obj);
+      indices = ADD_POINTERS(map, ib->ptr);
+   } else {
+      indices = ib->ptr;
+   }
 
-   switch(type) {
+   switch (ib->type) {
    case GL_UNSIGNED_INT: {
-      const GLuint *ui_indices = (const GLuint *)indices;
+      const GLuint *ui_indices = (const GLuint *)ib->ptr;
       GLuint max_ui = ui_indices[count-1];
       GLuint min_ui = ui_indices[0];
       for (i = 0; i < count; i++) {
@@ -88,6 +102,12 @@ get_minmax_index(GLuint count, GLuint type, const GLvoid 
*indices,
       assert(0);
       break;
    }
+
+   if (ib->obj->Name != 0) {
+      ctx->Driver.UnmapBuffer(ctx,
+                             GL_ELEMENT_ARRAY_BUFFER_ARB,
+                             ib->obj);
+   }
 }
 
 
@@ -566,53 +586,18 @@ dump_element_buffer(GLcontext *ctx, GLenum type)
                            ctx->Array.ElementArrayBufferObj);
 }
 
-
-static void GLAPIENTRY
-vbo_exec_DrawRangeElements(GLenum mode,
-                          GLuint start, GLuint end,
-                          GLsizei count, GLenum type, const GLvoid *indices)
+/* Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements */
+static void
+vbo_validated_drawrangeelements(GLcontext *ctx, GLenum mode,
+                               GLuint start, GLuint end,
+                               GLsizei count, GLenum type,
+                               const GLvoid *indices)
 {
-   GET_CURRENT_CONTEXT(ctx);
    struct vbo_context *vbo = vbo_context(ctx);
    struct vbo_exec_context *exec = &vbo->exec;
    struct _mesa_index_buffer ib;
    struct _mesa_prim prim[1];
 
-   if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count,
-                                          type, indices ))
-      return;
-
-   if (end >= ctx->Array.ArrayObj->_MaxElement) {
-      /* the max element is out of bounds of one or more enabled arrays */
-      _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, count %d, "
-                    "type 0x%x, indices=%p)\n"
-                    "\tindex=%u is out of bounds (max=%u)  "
-                    "Element Buffer %u (size %d)",
-                    start, end, count, type, indices, end,
-                    ctx->Array.ArrayObj->_MaxElement - 1,
-                    ctx->Array.ElementArrayBufferObj->Name,
-                    ctx->Array.ElementArrayBufferObj->Size);
-
-      if (0)
-         dump_element_buffer(ctx, type);
-
-      if (0)
-         _mesa_print_arrays(ctx);
-      return;
-   }
-   else if (0) {
-      _mesa_printf("glDraw[Range]Elements"
-                   "(start %u, end %u, type 0x%x, count %d) ElemBuf %u\n",
-                   start, end, type, count,
-                   ctx->Array.ElementArrayBufferObj->Name);
-   }
-
-#if 0
-   check_draw_elements_data(ctx, count, type, indices);
-#else
-   (void) check_draw_elements_data;
-#endif
-
    FLUSH_CURRENT( ctx, 0 );
 
    if (ctx->NewState)
@@ -623,13 +608,13 @@ vbo_exec_DrawRangeElements(GLenum mode,
       return;
    }
 
-   bind_arrays( ctx );
-
    if (ctx->NewState)
       _mesa_update_state( ctx );
 
+   bind_arrays( ctx );
+
    ib.count = count;
-   ib.type = type; 
+   ib.type = type;
    ib.obj = ctx->Array.ElementArrayBufferObj;
    ib.ptr = indices;
 
@@ -676,41 +661,63 @@ vbo_exec_DrawRangeElements(GLenum mode,
    vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, start, end );
 }
 
-
 static void GLAPIENTRY
-vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type,
-                      const GLvoid *indices)
+vbo_exec_DrawRangeElements(GLenum mode,
+                          GLuint start, GLuint end,
+                          GLsizei count, GLenum type, const GLvoid *indices)
 {
    GET_CURRENT_CONTEXT(ctx);
-   GLuint min_index = 0;
-   GLuint max_index = 0;
 
-   if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
+   if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count,
+                                          type, indices ))
       return;
 
-   if (!vbo_validate_shaders(ctx)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawElements(bad shader)");
+   if (end >= ctx->Array.ArrayObj->_MaxElement) {
+      /* the max element is out of bounds of one or more enabled arrays */
+      _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, count %d, "
+                    "type 0x%x, indices=%p)\n"
+                    "\tindex=%u is out of bounds (max=%u)  "
+                    "Element Buffer %u (size %d)",
+                    start, end, count, type, indices, end,
+                    ctx->Array.ArrayObj->_MaxElement - 1,
+                    ctx->Array.ElementArrayBufferObj->Name,
+                    ctx->Array.ElementArrayBufferObj->Size);
+
+      if (0)
+         dump_element_buffer(ctx, type);
+
+      if (0)
+         _mesa_print_arrays(ctx);
       return;
    }
+   else if (0) {
+      _mesa_printf("glDraw[Range]Elements"
+                   "(start %u, end %u, type 0x%x, count %d) ElemBuf %u\n",
+                   start, end, type, count,
+                   ctx->Array.ElementArrayBufferObj->Name);
+   }
 
-   if (ctx->Array.ElementArrayBufferObj->Name) {
-      const GLvoid *map = ctx->Driver.MapBuffer(ctx,
-                                                GL_ELEMENT_ARRAY_BUFFER_ARB,
-                                                GL_READ_ONLY,
-                                                
ctx->Array.ElementArrayBufferObj);
+#if 0
+   check_draw_elements_data(ctx, count, type, indices);
+#else
+   (void) check_draw_elements_data;
+#endif
+
+   vbo_validated_drawrangeelements(ctx, mode, start, end,
+                                  count, type, indices);
+}
 
-      get_minmax_index(count, type, ADD_POINTERS(map, indices),
-                       &min_index, &max_index);
 
-      ctx->Driver.UnmapBuffer(ctx,
-                             GL_ELEMENT_ARRAY_BUFFER_ARB,
-                             ctx->Array.ElementArrayBufferObj);
-   }
-   else {
-      get_minmax_index(count, type, indices, &min_index, &max_index);
-   }
+static void GLAPIENTRY
+vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type,
+                      const GLvoid *indices)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
+      return;
 
-   vbo_exec_DrawRangeElements(mode, min_index, max_index, count, type, 
indices);
+   vbo_validated_drawrangeelements(ctx, mode, ~0, ~0, count, type, indices);
 }
 
 
-- 
1.6.3.3


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with 
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Mesa3d-dev mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mesa3d-dev

Reply via email to