From: Ian Romanick Date: Mon, 10 Jun 2013 17:39:28 +0000 (-0700) Subject: glsl: Generate smaller values for uniform locations X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=cfa3c5ad828f56559a6cc2de299f993b8e748ea4;p=mesa.git glsl: Generate smaller values for uniform locations Previously we would generate uniform locations as (slot << 16) + array_index. We do this to handle applications that assume the location of a[2] will be +1 from the location of a[1]. This resulted in every uniform location being at least 0x10000. The OpenGL 4.3 spec was amended to require this behavior, but previous versions did not require locations of array (or structure) members be sequential. We've now encountered two applications that assume uniform values will be "small." As far as we can tell, these applications store the GLint returned by glGetUniformLocation in a int16_t or possibly an int8_t. THIS BEHAVIOR IS NOT GUARANTEED OR IMPLIED BY ANY VERSION OF OpenGL. Other implementations happen to have both these behaviors (sequential array elements and small values) since OpenGL 2.0, so let's just match their behavior. Fixes "3D Bowling" on Android. NOTE: This is a candidate for stable release branches. Signed-off-by: Ian Romanick Reviewed-by: Brian Paul Reviewed-and-tested-by: Chad Versace --- diff --git a/src/glsl/link_uniforms.cpp b/src/glsl/link_uniforms.cpp index 84680bebd9a..208778e4ada 100644 --- a/src/glsl/link_uniforms.cpp +++ b/src/glsl/link_uniforms.cpp @@ -739,7 +739,19 @@ link_assign_uniform_locations(struct gl_shader_program *prog) sizeof(prog->_LinkedShaders[i]->SamplerTargets)); } - prog->UniformLocationBaseScale = (1U<<16); + /* Determine the size of the largest uniform array queryable via + * glGetUniformLocation. Using this as the location scale guarantees that + * there is enough "room" for the array index to be stored in the low order + * part of the uniform location. It also makes the locations be more + * tightly packed. + */ + unsigned max_array_size = 1; + for (unsigned i = 0; i < num_user_uniforms; i++) { + if (uniforms[i].array_elements > max_array_size) + max_array_size = uniforms[i].array_elements; + } + + prog->UniformLocationBaseScale = max_array_size; #ifndef NDEBUG for (unsigned i = 0; i < num_user_uniforms; i++) {