[Mesa-dev] [PATCH 3/3] mesa: Fix and speedup gl_array_object::_MaxElement computation.

Mathias Fröhlich Mathias.Froehlich at gmx.net
Wed Jan 11 23:14:56 PST 2012


Use a bitmask approach to compute gl_array_object::_MaxElement.
To make this work correctly depending on the shader type actually used,
make use of the newly introduced typed bitmask getters.
With this change I gain about 5% draw time on some osgviewer examples.

Signed-off-by: Mathias Fröhlich <Mathias.Froehlich at web.de>
---
 src/mesa/main/arrayobj.c |   41 ++++++++++-----
 src/mesa/main/state.c    |  126 
+---------------------------------------------
 2 files changed, 28 insertions(+), 139 deletions(-)

diff --git a/src/mesa/main/arrayobj.c b/src/mesa/main/arrayobj.c
index 4b3e07b..c2e978f 100644
--- a/src/mesa/main/arrayobj.c
+++ b/src/mesa/main/arrayobj.c
@@ -280,15 +280,26 @@ remove_array_object( struct gl_context *ctx, struct 
gl_array_object *obj )
 
 
 /**
- * Helper for update_arrays().
- * \return  min(current min, array->_MaxElement).
+ * Helper for _mesa_update_array_object_max_element().
+ * \return  min(arrayObj->VertexAttrib[*]._MaxElement).
  */
 static GLuint
-update_min(GLuint min, struct gl_client_array *array)
+compute_max_element(struct gl_array_object *arrayObj, GLbitfield64 enabled)
 {
-   assert(array->Enabled);
-   _mesa_update_array_max_element(array);
-   return MIN2(min, array->_MaxElement);
+   GLuint min = ~((GLuint)0);
+   
+   while (enabled) {
+      struct gl_client_array *client_array;
+      GLint attrib = _mesa_ffsll(enabled) - 1;
+      enabled ^= BITFIELD64_BIT(attrib);
+      
+      client_array = &arrayObj->VertexAttrib[attrib];
+      assert(client_array->Enabled);
+      _mesa_update_array_max_element(client_array);
+      min = MIN2(min, client_array->_MaxElement);
+   }
+   
+   return min;
 }
 
 
@@ -299,17 +310,19 @@ void
 _mesa_update_array_object_max_element(struct gl_context *ctx,
                                       struct gl_array_object *arrayObj)
 {
-   GLbitfield64 enabled = arrayObj->_Enabled;
-   GLuint min = ~0u;
-
-   while (enabled) {
-      GLint attrib = _mesa_ffsll(enabled) - 1;
-      enabled &= ~BITFIELD64_BIT(attrib);
-      min = update_min(min, &arrayObj->VertexAttrib[attrib]);
+   GLbitfield64 enabled;
+
+   if (!ctx->VertexProgram._Current ||
+       ctx->VertexProgram._Current == ctx->VertexProgram._TnlProgram) {
+      enabled = _mesa_array_object_get_enabled_ff(arrayObj);
+   } else if (ctx->VertexProgram._Current->IsNVProgram) {
+      enabled = _mesa_array_object_get_enabled_nv(arrayObj);
+   } else {
+      enabled = _mesa_array_object_get_enabled_arb(arrayObj);
    }
 
    /* _MaxElement is one past the last legal array element */
-   arrayObj->_MaxElement = min;
+   arrayObj->_MaxElement = compute_max_element(arrayObj, enabled);
 }
 
 
diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c
index b910543..adbb0c3 100644
--- a/src/mesa/main/state.c
+++ b/src/mesa/main/state.c
@@ -63,130 +63,6 @@ update_separate_specular(struct gl_context *ctx)
 
 
 /**
- * Helper for update_arrays().
- * \return  min(current min, array->_MaxElement).
- */
-static GLuint
-update_min(GLuint min, struct gl_client_array *array)
-{
-   _mesa_update_array_max_element(array);
-   return MIN2(min, array->_MaxElement);
-}
-
-
-/**
- * Update ctx->Array._MaxElement (the max legal index into all enabled 
arrays).
- * Need to do this upon new array state or new buffer object state.
- */
-static void
-update_arrays( struct gl_context *ctx )
-{
-   struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
-   GLuint i, min = ~0;
-
-   /* find min of _MaxElement values for all enabled arrays.
-    * Note that the generic arrays always take precedence over
-    * the legacy arrays.
-    */
-
-   /* 0 */
-   if (ctx->VertexProgram._Current
-       && arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC0].Enabled) {
-      min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC0]);
-   }
-   else if (arrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled) {
-      min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_POS]);
-   }
-
-   /* 1 */
-   if (ctx->VertexProgram._Enabled
-       && arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC1].Enabled) {
-      min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC1]);
-   }
-   /* no conventional vertex weight array */
-
-   /* 2 */
-   if (ctx->VertexProgram._Enabled
-       && arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC2].Enabled) {
-      min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC2]);
-   }
-   else if (arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) {
-      min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL]);
-   }
-
-   /* 3 */
-   if (ctx->VertexProgram._Enabled
-       && arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC3].Enabled) {
-      min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC3]);
-   }
-   else if (arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) {
-      min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0]);
-   }
-
-   /* 4 */
-   if (ctx->VertexProgram._Enabled
-       && arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC4].Enabled) {
-      min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC4]);
-   }
-   else if (arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1].Enabled) {
-      min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1]);
-   }
-
-   /* 5 */
-   if (ctx->VertexProgram._Enabled
-       && arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC5].Enabled) {
-      min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC5]);
-   }
-   else if (arrayObj->VertexAttrib[VERT_ATTRIB_FOG].Enabled) {
-      min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_FOG]);
-   }
-
-   /* 6 */
-   if (ctx->VertexProgram._Enabled
-       && arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC6].Enabled) {
-      min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC6]);
-   }
-   else if (arrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled) {
-      min = update_min(min, &arrayObj-
>VertexAttrib[VERT_ATTRIB_COLOR_INDEX]);
-   }
-
-   /* 7 */
-   if (ctx->VertexProgram._Enabled
-       && arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC7].Enabled) {
-      min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC7]);
-   }
-
-   /* 8..15 */
-   for (i = 0; i < VERT_ATTRIB_TEX_MAX; i++) {
-      if (ctx->VertexProgram._Enabled
-          && arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC8 + i].Enabled) {
-         min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC8 + 
i]);
-      }
-      else if (i < ctx->Const.MaxTextureCoordUnits
-               && arrayObj->VertexAttrib[VERT_ATTRIB_TEX(i)].Enabled) {
-         min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_TEX(i)]);
-      }
-   }
-
-   /* 16..31 */
-   if (ctx->VertexProgram._Current) {
-      for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) {
-         if (arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled) {
-            min = update_min(min, &arrayObj-
>VertexAttrib[VERT_ATTRIB_GENERIC(i)]);
-         }
-      }
-   }
-
-   if (arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled) {
-      min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG]);
-   }
-
-   /* _MaxElement is one past the last legal array element */
-   arrayObj->_MaxElement = min;
-}
-
-
-/**
  * Update the following fields:
  *   ctx->VertexProgram._Enabled
  *   ctx->FragmentProgram._Enabled
@@ -690,7 +566,7 @@ _mesa_update_state_locked( struct gl_context *ctx )
    }
 
    if (new_state & (_NEW_ARRAY | _NEW_PROGRAM | _NEW_BUFFER_OBJECT))
-      update_arrays( ctx );
+      _mesa_update_array_object_max_element(ctx, ctx->Array.ArrayObj);
 
  out:
    new_prog_state |= update_program_constants(ctx);
-- 
1.7.7.5



More information about the mesa-dev mailing list