Binary Shader Program Management

Shader programs are ordinarily stored in source form, and are compiled and linked by the OpenGL® ES driver when the application first uses them by making OpenGL ES API calls.

You can also precompile shader programs with glslc, an offline shader compiler. This eliminates the need to compile those shader programs at run time. If all of the shader programs an application uses are precompiled, the OpenGL ES driver can save additional time and resources by not loading the compiler libraries at all.

An application also can control binary program management directly. It can use the glGetProgramBinary() function, added in OpenGL ES 3.0, to read back the binaries for any compiled and linked programs and store them for later use. The glProgramBinary() function loads these saved binaries. Unlike the glShaderBinary() function in OpenGL ES 2.0, glProgramBinary() operates on a linked program instead of individual vertex and fragment shaders, so no additional link step is required after the binary is loaded.

An application can save and load compiled program binaries either directly, by calling the OpenGL ES API, or through the automatic shader cache described below.

Automatic Shader Cache

The OpenGL ES 3.0 driver in Jetson Linux supports an NVIDIA proprietary shader cache. When shader cache support is enabled, the driver maintains a shader cache file for each program. If an application requests a shader, the driver searches the cache for a binary compiled from that source with the current versions of the compiler and the driver. If such a binary exists, it loads that binary from the cache. Otherwise it compiles the program and saves the binary in the cache.

The cache persists between application runs, so after a thorough initial run, programs need be compiled only when a new driver is installed.

The shader cache is enabled by default on read/write file systems. Assign the environment variable __GL_SHADER_DISK_CACHE a value of 0 to disable the cache.

By default, the cache is placed in ~/.nv. This directory is created if it does not already exist. You can specify a different location for the cache by setting the environment variable __GL_SHADER_DISK_CACHE_PATH to a directory’s pathname. If the specified directory does not exist, the driver disables the cache; it does not create the missing directory, as it would for the default ~/.nv directory.

Wherever the cache is kept, it takes the form of a subdirectory named GLCache. It contains a set of files with hashed names. These files encode the driver version, GPU, and application. Whenever you install a new version of the driver, the hashed names change. Users may then want to remove the old directories before running applications.

An application’s shader cache can be made read-only. Such a cache contains only precompiled shader program binaries; the OpenGL ES driver cannot save binaries in it when it compiles them at run time.

To make a cache read-only

  1. Run the application on a test or development system whose file system has write access.

  2. Copy the cache directory to the desired location in the target image.

  3. Set the cache directory’s permissions to give the application read-only access.

  4. Set the environment variables described above to enable the cache and specify its location.

Comparison and Combination

The main advantage of using the shader cache is that it is handled automatically, transparently to the application. In addition, the driver sometimes generates shaders internally for certain clear and copy operations, and if the cache is enabled, these too are generated only once, rather than each time the application runs.

Although the cache eliminates the need to recompile shaders, it has some search and maintenance overhead. Applications can avoid this overhead by saving and loading shader program binaries directly. Furthermore, cached binaries are recompiled each time a new driver is installed, while saved binaries need be replaced only when the compiler portion of the driver is updated.

An application can keep some shader programs in cache and load others directly. For instance, an application can use direct loading for the most critical shader programs, which must be available as soon as possible after startup, and rely on the cache to manager less frequently used shaders.