Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GLSL: Why is const int array so much slower than normal array?

I have an OpenGL shader written in glsl. I have a globally defined array at the top of the header like this:

const int permutations[256] = int[256](
    64 ,  34 ,  36 , 137 , 120 , 122 , 246 ,  46 ,  79 ,  10 ,  37 , 181,
    ...
    );

When I start the program, it is extremely slow, meaning I have only like 1 frame per second, when displaying a simple teapot using the shader.

However, as soon as I remove the "const" from the above declaration, everything works fine, and I'm back at interactive frame rates.

So, the "problem" is actually already solved... but I was wondering, why this could be the case? Very counterintuitive, as in my experience, using consts usually makes programs faster.


Update

I actually tried to use a Uniform first instead of the const int array, with exactly the same code everywhere else. However, in this case compiling the shader crashes with:

Internal error: assembly compile error for fragment shader at offset
34609:
-- error message -- line 651, column 22:  error: invalid local parameter number
like image 822
Jan Rüegg Avatar asked Dec 01 '11 08:12

Jan Rüegg


People also ask

Can you loop over a sampler array in GLSL?

Under GLSL version 3.30, Sampler arrays (the only opaque type 3.30 provides) can be declared, but they can only be accessed by compile-time integral Constant Expressions. So you cannot loop over an array of samplers, no matter what the array initializer, offset and comparison expressions are.

What are the requirements for array indices in GLSL?

When an array indexing expression, including struct field member accesses, results in an opaque types, the standard has special requirements on those array indices. Under GLSL version 3.30, Sampler arrays (the only opaque type 3.30 provides) can be declared, but they can only be accessed by compile-time integral Constant Expressions.

How can I access an opaque array in GLSL?

Under GLSL 4.00 and above, array indices leading to an opaque value can be accessed by non-compile-time constants, but these index values must be dynamically uniform. The value of those indices must be the same value, in the same execution order, regardless of any non-uniform parameter values, for all shader invocations in the invocation group.

How to declare arrays multidim in GLSL?

Given the presence of this feature, arrays can be declared multidimensionally in GLSL: multidim is an array of 5 elements, where each element is an array of 2 vec3 elements. So multidim.length () is 5, while multidim [0].length () is 2. Arrays can also be declared like this: This may make things more clear. You can combine these:


1 Answers

That's very strange. Most probably you're having driver issues. I've ran included shader code on my Nvidia 540M under windows, and let it run in cycle. In that cycle I called shader program once and measured time (also I had checked with transform feedback if shader is working correctly). Most of cycles ended in 2-3 miliseconds, with some peaks at 25 ms. However removing const identifier had no effect on performance. These are quite small values to measure, but from your description the performance hit of const should be observable even here.

#version 150
const int permutations[256] = int[256](
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
...
246, 247, 248, 249, 250, 251, 252, 253, 254, 255
);

flat out int num1[32];

void main(){
    for(int i = 0; i < 32; i++){
        num1[i] = (permutations[2*i]+permutations[2*i+1])*(permutations[2*i+2]+permutations[2*i+3]);
    }
}

Maybe if you wouldn't mind I could try to run your program on my hardware, but it would have to be compiled for windows and please include all dynamic libraries.

like image 118
Raven Avatar answered Sep 24 '22 23:09

Raven