So, my scene is taking a lot time to load and, after analyzing the profiler, looks like a bottleneck is caused by this Shader.Parse. I Google’d a bit but I can’t find a solution nor a reason that can explain why Shader.Parse is taking a bunch of time.
A reasonable argument would be that I have a lot of shaders to load, but actually it isn’t (unless I’m missing something, but what?).
So, yeah. What are the common causes of Shader.Parse to take so much time? Any fixes or tests to prove that I am wrong?
We have been making some optimizations in this area recently because we have also noticed that it is (too) slow.
We are currently hoping to land the improvements in Unity 2019.3.
Are you able to share an example of a shader that was slow? Or was it one of our default shaders?
And can you tell us the Unity version and platform you are profiling using?
We’re currently on 2018.3.4f Win10. I can’t see any specific shader being too slow, also, I can’t profile the GPU because profiler says to “update my GPU drivers”. Which are already up to date.
Thanks, it’s a CPU problem so CPU profiling is fine.
It’s probably not going to be the fault of any particular shader, but I was curious in case you knew of any specific ones that were problematic. We have seen it on many of our default shaders though.
I’m not sure we are going to be able to land any improvements to this area in Unity 2018.4 now as it’s not a serious bug, just an inefficiency. But if your project will be running for long enough that Unity 2019.3 might be a viable option, it may help you as we are seeing a 35% speedup in this area in our local testing, and hope to land the optimisation in a public build in the coming weeks. But I’m always wary of advising upgrades because it comes with a lot of risk to you.
Hi,
on loading map, for Xbox, I’ve a gigangic spike due to Shader.Parse too. On PC is not that much of a deal but its because I’ve a powerfull one.
I use standard shader like for 99,9% of the stuff in scene.
That GPU drivers message, try dissabling graphics jobs may be I think I did get that message in the past.
Last time on certification they called my attention on this issue because it kinda freezes right before launching the match… 2018.4.9f1
I don’t know if it’s on the issue tracker anywhere but we landed most of our improvements to 2019.3, and some more only made it into 2020.1 (unfortunately)
I recently noticed after upgrading from 2018.4.2 to 2018.4.23 that I’m getting large Shader.Parse spikes where I didn’t before (while async loading a scene). Is there any way to get around this? Prewarming the shaders seems to make no difference now.
If you are using asset bundles built with the legacy build pipeline (like Asset Graph) it simply does not support assigning built-in Unity assets to bundles (including built-in shaders and built-in meshes like Plane and Cube). The legacy pipeline can only assign asset bundles based on asset paths and the built-in assets don’t have a valid one (also, AssetDatabase.GetDependencies() does not detect built-in assets either).
What happens when building the bundles is that the built-in assets referenced by the assets in your bundles get the same treatment as any other dependency that doesn’t have a bundle assigned to it: it gets copied into each asset bundle that depends on it.
This is why using ShaderVariantCollections to warm up built-in shaders fail: each bundle will load a fresh copy of the shader, that needs to be Shader.Parse’d into the GPU again for each newly loaded bundle.
The ContentPipeline API behind the Scriptable Build Pipeline is capable of assigning bundles to built-in assets, since it assigns bundles by asset reference, not paths. It also has dependency collection functions that, unlike AssetDatabase, can detect built-in assets correctly (it even correctly reports built-in shaders set as custom shader fallbacks as dependencies).
However, depending on how far along your project and how it’s set up, switching from legacy to scriptable build pipeline is not feasible (there’s also the question of the SBP being newer, not as battle-tested as legacy, and largely undocumented beyond very basic use cases).
The “solution” then is to download the built-in shaders for your Unity version, move them all into your project, then replace all references to the built-in shaders by the imported ones. This way you can assign them to a bundle that will be correctly registered as a dependency of any other bundles that reference them, and you can put them into a ShaderVariantCollection (loaded from a bundle) and warm up them correctly.