9

Does anybody know how to do switch case syntax in the fragment shader on the Samsung Galaxy S2? I get the compilation error: Expected literal or '(', got 'switch'.

My syntax is as follows:

switch(i){
    case 0: x = alphas[0]; break;
    case 1: //...etc.
}

This works fine on the Nexus 7, but on the Galaxy S2 I get the above error. Are switch case instructions simply impossible on the Galaxy S2? The reason why I want to use them is they appear to give a performance improvement over if else on the Nexus 7. If they are impossible on the Galaxy S2, is there a way to query the device and use switch case if available, and if else otherwise?

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
Navigateur
  • 1,852
  • 3
  • 23
  • 39

2 Answers2

8

switch statement is not supported in OpenGL ES 2.0. From the OpenGL ES Shading Language 1.0.17 spec 3.7:

The following are the keywords reserved for future use. Using them will result in an error:

asm class union enum typedef template this packed goto switch default ...

Kimi
  • 13,621
  • 9
  • 55
  • 84
6

GLSL ES is based on version 1.10 of the desktop GLSL, but 'switch case' statements were added in vesrion 1.30, so you cannot assume device will support it.

Also I would recommend avoiding branching in fragment shader as it hits perfomanace badly.

zombo
  • 71
  • 1
  • 5
  • How can I avoid branching if I need to animate the colors of separate objects in the fragment shader and the GPU doesn't support array access by variable (only compile-time constants)? – Navigateur Apr 14 '13 at 18:27
  • 4
    You can try preparing different shaders for different object types (without _switch_, with code for proper _case_ inlined) and call glUseProgram(GLint aObjectShaderID) before drawing, when type changes. This is what I use right now, speedup depends on how often I have to change shader (objects to draw should be sorted by shaders to minimize shader changes) and how complex is branching but golden rule is to avoid branching at all cost and proflie after implementing each optimization. – zombo Apr 14 '13 at 19:47
  • zombo, does this require a separate `drawElements` call per program, yes? Doesn't this carry its own cost and how do you know it isn't more expensive than branching in the fragment shader? – Navigateur Apr 14 '13 at 19:58
  • @Navigateur: It sounds like you should be using a texture that contains these colors, and accessing the color based on a texture coordinate. – Nicol Bolas Apr 15 '13 at 01:34
  • @Navigateur Yes, it requires call per program. I profile my apps and shaders on iOS with Xcode's OpenGL Profiler, but I don't know of any good GL Profiler for Android. Also, Nicol Bolas idea sounds good and I think it might be worth implementing. – zombo Apr 15 '13 at 06:57
  • 2
    @Navigateur - I can back up zombo's gut feeling on the optimization. In almost every case I've seen, on mobile devices the small overhead of additional draw calls is more than offset by the performance gains of removing branching within your shaders. I've seen 10-20X speedups when removing branching in fragment shaders. – Brad Larson Apr 15 '13 at 19:43
  • @zombo, I tested it after my comment and yes, even with multiple draw calls, it's much faster without any branching in my fragment shaders. It's easy to obsess about certain optimizations to the extent that you cause much worse slowdown elsewhere as a result. Thanks zombo, you're a hero. I'm not sure I can do Nicol's idea as I'm animating color values smoothly based on floats, for different objects. I believe I'd have to continuously change the texture itself to accomodate this, right? Brad, thanks - are fragment shaders far more precious than vertex shaders as they're per-pixel, yes? – Navigateur Apr 16 '13 at 08:45
  • @Navigateur - In general, yes. If you can offload work to the vertex shader and feed the results to the fragment shader you usually see a nice performance increase (only calculating once per vertex instead of once per pixel). In particular, if those calculations provide texture coordinates for sampling, certain mobile GPUs can see a huge speedup by being able to cache texture reads. I make sure to do this where I can. – Brad Larson Apr 16 '13 at 18:07