Version: 2021.1
Optimizing shader variants
Performance tips when writing shaders

Asynchronous Shader compilation

Asynchronous Shader compilation prevents the Unity Editor from stalling by rendering dummy Shaders while compiling new Shader Variants. Asynchronous Shader compilation is enabled in the Editor settings (menu: Edit > Project Settings… > Editor > Shader Compilation) by default.

Shaders can consist of hundreds or thousands of variants that cover different usage scenarios with different keyword combinations. If the Editor had to compile all variants when loading a shader, the Shader import process would be very slow. To handle this, Unity uses on-demand Shader compilation by default. This means that the Editor compiles Shader Variants the first time it encounters them in a Scene. This can stall rendering in the Editor, because full Shader compilation can take anywhere from milliseconds to seconds. The time it takes to compile a Shader Variant depends on the selected graphics API and the complexity of the Shader. To overcome these stalls, use Asynchronous Shader Compilation.

Disabling asynchronous Shader compilation in the Game and Scene views

Asynchronous shader compilation is enabled by default. You can disable it for Game View and Scene View. This can be useful if you don’t know which parts of your rendering solution are causing issues. However, you might then still experience rendering stalls in the Editor during Shader compilation.

To disable asynchronous Shader compilation:

1) In your Project, go to Edit > Project Settings.. > Editor.

2) At the bottom of the Editor settings, under Shader Compilation, uncheck the Asynchronous Shader Compilation checkbox.

You can find the check box for Asynchronous Shader Compilation under the Project Settings > Editor > Shader Compilation.
You can find the check box for Asynchronous Shader Compilation under the Project Settings > Editor > Shader Compilation.

Note: When you disable asynchronous shader compilation, this only affects the Scene View and Game View. This doesn’t affect systems and custom scripts that explicitly enable asynchronous Shader compilation.

How asynchronous Shader compilation works

With Asynchronous Shader Compilation, the Editor adds shader variants to a compilation queue and completes them in a job thread; it does not compile them immediately. . To avoid rendering stalls, the Editor continues rendering while it’s also compiling a Shader Variant. The Editor then fills in the Shader Variant’s spot with a dummy Shader in a plain cyan color (you’ll see occasional transient glimpses of the cyan dummy Shader that show what’s going on in the background). This avoids some objects not being rendered in Scenes, because the Editor is still compiling them. When compilation has finished, the Editor swaps-in the real Shader. The progress bar in the bottom right corner of the Editor shows the status of the compilation queue.

The feature does not have any effect on the standalone Player, because the Editor compiles all the Shader Variants needed by the Player during the build process.

Note: Asynchronous Shader compilation works in the Scene and Game views by default. If you want to use it in other scenarios, see [Using asynchronous Shader compilation in custom Editor tools.

Unity renders Shader Variants that are still compiling with a cyan dummy Shader until compilation has finished. The bottom right progress bar indicates Shader compilation queue progress.
Unity renders Shader Variants that are still compiling with a cyan dummy Shader until compilation has finished. The bottom right progress bar indicates Shader compilation queue progress.

Note: If you use DrawProcedural or CommandBuffer.DrawProcedural, the Editor doesn’t swap in a dummy Shader. Instead, the Editor just skips rendering this Shader Variant until it has compiled the Shader Variant.

Note: Blit operations do not use asynchronous Shader compilation. This is to guarantee correct output in the most common use cases.

Advanced rendering in the Editor

By default, asynchronous Shader compilation works in the Scene and Game views. Advanced rendering solutions rely on generating data once and reusing it in later frames, which might cause the dummy Shader to pollute the generated data. If this happens, you can see the cyan color or other rendering artifacts in your Scene, even after the Shaders have finished compiling. The issue only happens the first time the Editor encounters the data generating Shader Variants. However, to avoid these issues, you can either disable asynchronous Shader compilation for some parts of your rendering, force synchronous Shader compilation for some Shaders, or detect the specific data pollution and re-generate the data when compilation is done.

Disabling asynchronous Shader compilation on specific rendering calls

If you want to use asynchronous Shader compilation, but also don’t want the dummy Shader to affect the rendering result on specific rendering calls, you can disable the feature for those calls in your C# scripts. The following instructions show you how to disable the feature in an immediate scope and a CommandBuffer scope. In both cases, you essentially inject clamps around the render calls that you don’t want Unity to compile asynchronously.

In an immediate scope

In an immediate scope, you’ll have to use ShaderUtil.allowAsyncCompilation;.

Save the current state of ShaderUtil.allowAsyncCompilation to a variable. Immediately before you call the render commands that you want to disable asynchronous compilation for, set ShaderUtil.allowAsyncCompilation to false. After the rendering calls you want to affect, restore ShaderUtil.allowAsyncCompilation back to the previous state that you saved under step 1.

Here is a pseudo-code example:

// Store the current state and disable async compilation
bool oldState = ShaderUtil.allowAsyncCompilation;
ShaderUtil.allowAsyncCompilation = false;

// Enter your rendering code that should never use the dummy shader
Graphics.DrawMesh(...);

// Restore the old state
ShaderUtil.allowAsyncCompilation = oldState;

In a CommandBuffer scope

In a CommandBuffer scope, you’ll have to use ShaderUtil.SetAsyncCompilation and ShaderUtil.RestoreAsyncCompilation.

Immediately before you call the render commands that you want to disable asynchronous compilation for, call ShaderUtil.SetAsyncCompilation, and set it to false. All the immediately following commands in the buffer won’t allow asynchronous compilation. After the rendering commands you want to affect, use Shader.Util.RestoreAsyncCompilation.

Here is a pseudo-code example:


// Disable async compilation for commands followed by this
ShaderUtil.SetAsyncCompilation(cmd, false);

/// Enter your rendering commands that should never use the dummy shader
cmd.DrawMesh(...);

// Restore the old state
ShaderUtil.RestoreAsyncCompilation(cmd);

Force synchronous compilation for specific Shaders

You can force synchronous compilation for specific Shaders. This is a good option for data generating Shaders that are always present at the start of your rendering, and which are relatively quick to compile.

To force synchronous compilation for a specific Shader: In your Shader code, add this directive: #pragma editor_sync_compilation

Note: Don’t force synchronous compilation for complex Shaders that encounter new variants in the middle of your rendering. Forced synchronous compilation of complex Shaders can stall rendering in the Editor.

Detecting compilation and refreshing date

If the dummy Shader pollutes your generated data, you must discard the polluted data and regenerate a new set with the properly-compiled Shaders.

If you already know the Material that Unity is using for data generation: Use ShaderUtil.IsPassCompiled to check the compilation status of the Shader Variant specified by the current state of the Material. When the status has gone from Uncompiled to Compiled, refresh the generated data.

If you do not know which specific Material generates polluted data, or if the data generation is not specific to a single Material:

Use ShaderUtil.anythingCompiling to detect whether Unity is compiling any shaders asynchronously. When any asynchronous compilation has finished, refresh the data.

Using asynchronous Shader compilation in custom Editor tools

By default, asynchronous Shader compilation works in the Game and Scene views. If you want to use it in custom Editor tools, you can enable it via C# for your custom tool.

In an immediate scope

In an immediate scope, you’ll have to use ShaderUtil.allowAsyncCompilation;.

Save the current state of ShaderUtil.allowAsyncCompilation to a variable. Immediately before you call the render commands that you want to enableasynchronous compilation for, set ShaderUtil.allowAsyncCompilation to true. After the rendering calls you want to affect, restore ShaderUtil.allowAsyncCompilation back to the previous state that you saved under step 1.

Here is a pseudo-code example:

// Store the current state and enable async compilation
bool oldState = ShaderUtil.allowAsyncCompilation;
ShaderUtil.allowAsyncCompilation = true;

// Enter your rendering code that you wish to utilize async compilation
Graphics.DrawMesh(...);

// Restore the old state
ShaderUtil.allowAsyncCompilation = oldState;

In a CommandBuffer scope

In a CommandBuffer based scope, you’ll have to use ShaderUtil.SetAsyncCompilation and ShaderUtil.RestoreAsyncCompilation.

Immediately before you call the render commands that you want to enable asynchronous compilation for, call ShaderUtil.SetAsyncCompilation, and set it to true. All the immediately following commands in the buffer then allow asynchronous compilation. After the rendering commands you want to affect, use Shader.Util.RestoreAsyncCompilation.

Here is a pseudo-code example:


// Enable async compilation for commands followed by this
ShaderUtil.SetAsyncCompilation(cmd, true);

/// Enter your rendering commands that you wish to utilize async compilation
cmd.DrawMesh(...);

// Restore the old state
ShaderUtil.RestoreAsyncCompilation(cmd);

Graphics.ExecuteCommandBuffer(cmd); 

Customizing compile time rendering

You can make your custom tools draw something other than the dummy Shader per Material. This way, you can avoid rendering with the Shader Variant that would be cyan, and instead draw something else while the Shader compiles.

To check if a specific Shader Variant has compiled, use ShaderUtil.IsPassCompiled.

To trigger the compilation manually, use ShaderUtil.CompilePass. This way, you can avoid rendering with the Shader Variant that would be cyan, and instead draw something else while the Shader compiles.


  • 2019–03–07 Page published
  • Asynchronous Shader Compilation added in 2019.1 NewIn20191
Optimizing shader variants
Performance tips when writing shaders
Copyright © 2023 Unity Technologies
优美缔软件(上海)有限公司 版权所有
"Unity"、Unity 徽标及其他 Unity 商标是 Unity Technologies 或其附属机构在美国及其他地区的商标或注册商标。其他名称或品牌是其各自所有者的商标。
公安部备案号:
31010902002961