GLSL indexing into uniform array with variable length
Asked Answered
E

1

12

I am passing an uniform array to geometry shader and want to index into it using a variable. I can use variable length array & index with fixed number (numeric constant) OR I can define a fixed length array & index using varible. However I can't index into variable length array using a variable.

Below is pseudo code for geometry shader with cases that work & case that doesn't work

This works:

    uniform vec2 dimensions[2];
    // some code which computes index which is an int
    float dimX = dimensions[index].x;

This works:

    uniform vec2 dimensions[];
    // some code which computes index which is an int
    float dimX = dimensions[0].x;

This doesn't work:

    uniform vec2 dimensions[];
    // some code which computes index which is an int
    float dimX = dimensions[index].x; 

Is it possible to do something like this?

Eradis answered 8/11, 2013 at 21:26 Comment(0)
D
21

Sadly, no this is not possible. You did not include the GLSL version you are targeting but did mention geometry shaders, so I have included the relevant part of the GLSL 1.5 spec. below:

GLSL Specification (Version 1.5) - 4.1.9 Arrays - pp. 25.

Variables of the same type can be aggregated into arrays by declaring a name followed by brackets ( [ ] ) enclosing an optional size. When an array size is specified in a declaration, it must be an integral constant expression (see Section 4.3.3 “Constant Expressions” ) greater than zero. If an array is indexed with an expression that is not an integral constant expression, or if an array is passed as an argument to a function, then its size must be declared before any such use.

While desktop GLSL is much more forgiving when it comes to indexing arrays with non-const expressions than GLSL ES, you still have to work within some limitations. The same way that texture lookups are often used to overcome non-const array indexing in OpenGL ES, you may be able to work around this by using a 1D texture lookup in your geometry shader. I have to wonder if you really need this functionality that badly though?

It is a good idea to define an upper limit to your uniform array anyway, because the GLSL spec. only requires an implementation provide 1024 uniform components (e.g. 1024 float, 256 vec4, 64 mat4 or some combination of each) in the geometry shader stage. If your array has a known maximum size at compile time you can avoid trouble later down the road associated with unknowingly exceeding this limitation.

UPDATE:

Since you mentioned GLSL 4.x, I would like to point out a newer feature in OpenGL known as Shader Storage Buffer Objects. Using SSBOs, it may be possible to use an array with dynamic length at run-time for your purposes. You can query the length of an SSBO using .length () in the shader, and handle range validation yourself. However, I think this is probably overkill but worth mentioning nevertheless.

Diligent answered 8/11, 2013 at 21:43 Comment(4)
Thanks for your response. I'm using on desktop with GLSL 4.+.Eradis
@Jitu: This applies to GLSL 4.x as well, the reason you cannot index an array with an unknown size using a non-const expression is because there is no way to verify array bounds / size requirements at compile-time in such a situation. One possible solution since you mentioned GLSL 4.x is something called Shader Storage Blocks (SSBO), they can have undefined length.. textures are the more portable way of accomplishing this, but SSBOs are definitely the future.Diligent
I accidentally hit enter before finishing my response. Number of elements in dimensions array is always gonna be under 20 or so, however I was curious why it doesn't work (now that you pointed to the specs, i know why). So I guess I can just declare it to be of size 20, upper limit in my case. I would like to verify one more thing, if I declare my uniform to be of size 20, however in C++ code I fill in only 5 elements in buffer, only space for 5 elements (and not 20) is allocated right? Also I wanted to avoid 1D texture because its slower than uniforms. Thanks, JituEradis
@Jitu: No, it actually has to reserve enough storage for every element in a uniform array declared vec2 dimensions [20];. But since each GLSL program already gives you enough storage for at least 1024 components as I mentioned in the answer, you should be fine (1024-40=984). Textures and vertex buffers require far more storage than uniforms ever will :)Diligent

© 2022 - 2024 — McMap. All rights reserved.