Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent loop unwinding in fragment shader

Tags:

loops

glsl

webgl

I'm writing a fragment shader for WebGL(GLSL ES 1.0) using the latest version of Chrome(and Firefox), and I wrote an iterative algorithm.

So first of all, I found out the hard way that the length of the loop is quite restricted (doc says it must be guessable at compile-time, which means it must be a constant or very close).

In addition, I must write a (for, since it's the only one which must be implemented according to the standard) loop that's potentially long but that breaks almost every time before the end.

Now, I've noticed that if I set a higher maximum number the compilation and linking of the shader takes alot more time. So, unless I'm wrong, the compiler does loop unwinding.

I'm not sure if anything can be done, but I've tried a few things and the compiler seems also to inline functions, even when called in loops.

I don't feel like it's normal for a shader to take a whole minute to compile for just about a hundred iterations of a loop. Or am I doing the wrong thing? Is a hundred iterations in a fragment shader way too much for a GPU? Because it seems to run just fine after it has compiled.

like image 474
Manux Avatar asked Apr 26 '12 13:04

Manux


2 Answers

This is one of the unfortunate realities of GLSL. It would be great if we could do an offline compile and send in bytecode, or if we had the ability to specify flags at compile time or so on, but that's just not how the spec works. You are entirely at the mercy of the driver manufacturer. If NVIDIA/ATI thinks loop unrolling is good for you, your loop is gonna get unrolled.

I do question what it is that you are doing that requires so much looping, though. Shaders are not really the right place to be doing super complex looping or branching calculations. You'll certainly take a performance hit for it. If you're not worried about realtime performance, then perhaps a large compile hit at the start of your program isn't so bad. If you are concerned about the rendering speed of your app then you likely need to re-evaluate your shaders complexity.

like image 116
Toji Avatar answered Oct 24 '22 14:10

Toji


You mention the shader taking more than a minute to compile a loop with a maximum of only about 100 iterations, and this makes me think your problem could be related to ANGLE.

ANGLE is a piece of software embedded in WebGL-capable browsers on the Windows OS, that takes your GLSL shader and translates it at runtime into a Direct3D HLSL shader. The thinking is that most Windows machines have newer Direct3D drivers compared to their OpenGL drivers, so the default behavior is to convert everything to D3D. In my experience this can be slow, particularly with long loops as you describe, although it's needed by many Windows users, particularly ones with Intel-based graphics.

If you're running Windows and you have good-quality OpenGL drivers, such as reasonably new ones from nVidia or AMD, you can try disabling ANGLE to see if it fixes your problem. On Google Chrome this is done by editing your Chrome icon to add --use-gl=desktop as a command-line parameter (in the 'target' field of the icon) and restart the browser. For Firefox, you can visit about:config and type webgl into the search box, and look for webgl.prefer-native-gl and set that to true.

Try your shader again with ANGLE disabled, and compile times may be improved. Keep in mind this is only a Windows issue, so editing these settings on other platforms has no effect, but I believe all other platforms all use native OpenGL directly.

like image 21
emackey Avatar answered Oct 24 '22 15:10

emackey