GLSL break command

I'm currently learning how to create shaders in GLSL for the game engine I'm working on, and I have a question regarding a language that puzzles me. I found out that in shader versions below 3.0 you cannot use homogeneous variables in a loop state. For example, the following code will not work on shaders older than 3.0.

for (int i = 0; i < uNumLights; i++) { ............... } 

But is it possible to replace this with a loop with a fixed number of iterations, but containing a conditional statement that breaks the loop, if in this case I am larger than uNumLights ?. Example:

 for (int i = 0; i < MAX_LIGHTS; i++) { if(i >= uNumLights) break; .............. } 

Are these equivalents? Should the latter work in older versions of GLSL? And if so, isn’t it more efficient and easier to implement than other methods that I read about, for example, using a different version of the shader for a different number of lights?
I know this may be a stupid question, but I am a newbie and I cannot find a reason why this should not work.

+6
shader glsl
source share
2 answers

GLSL can be confusing because for() offers you that there should be conditional branching, even if it is not, because the hardware cannot do it at all (which applies to if() in the same way).

What really happens on pre-SM3 hardware is that the HAL inside your OpenGL implementation will fully expand your loop, so there really is no transition. And this explains why he has difficulties with non-constants.

While it is technically possible to do this with non-constants, the implementation will have to recompile the shader every time you change this uniform, and it can work against the maximum number of commands if you are just allowed to provide any random number.

This is a problem because ... what then? This is a bad situation.

If you set a constant that is too large, it will give you a "too many instructions" compiler error when creating a shader. Now, if you give a stupid number in the form, and the HAL should thus create new code and work against this limit, what can OpenGL do?
You most likely confirmed your program after compilation and linking, and you most likely requested information about the shader information, and OpenGL continued to tell you that everything was in order. It is, in some way, a binding promise; it cannot simply be decided otherwise. Therefore, he must make sure that this situation cannot occur, and the only workable solution is to prevent uniforms in conditions of equipment generations that do not support dynamic branching.
Otherwise, glUniform should have some form of validation that rejects bad values. However, since this depends on the successful (or unsuccessful) recompilation of the shaders, this will mean that it should work synchronously, which makes it “without movement”. Also think that GL_ARB_uniform_buffer_object displayed on some SM2 hardware (like GeForce FX), which means that you can throw a buffer object with unpredictable content into OpenGL and still expect it to work somehow! The implementation will have to scan the buffer memory for invalid values ​​after it is deleted, which is crazy.

Like a loop, the if() does not work at the hardware level of SM2, even if it looks like it. Instead, it will compute both branches and perform a conditional move.

+11
source share

(I assume you are talking about pixel shaders).
The second option will only work on gpu, which supports the shader model> = 3. Because dynamic branching (such as setting the uNumLights variable to IF state) is not supported in the gpu, 3 shader model either.

Here you can compare what is and is not supported between different shader models.

+2
source share

All Articles