Shaders get compiled during runtime every single time an app starts. I understand the reasoning for this is that there are so many GPU architectures out there that it does not make sense to ship pre-compiled shaders. However, I wonder if the designers have explored the possibility of storing out the compiled shader during the first run and load the compiled version from the next run. This is akin to having the intermediate "*.o
" as in C/C++ compilation and just linking them when we're building the app. If this is possible, is it a bad idea to do this?
1 Answer
OpenGL 4.1's glGetProgramBinary
and glProgramBinary
exist for this purpose. The first one retrieves a binary that represents the compiled program in its entirety (though none of the state stored within it. It, and its implementation-defined format, can be stored and reloaded via glProgramBinary
.
Of course, there are limitations. Implementations are not required to be able to load the format they gave you. That is, a driver change could cause implementations to switch to a different versions, leaving all of your binaries obsolete and un-loadable. So you have to be ready to recompile from the source.
Alternatively, GL 4.6 allows you to employ SPIR-V, an intermediate shader language. The idea here is that you compile your code to SPIR-V, then load that SPIR-V into a shader, where you can move forward from there. There are no version changes that could break your code.
Of course, SPIR-V is an intermediate language, so it still has to be compiled to some degree, along with all of the error checking and the like needed to make the final GPU code. It won't be faster than program binaries, but it's a bit more reliable (for implementations that support it).