Using the Max Fragment Uniform Components GLSL field as the size of a uniform array

Hello !

This may be a simple question, but is it possible in a fragment shader to use the gl_MaxFragmentUniformComponents field as the size of a float (or vec_) array uniform.

For example, is it possible to do something like this :

uniform vec4 array[gl_MaxFragmentUniformComponents / 4];

Or is there any other way to achieve a similar result while not hard coding the limit in a #DEFINE directive ? (with the code above, linking shaders fails, but the actual fragment shader log is empty).

Thanks !

Well, what error do you get out of the linking log? Linking and compilation are separate steps with separate errors.

Also, I would not expect the maximum number of uniform components to actually be the maximum usable number of components. Implementation often fudge the maximum, as they may require some uniforms for implementing certain GLSL features.

I would suggest that you use a UBO for this. The limits are far more likely to be respected, and they’re likely to be bigger as well.

Haha well I didn’t even know there was a linking log, now I do ^^’.

This is what it says :

Fragment info
-------------
(0) : error C6020: Constant register limit exceeded at screenTexture; more than 1024 registers needed to compile program
(0) : error C6020: Constant register limit exceeded at screenResolution; more than 1024 registers needed to compile program
(0) : error C6020: Constant register limit exceeded at region; more than 1024 registers needed to compile program
(0) : error C6020: Constant register limit exceeded at strengthTexture; more than 1024 registers needed to compile program
(0) : error C6020: Constant register limit exceeded at strengthResolution; more than 1024 registers needed to compile program
(0) : error C6020: Constant register limit exceeded at strengthPosition; more than 1024 registers needed to compile program
(0) : error C6020: Constant register limit exceeded at kernelSize; more than 1024 registers needed to compile program

So it seems like the issue is that while calling glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &uniforms) returns 4096 in my case, only 1024 are available ? Could that be the issue ?

Also, I’ve never used UBOs (though I’ve read about them a bit) so this might be a solution…

EDIT

Since then, I’ve tried changing the array size, and this is the top of my fragment shader, with all the uniforms :

uniform sampler2D screenTexture;
uniform ivec2 screenResolution;
uniform vec4 region = vec4(0, 0, 1, 1);

uniform sampler2D strengthTexture;
uniform ivec2 strengthResolution;
uniform ivec2 strengthPosition;

uniform vec4 kernel[(gl_MaxFragmentUniformComponents - 25) / 4];
uniform ivec2 kernelSize;

This works, but using only one more element in the kernel array leads to the same linking error as before (this is the limit). While other than the kernel, there should be 14 other uniforms used (2 sampler2D, 4 ivec2 and 1 vec4, so 2*1 + 4*2 + 1*4 = 14), I need to remove 25 from the count so that it works.

Also, it seems like I can have a float array with an undefined size ?

Thanks Alphonse !

I think it means you’re using more than 1024 vec4s due to the implementation having some “hidden” uniforms. Or possibly exceeding GL_MAX_UNIFORM_LOCATIONS, which is the maximum number of default-block uniforms across all stages.

In general, it’s unwise to use the default uniform block for “large” arrays. Use UBOs or SSBOs or, as a last resort on older versions, textures.

Except for the last member of a shader storage block, arrays must be sized explicitly (in the declaration) or implicitly (by indexing them only with integral constant expressions).

Oh actually since I’m doing image convolution, an image kernel would work perfectly ! And i’d be able to use a kernel as large as I want.

Thanks all !