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:

committed by
Mathias Fröhlich

parent
2a207c4bf9
commit
7a1e941ebe
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user