4
$\begingroup$

Context

As I was trying to learn more about Vulkan, I learned that certain fixed-function steps could be implemented with shader code from this video (at around the spot where he talks about the following problem):

https://youtu.be/X8Ob_b3ANzs?t=24m

In this video, the presenter says "hitching" can occur in OpenGL because for some GPUs the colorblend stage apparently needs to be recompiled at certain times. He gives an example of when a player takes out a torch and causes hitching due to bloom.

Questions

Why would this shader need to be recompiled in this scenario? In what scenarios would this shader need to be recompiled? Is this common practice/an issue across vendors?

$\endgroup$
5
$\begingroup$

In GL's model of the GPU, the colour blending step is performed by special-purpose hardware. This idea dates back to the fixed-function origins of GL, before programmable shaders were even a thing.

But not all GPUs today implement all colour blend options with special-purpose hardware. The hardware vendor can reduce gate count and power use by getting rid of some of the less-used blend modes (or even by getting rid of the blender hardware completely and doing everything in shaders). Instead, the GL driver has to add some code to the shader to do the blending. This code is added transparently to the driver, and isn't visible to the application, because GL doesn't have a way to make this visible or to control it from the application.

Now, the shader object (the compiled shader) doesn't just depend on the shader source code, but also on the blend mode in effect when it was compiled. If the application subsequently changes the blend mode, the driver needs to work out which shader objects are affected, retrieve the stored source of those shader objects, add the code for the new blend mode, and recompile the shader. Again, it has to do this behind the application's back, because GL doesn't have a way to control it: GL assumes the shader object is independent of the blend mode.

Normally, the application would compile shaders during a loading screen, or in a thread, but because the shader compilation isn't triggered by the application, it can't control when it happens. It just happens by magic when the application changed something that should be unrelated (the blend mode), which might be in the middle of a frame, so it causes hitching. And of course because it's hidden, the app can't simply ask to go back to the old state: changing the blend mode again might trigger another shader compilation (though it might come from a cache in the shader compiler).

Blend mode isn't the only parameter that causes this. Some unusual texture modes are also supported by adding code to the shader. (YUV textures commonly work this way, on implementations that support them.) Exactly which parameters cause a problem depends on the implementation: it's different for different hardware architectures. I think it's typically a bigger problem on mobile, because the GPU vendors are more sensitive to gate count and power use and more keen to replace special-purpose hardware with shader code.


The reason Vulkan makes this less of a problem is that it creates a new kind of state, which depends on the blend mode, the shaders, and other parameters. Changing any of these requires the app to perform an explicit "prepare" operation, which might recompile shaders. This gives the app control over when it happens, including the ability to prepare all the combinations of parameters up-front in a loading screen or in a background thread. It means that shader compilation never happens without the app asking for it explicitly. And it means the app can just go back to the old state by switching to it, instead of changing the blend mode and waiting for another shader recompilation.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.