The wierdest GLSL Behavior

I am accessing an array of vec4s. When I use 215
like arr[215 / 4][215 % 4]

I get the correct behavior

However. When I do.
int h = 215
arr[h / 4][h% 4]

I get different behavior!

Does it have anything to do with layouts…? I am completely lost.

What can I possibly check?


int h = 215
arr[h / 4][h% 4]

The behavior of that ought to be “it didn’t compile.”

h here is an integer, but it is not an integral constant expression. And array definitions must use integral constant expressions for their sizes.

You can make it an integral constant expression by declaring h with const.

THANK YOU!!! SOOOOOOOO MUCH!!!

I knew arrays had to be const when using a variable to initialize them, but even accessing them with variable–that variable too must be const–interesting.

I went back to my UBOs to see if I sent the data down correctly, and if I was reading it write. Such a little thing, such big ramifications. Thank you SOO MUCH.

const int h = some value from UBO

That does not work.

therefore I cant do

arr[h/4][h%4]

How would I query and array based on an input from a UBO?

I am reading something that VBO’s and UBO’s are opaque types, so they can’t be converted to a constant expression?

BUT! Then I saw this “Opaque types cannot be l-values. The only expressions that they can be a part of are array-indexing”

array_indexing is exactly what I am trying to do…

Array dimensions must be integral constant expressions. Array indices only need to be dynamically uniform (and even that requirement only applies in some cases).

Are you providing an explicit size for the array in its declaration? If you aren’t (e.g. you’re using “vec4 arr[];”, indicating an array of unspecified size), the compiler will infer the size from the expressions used to index it, but in order for it to do so, all such expressions must be integral constant expressions.

It looks something along the lines of
uniform exp{
Ivec4 arr[215]:
Ivec4 indexes_of_arr_per_vertex[215];
};

I’m guessing it has a definite constant literal size?

But arr[indexes_of_arr_per_vertex] is undefined behavior

OK, let me try to explain this more fully.

When declaring an array, the array size must be an integral constant expression.

When accessing an array, the array index can be any expression that is convertible to an integer. There are a few exceptions to this, but this would only be for arrays of opaque types and arrays of buffer-backed interface blocks (not arrays in interface blocks; the block itself is an array). In those cases, the expression must be dynamically uniform.

I was confused earlier, thinking you were declaring an array rather than fetching values from it.

const int h = some value from UBO

That does not work.

Of course not. const is not magic. If you initialize a const-qualified variable with an expression that is not a constant expression, it cannot transform the result of that expression into a compile-time constant. So it does the best it can: preventing you from modifying the value of h after initializing it.

const int h = SOMETHING only results in a constant expression if SOMETHING is also a constant expression.

Older versions of GLSL required that const qualified variables be initialized with constant expressions. But that’s no longer the case since GL 4.20.

Thanks for the explanation. Const. is a little different that C. So in the case that I want to access an array in an interface uniform block, it needs to be dynamically uniform.

What I have read is “uniform​-qualified variables are dynamically uniform”

So what exactly is the issue w/ my approach above?

I have a definite size, and indexing the array with a dynamically uniform quantity.

No! I specifically said not that: “not arrays in interface blocks; the block itself is an array.”

So:



uniform ArrayInBlock
{
  vec4 InTheBlock[4];
} arrayInBlock;

uniform ArrayOfBlocks
{
  vec4 InTheBlock;
} arrayOfBlocks[4];

arrayInBlock.InTheBlock[Any_Integer_Expression];

arrayOfBlocks[Dynamically_Uniform_Expression].InTheBlock;

See the difference?

How could we know? You’ve posted virtually none of your actual code. It could be lots of things, and we can’t do anything more than guess.

I don’t want to convolute things with too much code. So before I just post it all, I want to make sure I got this right.
When indexing an array in an interface block–and NOT and array of an interface blocks–any integer expression will do. This naturally makes sense.

Thusly

uniform block{
ivec4 arr[215];
};

int h = 215;
arr[h / 4][h% 4];

should equal

arr[215 / 4][215 % 4];

Is that correct?

SOLVED!

Alright. The problem was weird. I was using dvec4s and using any integer expression to query the values like this

uniform block{
dvec4 arr[110];
};

then doing
int h = 15;

arr[h / 4][h % 5];

however, this apparently does compile–but with undefined behavior. When h is const, the output changes–then when it is not.

but THIS!!

uniform block{
vec4 arr[110];
};

then doing
int h = 15;

arr[h / 4][h % 5];

compiles with perfectly rational behavior. I am guessing its a limitation of the GPU? Thanks for the assist guys.

Also how can tag my code as code so it appears in a blue box on this forum?

arr[h / 4][h % 5];

I’m going to assume that’s h % 5 was supposed to be h % 4.

[QUOTE=Septimra;1272130]SOLVED!

Alright. The problem was weird. I was using dvec4s and using any integer expression to query the values like this[/quote]

So you found a driver bug. You should report that.

Also… why were you sending doubles?

You use [ code ] tags (without the spaces).

So you found a driver bug.

Wow, thats so cool. I was sending them because i was using atof that returns doubles so i just went with it for now. I was gonna make em floats eventually, but then this happened. If forced me to clean my code, so this was for the best. If forced me to do tons of research and really understand glsl and the hardware more, so I’m not complaining. Really for what I am doing, floats are just fine.

and yea completely meant % 4

 arr[h / 4][h % 4];