Shader.CreateGPUProgram takes a long time on first startup (iOS)

We’re having this problem of very long loading times on the very first startup of our game (or when restarting the phone, but not when killing the app and reopening it or when reinstalling it).

A check with the profiler shows that Shader.CreateGPUProgram is the problem:
Fresh install: 6053ms
Reinstall: 253ms


Can I control when this happens? We disabled loading shader variants and the shaders used at that stage (first scene) are very few.
We do use quite a lot of shaders. I guess reducing the amount of shaders would help. I’m wondering however:

  • Are shaders included in the Resource folder also affected for Shader.CreateGPUProgram
  • Will shaders with shader variants create a smaller overhead than the shaders as separate files
  • What actually happens at Shader.CreateGPUProgram? And why does it take so much more time at the first run? Is this a bug, or does it make sense?

btw. running Unity 5.6.4p4 and XCode 9.3 if that is important.

1 Like

Quick update: Shader.CreateGPUProgram compiles the shaders for the specific gpu. This happens whenever an app is freshly installes or the phone is restarted. Here is a simple test I made to show the impact:

This is only for creating the shaders. Warming up the shaders takes about the same amount of time. Interestingly enough this seems to behave rather similar as Shader.CreateGPUProgram. It is normally only necessary at fresh install or when the phone is restarted.
Can someone explain to me why shaders won’t need warmup when I kill the app and restart it? Is the shader actually still on the GPU? And is there a faster way to flush the GPU buffer other than restarting the phone?

TLDR: When implementing shaders, don’t only look at performance but also loading times, they have a huge impact on the first start of your app.

1 Like

Hi,

Did you ever solve this problem. We have it in our game as well. Our “Fresh Install” time for an iPhone 7 is around 20 seconds and “Reopening” time is 2 seconds.

We have been blaiming the Resource folder up until i saw this post. We will try to fix this as well and i’ll post back if we come to any conclusion on how to get rid of the problem.

If someone from Unity could comment on this that would be even better.

Thanks,
Kristofer

Well, as pointed out in the second post: The shaders get compiled on the device, that’s taking a shitload of time. Additionally the shaders also need to be warmed up, this is also mostly only necessary for fresh installs.
So in the end, try reducing the amount of shaders (and shader variants) you are using. A unity team member commented on it in this thread: Profiling Shader.CreateGPUProgram

I have the same issue with Unity 2017.4.0 and blank project. 7-12 seconds startup on iOS. 1-2 seconds on Android. Just opened a bug in the issue tracker but haven’t heard from Unity yet.

Was this ever resolved? I am encountering the same issue on Oculus Go. The profiler shows Shader.CreateGPUProgram running even when I have preloaded a shader variant collection with single pass VR rendering.

And is it possible is that cause crash on first launch because of lack of memory for example?

I had a meeting at Unite Berlin with an evangelist. Apparently ShaderVariantCollection.WarmUp does not always do what it should do on different platforms (apparently not even iOS). So maybe try showing the different shaders to a camera that renders into a render texture.

I would doubt that, did you check the profiler / logcat / Xcode log / whatever you’re on.

1 Like

Hi, did you find the answer to your question? (I have the same issue and would like to know how it works inside)

Hi,

Nope I still have no clue why that is the case, if you find it out, let me know :slight_smile:

By any chance, do you have visual FX graph in your project? It was added to our project when we upgraded from 2018.4 to 2019.3 and that added alot of time to compile compute shaders on the first startup.

No, in my case, it was a simple Unity 5.6 project with the good old builtin renderpipeline, no fancy packages involved. I just wrote quite a few shaders for the game, that’s why I hit the bottleneck.
My learning from here is clearly is to not only look on performance of shaders, but also on number of shaders to compile as little shaders as necessary.

For example, I built multiple shaders for stencil operations, until I learnt, that you can dynamically set, how a material reads or writes to the stencil and what id they are using. This lead me to build this repo: https://github.com/supyrb/ConfigurableShaders

I guess the VFX problem still has the same root cause: Compiling (too many) shaders. It is odd however, that the shader copile happens for you, even if you don’t use the FX graph. Did your shaders maybe somehow land in the always include assets or always include shaders lists? If that is not the case, I guess Unity does some magic under the hood to make sure those shaders are prewarmed at the start of the application…

Yeah my best bet is that unity is doing this under the hood :confused:

I’m pretty sure this is the cause of our long initial load times. On first startup, our splash screen is visible for 10+ seconds, subsequent startups are under 4 seconds. We have a Preloaded Shaders list with ~700 variants :eyes:

Yes, that is most likely the reason for your long startup time. Try to minimize the shaders or its variants or merge shaders. Any maybe don’t load the shaders at startup, but in a supersmall first scene, so you can show a progressbar or some kind of progress to its users. https://discussions.unity.com/t/682545

1 Like

I was having similar issues with WebGL, where CreateGPUProgram was exceptionally untimely (in the middle of gameplay when some my shaders are introduced).

Just chiming in to say that showing my two heavy shaders to my render texture camera first allowed me to control when those shaders were being compiled.