What is a uber shader?
Members - Reputation: 145
Posted 25 July 2014 - 08:53 AM
Members - Reputation: 2413
Posted 25 July 2014 - 08:58 AM
Since dynamic branches can have quite a big performance impact, usually people prefer to make as many branches as possible static or determined at compile time. Frequently when people refer to an ubershader they're referring to one large shader that's compiled many times with different #defines for different features. For example, you might have a #define USE_NORMAL_MAP that can turn on the normal mapping feature, or NUM_SPOTLIGHTS which determines how many spotlights to shade for, etc.
The problem with ubershaders is that you can easily get a massive number of compilation permutations, which is hard to manage.
Crossbones+ - Reputation: 3814
Posted 25 July 2014 - 11:39 AM
I'm wondering what a uber shader is. My first impression about a uber shader is putting everything in one shader and choosing the path dynamically. Does the shaders in Unreal Engine count as uber shader? They have plenty of branches in their shader code, however most of them are based on static conditions which are defined by macros during shader compiling, not run time. Do these kind of shader fall into the cateogry of uber shader? Thanks
I think it's a slightly fuzzy term without a strict definition.
I'd say that if your shader code is handling lots of different rendering scenarios, then it's an uber-shader. Whether those different scenarios are implemented with run-time or compile time switches doesn't matter imo, it's still an uber shader.
I think that sometimes when people talk about uber-shaders, they mean just the scenario where there is pretty much just one shader used by the entire title (maybe with the exception that 2D/post-processing might use something different). Other times it's more broad, and a title might be said to have a skinning uber shader and an environment uber shader, etc.
Members - Reputation: 1012
Posted 25 July 2014 - 12:22 PM
uber shaders were originally ment to reduce program state changes issued to gpu, thus it was being an idea of putting shader instructions into one shader and by branching over a uniform variable issue the desired ones, without need of a program state change over gpu. Compile macros does not realy target this usage, as they create separate compiled program objects in just a particular way. You need to check further wheather those shaders in unreal engine are the "uber shaders"
But it is rather rare to have a performance benefit in using uber shaders in a well managed rendering set, since many branches in many draw calls will likely under-perform a few program state changes. One should rather think of sorting draw calls by shader programs primarily. Generaly, branching by uniform value is cheaper than branching by vertex atribute value , and cheaper than branching by interpolated or sampled value.
Moderators - Reputation: 48135
Posted 27 July 2014 - 01:53 AM
Also, back in the previous generation (D3D9 era), many GPUs allowed shaders to have 32 uniform boolean values. Doing a runtime branch on one of these was called "static branching", and branching on anything else was "dynamic branching". They both occur at runtime, but "static branching" was cheaper.
So there's actually 3 kinds:
1) compile-time selection of options, using different shaders at runtime.
2) runtime selection of options by branching on uniform Boolean values.
3) runtime selection of options by branching on other data (uniform floats, texels from a gbuffer, etc).
I don't think modern GPUs treat options #2/#3 differently any more though!