4

I've written an OpenGL live wallpaper for Android that uses 17 pixel and 17 vertex shaders. On my HTC Legend, these take about 3 seconds to load and compile. Loading time is about 20% of this, the rest is compiling.

A live wallpaper has its OpenGL context destroyed every time a full-screen app is ran, and when the wallpaper becomes visible again, all shaders, textures and so on need to be reloaded, causing the screen to freeze for about 3 seconds each time, which is unacceptable to me :(

I've done some reading and apparently, it's not possible to precompile the shaders. What else could I do to fix this? Is it possible to load and compile shaders in a background thread? I could show some kind of progress animation in that case. Wouldn't be great, but better than nothing...

[EDIT1] Another big reason to speed this up is that the whole OpenGL based Live Wallpaper life cycle is difficult to get working properly on all devices (and that is an understatement). Introducing long load times whenever the context is lost/recreated adds more headaches than I want. Anyway:

As answer 1 suggests, I tried looking at the GL_OES_get_program_binary extension, to make some kind of compile-once-store-compiled-version-per-installed-app, but I'm worried about how widely this extension is implemented. For example, my Tegra2 powered tablet does not seem to support it.

Other approaches I'm considering:

1) Ubershader: putting all pixel shaders into one big shader, with a switch or if statements. Would this slow down the pixel shader dramatically? Would it make the shader too big and make me overrun all those pesky register/instruction count/texture lookup limits? Same idea for the vertex shaders. This would reduce my entire shadercount to 1 pixel and 1 vertex shader, and hopefully make compiling/linking lots faster. Has anyone tried this? [EDIT2] I just tried this. Don't. Compiling/linking now takes 8 seconds before giving up with a vague "link failed" error :(

2) Poor man's background loading: don't load/compile the shaders at the beginning, but load/compile one shader per frame update for the first 17 frames. At least I would be refreshing the display, and I could show a progress bar to make the user see something is happening. This would work fine on the slow devices, but on the fast devices this would probably make the whole shader load/compile phase slower than it needs to be...

Nils Desle
  • 81
  • 1
  • 5

1 Answers1

3

Check if your implementation supports OES_get_program_binary.

genpfault
  • 51,148
  • 11
  • 85
  • 139
  • I'll do that, thanks! I assume you are suggesting I compile them once, at first execute, save the binaries and next time, reload them? That would require an extra permission for SD access but I suppose I could live with that. I'll update this question/answer once I know more. – Nils Desle Jan 05 '12 at 13:51
  • OK, tried it on the two devices I own (an HTC Legend and an Asus EEE transformer).The results were a bit surprising: the older, weaker HTC Legend supports this extension, the newer, "awesome" NVidia Tegra2 does not. On the other hand, on the Asus, compiling the shaders takes much less time (haven't timed it yet, but definately less than a second). I'm a bit worried about how widely this command has been implemented by the various hardware vendors, and whether it's worth my time to implement this whole caching scheme... – Nils Desle Jan 07 '12 at 09:47
  • How do you get the binary from the driver? – Daniel Ryan May 24 '12 at 21:14
  • 1
    It's right there in the extension spec: `glGetProgramBinaryOES()`. – genpfault May 24 '12 at 21:55