As explained here, such shader programs will attempt to cache the program binaries on disk using GL_ARB_get_program_binary or the standard equivalents in OpenGL ES 3.0. When no support is provided by the driver, the behavior is equivalent to the non-cached case. The files are stored in the global or per-process cache location, whichever is writable. The result is a nice boost in performance when a program is created with the same shader sources next time.
How big is the improvement? It varies. Some drivers have already been doing some sort of caching for the past couple of years, while some others have similar features in the pipeline. However, the gains turn out to be quite significant in practice on devices that are out in the field right now:
Do not read too much into the actual numbers. What is important is the difference between Qt 5.8 and 5.9. Also, a simple Qt Quick or GL-backed QPainter scene will definitely not use 10 programs, but as complexity grows, with Qt Graphical Effects and custom ShaderEffect items entering the picture, getting similar improvements does not look far fetched anymore.
In fact we gain something even on systems that employ shader caching already. Therefore every application's startup and view switching times are expected to benefit with Qt 5.9 - without having to change anything.
Applications that use QOpenGLShaderProgram on their own can usually switch to the cacheable function variants by just changing the name in the function call. The change have to be a conscious decision, though, since some of the APIs change semantics when program binaries are used. Most notably, QOpenGLShader, addShader(), and removeShader() are incompatible with the program-level caching since they rely on individual shader compilation.
That's it for now, stay tuned for more posts about exciting upcoming Qt 5.9 and 5.10 features.