shader_feature long compilation time with surface shaders

Recently I’ve been writing Uber shaders with tons of options. I managed to write a 2D uber shader that has around 100 shader_features and it compiles real fast, pretty much instantly. But when I add around 20 shader_features to a surface shader the compilation times get completely out of hand (around 5 minutes).

Does anyone know what’s going on?

Thanks and cheers

It sounds like it’s taking it from cache and not really compiling it.

Been doing some more shader work with surface shaders and it’s just unbearable, with 11 shader_features ANY change done to the shader takes almost 10 minutes…

It’s impossible to work like this.

Got any advice?

Shader features can explode variants exponentially, it’s understandable. Are you using the new shader_feature_local now at least?

One thing that can help is making sure to strip any features you’re not using from surface shaders to avoid generating variants for those features, look at the “Code generation options” of this page. And also restricting to only your currently used renderer with #pragma only_renderers while you’re working on it.

Surface Shaders generate like 6 or so different passes that are used in different situations, and then there’s tonnes of shader features and multi-compiles involved in them by default already which your shader_features are going to stack on top of and multiply.

A default Surface Shader can generate over 2000 (yes, really) variants. Every single multi_compile shader_feature added can double the number.
Add one shader_feature and you’re now up to over 4000 variants.
Add a shader_feature with three options, you’re at over 6000 variants.
Add two shader_feature lines with one or two options each (one option is actually two, so it’s the same thing), you’re at over 8000 variants.

Now, most of these won’t always be compiled, but a lot of them will be. Unity’s forward lighting system requires a lot of variants that use multi_compile. Certainly more than a shader that’s only using shader_feature lines alone.

I was using shader_feature_local but since the shader I’m working on is part of a Unity Store package I need to remove it to ensure backwards compatibility.

And thanks for the link, stripping some options away definitely accelerates the workflow a bit.