Version: 2020.1
着色器编译
优化着色器变体

Asynchronous shader compilation in the Unity Editor

Asynchronous shader compilation is an Editor-only feature that can speed up your workflow when you have complex Unity shaders with lots of shader variants.

本页包含以下信息:

概述

Unity shaders can contain of hundreds or thousands of shader variants. If the Editor compiled all variants when loading a Unity shader, the import process would be very slow. Instead, the Editor compiles shader variants on-demand, the first time it encounters them.

Compiling these shader variants can cause the Editor to stall for milliseconds or even seconds, depending on the graphics API and the complexity of the Unity shader. To avoid these stalls, you can use Asynchronous Shader Compilation to compile the shader variants in the background, and use placeholder Unity shaders in the meantime.

异步着色器编译的工作原理

异步着色器编译的工作原理是:

  1. 当编辑器第一次遇到未编译的着色器变体时,它会将着色器变体添加到作业线程上的编译队列中。编辑器右下角的进度条会显示编译队列的状态。
  2. While the shader variant is loading, Editor renders the geometry with a placeholder Unity shader, which appears as a plain cyan color.
  3. 当编辑器完成对着色器变体的编译后,它会使用着色器变体来渲染几何体。

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.

Unity 会渲染仍在用青色虚拟着色器进行编译的着色器变体,直到编译完成。右下角的进度条指示编译队列的进度。
Unity 会渲染仍在用青色虚拟着色器进行编译的着色器变体,直到编译完成。右下角的进度条指示编译队列的进度。

异常

将产生以下异常:

  • If you draw geometry using DrawProcedural or CommandBuffer.DrawProcedural, the Editor doesn’t use a placeholder Unity shader. Instead, the Editor just skips rendering this geometry until it has compiled the shader variant.
  • Unity 编辑器不会使用带有 Blit 操作的异步着色器编译。这是为了保证在最常见的用例中获得正确输出。

为您的项目启用和禁用异步着色器编译

默认情况下已启用异步着色器编译。

To enbale or disable asynchronous shader compilation:

  1. Go to Edit > Project Settings.. > Editor.
  2. 在编辑器设置底部的 Shader Compilation 下,取消选中 Asynchronous Shader Compilation 复选框。
可以在 Project Settings > Editor > Shader Compilation 下找到 Asynchronous Shader Compilation 的复选框。
可以在 Project Settings > Editor > Shader Compilation 下找到 Asynchronous Shader Compilation 的复选框。

Note: Enabling and disabling asynchronous shader compilation in this way affects only the Scene and Game views by default. If you want to use it in other scenarios, you can control this via scripts. See [Using asynchronous Shader compilation in custom Editor tools.

为特定渲染调用启用和禁用异步着色器编译

You can enable or disable asynchronous shader compilation for specific rendering commands in your C# scripts. You might use this

The following instructions show you how to enable or disable the feature in an immediate scope, and a CommandBuffer scope.

在直接作用域中

In an immediate scope, you can use ShaderUtil.allowAsyncCompilation;.

为此需要执行以下操作:

  1. ShaderUtil.allowAsyncCompilation 的当前状态存储在一个变量中。
  2. 在调用渲染命令之前,将 ShaderUtil.allowAsyncCompilation 设置为 false
  3. 调用渲染命令。
  4. 调用渲染命令后,将 ShaderUtil.allowAsyncCompilation 恢复到之前的状态。

下面是一个伪代码示例:

// Store the current state
bool oldState = ShaderUtil.allowAsyncCompilation;

// Disable async compilation
ShaderUtil.allowAsyncCompilation = false;

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

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

在 CommandBuffer 作用域中

In a CommandBuffer scope, you can use ShaderUtil.SetAsyncCompilation and ShaderUtil.RestoreAsyncCompilation.

  1. 在调用渲染命令之前,调用 ShaderUtil.SetAsyncCompilation,并将其设置为 false。CommandBuffer 中的后续命令将不允许异步编译。
  2. 将渲染命令添加到 CommandBuffer。
  3. 在渲染命令之后,调用 Shader.Util.RestoreAsyncCompilation 恢复异步着色器编译的状态。

下面是一个示例:


// Disable async compilation for subsequent commands
ShaderUtil.SetAsyncCompilation(cmd, false);

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

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

Disabling asynchronous compilation for specific Unity shaders

You can disable asynchronous shader compilation for specific Unity shaders by forcing the Editor to always compile them synchronously. This is a good option for data generating Unity shaders that are always present at the start of your rendering, and which are relatively quick to compile. You would most likely need this if you are performing advanced rendering.

To force synchronous compilation for a Unity shader, add the #pragma editor_sync_compilation directive to your Unity shader source code.

Note: If you force synchronous compilation for complex Unity shaders that encounter new shader variants in the middle of your rendering, this can stall rendering in the Editor.

检测异步着色器编译

您可以使用 C# API 监控异步着色器编译状态,并在此状态更改时执行操作。

This is most likely useful in advanced rendering; if the placeholder Unity shader pollutes your generated data, you can discard the polluted data and regenerate a new set with the correct shader variants.

如果您已知自己感兴趣的材质,可以使用 ShaderUtil.IsPassCompiled 检查着色器变体的编译状态。当状态从 Uncompiled 改变为 Compiled 时,编译完成。

如果您不知道自己感兴趣的材质,或者您对不止一种材质感兴趣,可以使用 ShaderUtil.anythingCompiling 检测 Unity 是否正在异步编译任何着色器变体。当状态从 true 变为 false 时,所有当前编译完成。

Editor 中的高级渲染

Advanced rendering solutions rely on generating data once and reusing it in later frames. If the Editor uses a placeholder Unity shader during this process, it might pollute the generated data. If this happens, you can see the cyan color or other rendering artifacts in your scene, even after the shader variants have finished compiling.

为避免这种情况,您可以:

自定义编辑器工具和异步着色器编译

默认情况下,异步着色器编译功能在 Game 视图和 Scene 视图中有效。如果要在自定义 Editor 工具中使用该功能,可以通过 C# 为自定义工具启用该功能。

为此,您可以为特定的渲染调用启用异步着色器编译

自定义编译时间渲染

You can make your custom tools draw something other than the placeholder Unity shader for each material. This way, you can avoid rendering in plain cyan, and instead draw something else while the shader variant compiles.

要检查特定着色器变体是否已编译,请参阅检测异步着色器编译

要手动触发编译,您可以使用 ShaderUtil.CompilePass。这样就可以避免使用青色占位着色器来进行渲染,而是在着色器变体进行编译时绘制其他内容。

着色器编译
优化着色器变体