Programmatically compiling all shaders the first time an application is run and saving the binaries for reuse can significantly reduce load times for games in subsequent runs. The OpenGL* ES 3.0 sample code introduced here demonstrates a simple implementation of this capability.

Precompiling shaders is a technique to improve the user experience for games and other applications that use large numbers of complex shaders, by reducing load times.

The first time the application is executed, it compiles all of the shaders, and the binaries produced are saved to local storage.

For subsequent runs of the application, shader compilation is not necessary, because the required binaries have already been produced and are available at runtime.

This approach enhances efficiency for resource-constrained mobile devices and improves responsiveness from the user’s perspective.

A key benefit of the precompiled shader approach discussed here, relative to some alternatives, is that the shader binaries are built natively for the execution platform, using the target device’s actual runtime environment. That overcomes limitations faced by developers who seek a similar result by compiling shaders and packaging the binaries as assets before distributing the application, for example, which can result in cross-platform incompatibilities.

Downloading and installing the sample

The code sample is available for download from GitHub. To build and deploy the application to your Android device, follow the steps below.

Navigate to PrecompiledShaders\projects\android

Run the following:

android update project –p .

ndk-build

ant debug

ant installd

Details of the implementation

This sample implements shader precompilation by caching the shader binary on the first run and then using that file on each subsequent run. The implementation operates as follows:

Cache the shader on the first run only.

Compile and link the program in the usual way.

Use glGetProgramBinary to save the compiled/linked program binary into an array.

Load the shader.

Use glProgramBinary to load the program binary into the program object.

Performance comparison: precompiled versus runtime-compiled shaders

The following chart compares load times for precompiled shaders with those for shaders compiled at runtime, using the code sample introduced here with a very simple shader. These results clearly demonstrate the value of shader precompilation.

Conclusion

While the shader precompilation technique used in this sample doesn’t require significant development effort, it is a flexible, cross-platform approach to decrease load times significantly. This approach should be used routinely to optimize the user experience within the hardware constraints of mobile devices.