mesa: Fix and speedup gl_array_object::_MaxElement computation.

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@web.de>
Reviewed-by: Brian Paul <brianp@vmware.com>
This commit is contained in:
Mathias Fröhlich
2011-12-29 13:10:01 +01:00
committed by Mathias Fröhlich
parent 2a207c4bf9
commit 7a1e941ebe
2 changed files with 27 additions and 138 deletions

View File

@@ -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 = 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;
GLbitfield64 enabled;
while (enabled) {
GLint attrib = ffsll(enabled) - 1;
enabled &= ~BITFIELD64_BIT(attrib);
min = update_min(min, &arrayObj->VertexAttrib[attrib]);
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);
}

View File

@@ -62,130 +62,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
@@ -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);