Common practice of glGetActiveUniform leads to O(N²) behavior in Mesa
The common usage to grab all the uniform data from a shader boils down the following:
glGetProgramiv( programObject, GL_ACTIVE_UNIFORMS, &uniformCount );
for( GLuint index = 0; index < uniformCount; index++ )
{
glGetActiveUniform( programObject, index, uniformLength, NULL,
&arraySize, &glType, uniformName );
location = glGetUniformLocation( programObject, uniformName );
}
Unfortunately to grab uniform location data, we need glGetUniformLocation which uses a char* instead of an index. Poor API choice I guess.
_mesa_program_resource_location uses _mesa_program_resource_find_name to find it, performing a linear search across all active uniforms.
Hence effectively the loop becomes:
for( GLuint index = 0; index < uniformCount; index++ )
{
glGetActiveUniform( programObject, index, uniformLength, NULL,
&arraySize, &glType, uniformName );
for( GLuint j = 0; j < uniformCount; j++ )
return matches( j, uniformName ); //pseudo code
}
I noticed this because a compute shader was taking unusually long to compile and when I take a deeper look, it was because my shader happens to have 16391 active uniforms. I'm attaching the shader source code:
The quickest solution would be to implement a hashed table to store name -> index lookup.
I have no complaints if Mesa prefers to create an extension to grab uniform locations using indices instead of referencing by name, I can live with that.