着色缓存器_新的缓存着色器预处理器(实验性)可加快构建速度

着色缓存器_新的缓存着色器预处理器(实验性)可加快构建速度

着色缓存器

Shader compilation is a lengthy process that involves several steps. One of the first steps is preprocessing the shader source. Unity 2020.1 beta introduces the Caching Shader Preprocessor, a new custom solution to perform this compilation step. It is up to 25% faster than the platform compilers’ preprocessor, closely follows the C standard, and offers new features.

着色器编译是一个漫长的过程,涉及多个步骤。 第一步之一是预处理着色器源。 Unity 2020.1 beta 引入了缓存着色器预处理器,这是一种新的自定义解决方案,可以执行此编译步骤。 它比平台编译器的预处理器快25%,紧密遵循C标准并提供新功能。

Anyone who uses Unity deals with shaders, directly or indirectly. Shaders are programs that run on the GPU. They determine how objects are rendered to the screen. When, for example, a point light is added to a scene, objects that need to react to it will use a different shader variant, which defines how to handle point lights.

使用Unity的任何人都直接或间接处理着色器。 着色器是在GPU上运行的程序。 它们确定如何将对象渲染到屏幕上。 例如,当将点光源添加到场景时,需要对其进行React的对象将使用不同的着色器变体,该变体定义了如何处理点光源。

Whenever a new shader variant is used that has not yet been encountered, the Unity Editor has to compile it. When building the application to run on your target device, the Editor needs to compile all of the required shaders.

每当使用尚未遇到的新着色器变体时,Unity编辑器都必须对其进行编译。 在构建要在目标设备上运行的应用程序时,编辑器需要编译所有必需的着色器。

A checkbox to switch the Caching Shader Preprocessor on or off can be found in Editor settings in the Shader Compilation section.

在“着色器编译”部分的“编辑器”设置中,可以找到用于打开或关闭“缓存着色器预处理器”的复选框。

The rest of this blog post covers technical details that you may find useful if you are writing shaders.

本博客文章的其余部分介绍了技术细节,如果您正在编写着色器,这些技术细节可能会有用。

专为速度而打造 (Built for speed)

The new preprocessor caches intermediate preprocessing data to speed up shader import and compilation time. With this caching, the Editor doesn’t need to parse include files until their contents change, and compiling multiple variants of the same shader is more efficient. Enabling the new preprocessor has the most noticeable effect when shaders within a project use a large set of common include files.

新的预处理器缓存中间预处理数据,以加快着色器的导入和编译时间。 通过这种缓存,编辑器不需要解析包含文件,直到它们的内容更改为止,并​​且编译同一着色器的多个变体更加有效。 当项目中的着色器使用大量公共包含文件时,启用新的预处理器具有最明显的效果。

统一性 (Unification)

Different shader compiler back ends come with their own preprocessors. Running a custom standardized preprocessing layer before the compiler is executed ensures that shader code is compatible with any compiler back end used currently or in the future, which in turn means easier project upgrades between Unity versions.

不同的着色器编译器后端带有自己的预处理器。 在执行编译器之前运行定制的标准化预处理层,以确保着色器代码与当前或将来使用的任何编译器后端兼容,这反过来又意味着在Unity版本之间进行更轻松的项目升级。

The same preprocessor is now used during shader importing, replacing the plain text parsing solution employed previously for checking shader compilation parameters (#pragma directives). This enables us to offer additional new features, such as conditional #pragma directive selection and a possibility to put those directives in include files.

现在,在着色器导入期间使用了相同的预处理器,从而替换了以前用于检查着色器编译参数( #pragma指令 ) 的纯文本解析解决方案 。 这使我们能够提供其他新功能,例如有条件的#pragma指令选择以及将这些指令放入包含文件的可能性。

新功能 (New features)

Show preprocessed source Shader inspector now has a “Preprocess only” checkbox so you can toggle between showing compiled shader code and preprocessed shader source. This feature is very useful for anyone developing shaders and facilitates shader debugging.

显示预处理的源 着色器检查器现在具有“仅预处理”复选框,因此您可以在显示编译的着色器代码和预处理的着色器源之间切换。 此功能对开发着色器的任何人都非常有用,并有助于着色器调试。

Shader compilation parameters in include files We introduced a new preprocessor directive, #include_with_pragmas, that allows shader developers to put #pragma directives that control compilation settings in include files. They act as regular #include directives but are not ignored during shader import time.

在着色器编译参数包括文件 ,我们推出了新的预处理器指令,#include_with_pragmas, 它允许开发人员着色放 的#pragma指令,在控制编译设置包括文件。 他们作为普通 #include指令,但在着色器导入时不忽略。

This distinction minimizes shader import time; otherwise, we would need to run the preprocessor on all the files included in the shader.

这种区别最大程度地减少了着色器导入时间; 否则,我们将需要对着色器中包含的所有文件运行预处理器。

The old shader import path ignores the new directive.

旧的着色器导入路径会忽略新的指令。

Conditional shader compilation directive selection Running the preprocessor during shader importing makes it possible to wrap #pragma directives that control shader compilation in preprocessor conditionals.

条件着色器编译指令选择 在着色器导入期间运行预处理器可以将控制着色器编译的#pragma指令包装在预处理器条件中。

Not every conditional can affect #pragma selection. The preprocessor detects where the arguments for the conditional expression come from. This prevents recursion and minimizes intrusion into the shader compilation pipeline. The conditional affects #pragma directive reporting only if it depends on generic macro definitions (Unity version or UNITY_OLD_PREPROCESSOR macros), user macro definitions, or platform keywords that depend on the build target and cannot be configured by other means. The latter include SHADER_API_DESKTOP, SHADER_API_MOBILE, UNITY_NO_CUBEMAP_ARRAY, UNITY_FRAMEBUFFER_FETCH_AVAILABLE, UNITY_USE_NATIVE_HDR and UNITY_NO_RGBM as well as console SHADER_API_<CONSOLE> keywords, because these depend on build target only. Note that user macro definitions do not include user keywords specified with #pragma multi_compile or #pragma shader_feature directives.

并非每个条件都会影响#pragma选择。 预处理程序检测条件表达式的参数来自何处。 这样可以防止递归并最大程度地减少对着色器编译管道的入侵。 仅当条件条件依赖于通用宏定义(Unity版本或UNITY_OLD_PREPROCESSOR宏),用户宏定义或依赖于构建目标且无法通过其他方式配置的平台关键字时,它才会影响#pragma指令报告。 后者包括SHADER_API_DESKTOP,SHADER_API_MOBILE,UNITY_NO_CUBEMAP_ARRAY,UNITY_FRAMEBUFFER_FETCH_AVAILABLE,UNITY_USE_NATIVE_HDR和UNITY_NO_RGBM以及控制台SHADER_API_ <CONSOLE>关键字,因为它们仅取决于生成目标。 请注意,用户宏定义不包括使用#pragma multi_compile或#pragma shader_feature指令指定的用户关键字。

Example of valid usage:

有效用法示例:

1
2
3
4
5
6
7
8
#pragma vertex vert
#if defined(SHADER_API_XBOXONE) || defined(SHADER_API_PS4)
#pragma fragment ConsoleFrag
#elif defined(SHADER_API_SWITCH) || defined(SHADER_API_MOBILE)
#pragma fragment MobileFrag
#else
#pragma fragment DesktopFrag
#endif
1
2
3
4
5
6
7
8
#pragma vertex vert
#if defined(SHADER_API_XBOXONE) || defined(SHADER_API_PS4)
#pragma fragment ConsoleFrag
#elif defined(SHADER_API_SWITCH) || defined(SHADER_API_MOBILE)
#pragma fragment MobileFrag
#else
#pragma fragment DesktopFrag
#endif

Example of invalid usage:

无效用法示例:

1
2
3
4
5
6
7
8
9
#pragma multi_compile __ A B
#pragma vertex vert
#if defined(A)
#pragma fragment FragA
#elif defined(B)
#pragma fragment FragB
#else
#pragma fragment Frag
#endif
1
2
3
4
5
6
7
8
9
#pragma multi_compile __ A B
#pragma vertex vert
#if defined(A)
#pragma fragment FragA
#elif defined(B)
#pragma fragment FragB
#else
#pragma fragment Frag
#endif

Changes in preprocessing behavior The new shader preprocessing solution features the following noteworthy differences in behavior:

预处理行为变化 新的着色器预处理解决方案在行为上具有以下值得注意的差异:

  • #pragma warning is now supported

    现在支持#pragma警告

  • #include directive parameters are now macro-expanded if they don’t match the regular format (“#include <my_include_file>” or “#include “my_include_file””)

    如果#include指令参数与常规格式不匹配,则可以对其进行宏扩展(“ #include <my_include_file>”或“ #include“ my_include_file””)

  • #line directive parameters are now macro-expanded if they don’t match the regular format (“#line” followed by unsigned integer and, optionally, by a file name)

    现在,如果#line指令参数与常规格式不匹配,则可以对其进行宏扩展(“ #line”后跟无符号整数,还可以选择文件名)

  • When a macro is redefined, a warning is issued if the new definition differs from the previous one

    重新定义宏时,如果新定义与先前的定义不同,则会发出警告。

  • Macro expansion fully conforms to the C language standard

    宏扩展完全符合C语言标准

  • Ill-formed #undef directives are no longer ignored if the first argument is an identifier

    如果第一个参数是标识符,则不再忽略格式错误的#undef指令

  • Stringizing is now supported fully

    现在完全支持字符串化

  • Concatenation now works in macros without arguments

    串联现在可以在不带参数的宏中使用

  • Invalid concatenation now issues a warning

    无效的串联现在发出警告

  • Macro parameters are not expanded when used for stringizing or concatenation

    用于字符串化或串联时, 宏参数 不会 扩展

  • Shift operators are now supported in conditional expressions

    现在条件表达式中支持Shift运算符

  • When the preprocessor encounters a macro name that has no parameters when it should have parameters, no error is generated and no macro expansion happens

    当预处理器遇到应具有参数的无参数的宏名称时,不会产生错误,也不会发生宏扩展

  • “\\\n” (backslash followed by newline) is not treated as space anymore

    “ \\\ n”(反斜杠后跟换行符)不再被视为空格

The old shader import pipeline now defines a UNITY_OLD_PREPROCESSOR macro, which can be used to distinguish between the two preprocessors.

现在,旧的着色器导入管道定义了一个UNITY_OLD_PREPROCESSOR宏,该宏可用于区分两个预处理器。

让我们知道您的想法 (Let us know what you think)

Caching Shader Preprocessor is a new feature. It is marked as experimental in Unity 2020.1 and applies across all platforms and render pipelines. 

缓存着色器预处理器是一项新功能。 它在Unity 2020.1中被标记为实验性的,并适用于所有平台和渲染管道。

We intend to have it fully available by the end of the 2020 version cycle, so try out the feature in Unity 2020.1 beta and give your feedback on the forum.

我们打算在2020年版本周期结束时使其完全可用,因此请试用Unity 2020.1 beta中的功能,并 在论坛上 提供您的 反馈。

翻译自: https://blogs.unity3d.com/2020/05/06/faster-builds-with-the-new-caching-shader-preprocessor-experimental/

着色缓存器