剥离脚本化着色器变体

2023-10-09 16:40
文章标签 脚本 变体 着色器 剥离

本文主要是介绍剥离脚本化着色器变体,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Massively reduce Player build time and data size by allowing developers to control which Shader variants are handled by the Unity Shader compiler and included in the Player data.

通过允许开发人员控制Unity Shader编译器处理哪些Shader变体并将其包含在Player数据中,来大大减少Player的构建时间和数据大小。

Player build time and data size increase along with the complexity of your project because of the rising number of shader variants.

由于着色器变体的数量不断增加,播放器的构建时间和数据大小会随着项目的复杂性而增加。

With scriptable shader variants stripping, introduced in 2018.2 beta, you can manage the number of shader variants generated and therefore drastically reduce Player build time and data size.

通过2018.2 beta中引入的可脚本化的着色器变体剥离功能,您可以管理生成的着色器变体的数量,从而大大减少Player的构建时间和数据大小。

This feature allows you to strip all the shader variants with invalid code paths, strip shader variants for unused features or create shader build configurations such as “debug” and “release” without affecting iteration time or maintenance complexity.

此功能使您可以剥离带有无效代码路径的所有着色器变体,为未使用的功能剥离着色器变体或创建着色器构建配置(例如“调试”和“发布”),而不会影响迭代时间或维护复杂性。

In this blog post, we first define some of the terms we use. Then we focus on the definition of shader variants to explain why we can generate so many. This is followed by a description of automatic shader variants stripping and how scriptable shader variants stripping is implemented in the Unity shader pipeline architecture. Then, we look at the scriptable shader variants stripping API before discussing results on the Fountainbleau demo and concluding with some tips on writing stripping scripts.

在此博客文章中,我们首先定义一些我们使用的术语。 然后,我们着重介绍着色器变体的定义,以解释为什么我们可以生成这么多变体。 接下来是对自动着色器变体剥离的描述,以及如何在Unity着色器管道体系结构中实现可脚本化的着色器变体剥离。 然后,在讨论Fountainbleau演示的结果并总结一些编写剥离脚本的技巧之前,我们先看一下可脚本化的着色器变体剥离API。

Learning scriptable shader variants stripping is not a trivial undertaking, but it can lead to a massive increase in team efficiency!

学习可脚本化的着色器变体剥离并不是一件容易的事,但是它可以大大提高团队效率!

概念 (Concepts)

To understand the scriptable shader variants stripping feature it is important to have a precise understanding of the different concepts involved.

要了解可编写脚本的着色器变体剥离功能,重要的是要对所涉及的不同概念有一个精确的了解。

  • Shader asset: The full file source code with properties, sub-shader, passes, and HLSL.

    着色器资产 :包含属性,子着色器,过程和HLSL的完整文件源代码。

In Unity, uber shaders are managed by ShaderLab sub shaders, passes, and shader types as well as the  #pragma multi_compile and #pragma shader_feature preprocessor directives.

在Unity中,超级着色器由ShaderLab子着色器,过程和着色器类型以及#pragma multi_compile和#pragma shader_feature 预处理器指令管理 。

计算生成的着色器变体的数量 (Counting the number of shader variants generated)

To use scriptable shader variant stripping, you need a clear understanding of what a shader variant is, and how shader variants are generated by the shader build pipeline. The number of shader variants generated is directly proportional to the build time and the Player shader variant data size. A shader variant is one output of the shader build pipeline.

要使用可脚本化的着色器变体剥离,您需要清楚地了解什么是着色器变体,以及着色器构建管道如何生成着色器变体。 生成的着色器变量的数量与构建时间和Player着色器变量的数据大小成正比。 着色器变体是着色器构建管道的一个输出。

Shader keywords are one of the elements that cause the generation of shader variants. An unconsidered use of shader keywords can quickly lead to a shader variants count explosion and therefore extremely long build time.

着色器关键字是导致生成着色器变体的元素之一。 不考虑使用着色器关键字会Swift导致着色器变体数量激增,因此构建时间非常长。

To see how shader variants are generated, the following simple shader couns how many shader variants it produces:

若要查看着色器变体的生成方式,以下简单的着色器会计算出它会生成多少个着色器变体:

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
Shader "ShaderVariantsStripping"
{
SubShader
{
Pass
{
Name "ShaderVariantsStripping/Pass"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile COLOR_ORANGE COLOR_VIOLET COLOR_GREEN COLOR_GRAY
#pragma multi_compile OP_ADD OP_MUL OP_SUB
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 get_color()
{
#if defined(COLOR_ORANGE)
return fixed4(1.0, 0.5, 0.0, 1.0);
#elif defined(COLOR_VIOLET)
return fixed4(0.8, 0.2, 0.8, 1.0);
#elif defined(COLOR_GREEN)
return fixed4(0.5, 0.9, 0.3, 1.0);
#elif defined(COLOR_GRAY)
return fixed4(0.5, 0.9, 0.3, 1.0);
#else
#error "Unknown 'color' keyword"
#endif
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 diffuse = tex2D(_MainTex, i.uv);
fixed4 color = get_color();
#if defined(OP_ADD)
return diffuse + color;
#elif defined(OP_MUL)
return diffuse * color;
#elif defined(OP_SUB)
return diffuse - color;
#else
#error "Unknown 'op' keyword"
#endif
}
ENDCG
}
}
}

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
Shader "ShaderVariantsStripping"
{
SubShader
{
Pass
{
Name "ShaderVariantsStripping/Pass"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile COLOR_ORANGE COLOR_VIOLET COLOR_GREEN COLOR_GRAY
#pragma multi_compile OP_ADD OP_MUL OP_SUB
struct appdata
{
float4 vertex : POSITION ;
float2 uv : TEXCOORD0 ;
} ;
struct v2f
{
float2 uv : TEXCOORD0 ;
float4 vertex : SV_POSITION ;
} ;
sampler2D _MainTex ;
float4 _MainTex_ST ;
v2f vert ( appdata v )
{
v2f o ;
o . vertex = UnityObjectToClipPos ( v . vertex ) ;
o . uv = v . uv ;
return o ;
}
fixed4 get_color ( )
{
#if defined(COLOR_ORANGE)
return fixed4 ( 1.0 , 0.5 , 0.0 , 1.0 ) ;
#elif defined(COLOR_VIOLET)
return fixed4 ( 0.8 , 0.2 , 0.8 , 1.0 ) ;
#elif defined(COLOR_GREEN)
return fixed4 ( 0.5 , 0.9 , 0.3 , 1.0 ) ;
#elif defined(COLOR_GRAY)
return fixed4 ( 0.5 , 0.9 , 0.3 , 1.0 ) ;
#else
#error "Unknown 'color' keyword"
#endif
}
fixed4 frag ( v2f i ) : SV_Target
{
fixed4 diffuse = tex2D ( _MainTex , i . uv ) ;
fixed4 color = get_color ( ) ;
#if defined(OP_ADD)
return diffuse + color ;
#elif defined(OP_MUL)
return diffuse * color ;
#elif defined(OP_SUB)
return diffuse - color ;
#else
#error "Unknown 'op' keyword"
#endif
}
ENDCG
}
}
}

The total number of shader variants in a project is deterministic and given by the following equation:

项目中着色器变体的总数是确定性的,并由以下公式给出:

Keywords in the equation refers to both platform and shader keywords. A graphics tier is a specific platform keyword set combination.

公式中的关键字指的是平台和Shader关键字。 图形层是特定的平台关键字集组合。

The ShaderVariantStripping/Pass has two multi compile directives. The first directive defines 4 keywords (COLOR_ORANGE, COLOR_VIOLET, COLOR_GREEN, COLOR_GRAY) and the second directive defines 3 keywords (OP_ADD, OP_MUL, OP_SUB). Finally, the pass defines 2 shader stages: a vertex shader stage and a fragment shader stage.

ShaderVariantStripping / Pass具有两个多重编译指令。 第一个指令定义4个关键字(COLOR_ORANGE,COLOR_VIOLET,COLOR_GREEN,COLOR_GRAY),第二个指令定义3个关键字(OP_ADD,OP_MUL,OP_SUB)。 最后,该遍定义了两个着色器阶段:一个顶点着色器阶段和一个片段着色器阶段。

This shader variant total is given for a single supported graphics API. However, for each supported graphics API in the project, we need a dedicated set of shader variants. For example, if we build an Android Player that supports both OpenGL ES 3 and Vulkan, we need two sets of shader variants. As a result, the Player build time and shader data size are directly proportional to the number of supported graphics APIs.

此着色器变体总数是针对单个受支持的图形API给出的。 但是,对于项目中每个受支持的图形API ,我们需要一组专用的着色器变体。 例如,如果我们构建一个同时支持OpenGL ES 3和Vulkan的Android Player,则需要两组着色器变体。 因此,Player的构建时间和着色器数据大小与支持的图形API的数量成正比。

着色器构建管道 (Shader build pipeline)

The shader compilation pipeline in Unity is a black box where each shader in the project is parsed to extract shader snippets before collecting the variant preprocessing instructions, such as multi_compile and shader_feature. This produces a list of compilation parameters, one per shader variant.

Unity中的着色器编译管道是一个黑匣子,在此项目中每个着色器都经过解析,以在收集变体预处理指令(例如multi_compile和shader_feature)之前提取着色器片段。 这将生成一个编译参数列表,每个着色器变体一个。

These compilation parameters include the shader snippet, the graphics tier, the shader type, the shader keyword set, the pass type and name. Each of the set compilation parameters are used to produce a single shader variant.

这些编译参数包括着色器代码段,图形层,着色器类型,着色器关键字集,通过类型和名称。 每个设置的编译参数都用于生成单个着色器变体。

Consequently, Unity executes an automatic shader variant stripping pass based on two heuristics. Firstly, stripping is based on the Project Settings, for example, if Virtual Reality Supported is disabled then VR shader variants are systematically stripped. Second, the automatic stripping is based on the configuration of Shader Stripping section of the Graphics Settings.

因此,Unity基于两种启发式算法执行自动着色器变体剥离过程。 首先,剥离是基于项目设置的,例如,如果禁用“支持虚拟现实”,则系统地剥离VR着色器变体。 其次,自动剥离基于“ 图形设置”的“着色器剥离”部分的配置。

Automatic shader variants stripping options in the GraphicsSettings.

GraphicsSettings中的自动着色器变体剥离选项。

Automatic shader variants stripping is based on build time restrictions. Unity can’t automatically select only the necessary shader variants at build time because those shader variants depend on runtime C# execution. For example, if a C# script adds a point light but there were no point lights at build time, then there is no way for the shader build pipeline to figure out that the Player would need a shader variant that does point light shading.

自动着色器变体剥离是基于构建时间限制的。 Unity无法在构建时自动选择必要的着色器变体,因为这些着色器变体取决于运行时C#执行。 例如,如果C#脚本添加了一个点光源,但在构建时没有点光源,则着色器构建管道无法确定Player是否需要进行点光源着色的着色器变体。

Here’s a list of shader variants with enabled keywords that get stripped automatically:

这是带有启用的关键字的着色器变体的列表,这些自动被剥离:

Lightmap modes: LIGHTMAP_ON, DIRLIGHTMAP_COMBINED, DYNAMICLIGHTMAP_ON, LIGHTMAP_SHADOW_MIXING, SHADOWS_SHADOWMASK

光照贴图模式:LIGHTMAP_ON,DIRLIGHTMAP_COMBINED,DYNAMICLIGHTMAP_ON,LIGHTMAP_SHADOW_MIXING,SHADOWS_SHADOWMASK

Fog modes: FOG_LINEAR, FOG_EXP, FOG_EXP2

雾模式:FOG_LINEAR,FOG_EXP,FOG_EXP2

Instancing Variants: INSTANCING_ON

实例变体:INSTANCING_ON

Furthermore, when Virtual Reality support is disabled, the shader variants with the following built-in enabled keywords are stripped:

此外,禁用虚拟现实支持后,将剥离具有以下内置启用的关键字的着色器变体:

STEREO_INSTANCING_ON, STEREO_MULTIVIEW_ON, STEREO_CUBEMAP_RENDER_ON, UNITY_SINGLE_PASS_STEREO

STEREO_INSTANCING_ON,STEREO_MULTIVIEW_ON,STEREO_CUBEMAP_RENDER_ON,UNITY_SINGLE_PASS_STEREO

When automatic stripping is done, the shader build pipeline uses the remaining compilation parameter sets to schedule shader variant compilation in parallel, launching as many simultaneous compilations as the platform has CPU core threads.

自动剥离完成后,着色器构建管道会使用其余的编译参数集来并行调度着色器变体编译,并启动与平台具有CPU核心线程的数目相同的同时编译。

Here’s a visual representation of that process:

这是该过程的直观表示:

Shader pipeline architecture with scriptable shader variant stripping integration in orange.

具有橙色的可编写脚本的着色器变量剥离集成的着色器管道体系结构。

In Unity 2018.2 beta, the shader pipeline architecture introduces a new stage right before the shader variant compilation scheduling, allowing users to control the shader variant compilation. This new stage is exposed via C# callbacks to user code, and each callback is executed per shader snippet.

在Unity 2018.2 beta中 ,着色器管道架构在着色器变体编译日程安排之前引入了一个新阶段,允许用户控制着色器变体编译。 这个新阶段通过C#回调公开给用户代码,并且每个回调均按着色器代码段执行。

可编写脚本的着色器变体剥离API (Scriptable shader variant stripping API)

As an example, the following script enables stripping of all the shader variants that would be associated with a “DEBUG” configuration, identified by a “DEBUG” keyword used in development Player build.

例如,以下脚本可剥离所有与“ DEBUG”配置相关联的着色器变体,“ DEBUG”配置由开发Player构建中使用的“ DEBUG”关键字标识。

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Rendering;
using UnityEngine;
using UnityEngine.Rendering;
// Simple example of stripping of a debug build configuration
class ShaderDebugBuildProcessor : IPreprocessShaders
{
ShaderKeyword m_KeywordDebug;
public ShaderDebugBuildProcessor()
{
m_KeywordDebug = new ShaderKeyword("DEBUG");
}
// Multiple callback may be implemented.
// The first one executed is the one where callbackOrder is returning the smallest number.
public int callbackOrder { get { return 0; } }
public void OnProcessShader(
Shader shader, ShaderSnippetData snippet, IList<ShaderCompilerData> shaderCompilerData)
{
// In development, don't strip debug variants
if (EditorUserBuildSettings.development)
return;
for (int i = 0; i < shaderCompilerData.Count; ++i)
{
if (shaderCompilerData[i].shaderKeywordSet.IsEnabled(m_KeywordDebug))
{
shaderCompilerData.RemoveAt(i);
--i;
}
}
}
}

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
using System . Collections . Generic ;
using UnityEditor ;
using UnityEditor . Build ;
using UnityEditor . Rendering ;
using UnityEngine ;
using UnityEngine . Rendering ;
// Simple example of stripping of a debug build configuration
class ShaderDebugBuildProcessor : IPreprocessShaders
{
ShaderKeyword m_KeywordDebug ;
public ShaderDebugBuildProcessor ( )
{
m_KeywordDebug = new ShaderKeyword ( "DEBUG" ) ;
}
// Multiple callback may be implemented.
// The first one executed is the one where callbackOrder is returning the smallest number.
public int callbackOrder { get { return 0 ; } }
public void OnProcessShader (
Shader shader , ShaderSnippetData snippet , IList < ShaderCompilerData > shaderCompilerData )
{
// In development, don't strip debug variants
if ( EditorUserBuildSettings . development )
return ;
for ( int i = 0 ; i < shaderCompilerData . Count ; ++ i )
{
if ( shaderCompilerData [ i ] . shaderKeywordSet . IsEnabled ( m_KeywordDebug ) )
{
shaderCompilerData . RemoveAt ( i ) ;
-- i ;
}
}
}
}

OnProcessShader is called right before the scheduling of the shader variant compilation.

在计划着色器变体编译之前,将调用OnProcessShader。

Each combination of a Shader, a ShaderSnippetData and ShaderCompilerData instances is an identifier for a single shader variant that the shader compiler will produce. To strip that shader variant, we only need to remove it from the ShaderCompilerData list.

Shader,ShaderSnippetData和ShaderCompilerData实例的每种组合都是着色器编译器将生成的单个着色器变体的标识符。 要剥离该着色器变体,我们只需要将其从ShaderCompilerData列表中删除即可。

Every single shader variant that the shader compiler should generate will appear in this callback. When working on scripting the shader variants stripping, you need to first figure out which variants need removing, because they’re not useful for the project.

着色器编译器应生成的每个着色器变体都将出现在此回调中。 在编写着色器变体剥离脚本时,您首先需要弄清楚哪些变体需要删除,因为它们对项目没有用。

结果 (Results)

渲染管线的着色器变体剥离 (Shader variants stripping for a render pipeline)

One use case for the scriptable shader variants stripping is to systematically strip invalid shader variants of a render pipeline due to the various combinations of shader keywords.

可脚本化的着色器变体剥离的一个用例是,由于着色器关键字的各种组合,系统地剥离渲染管道的无效着色器变体。

A shader variants stripping script included in the HD render pipeline allows you to systematically reduce the build time and size of a project using the HD render pipeline. This script applies to the following shaders:

HD渲染管道中包含的着色器变体剥离脚本允许您使用HD渲染管道来系统地减少项目的构建时间和大小。 该脚本适用于以下着色器:

HDRenderPipeline/Lit HDRenderPipeline/LitTessellation HDRenderPipeline/LayeredLit HDRenderPipeline/LayeredLitTessellation

HDRenderPipeline / Lit HDRenderPipeline / LitTessellation HDRenderPipeline / LayeredLit HDRenderPipeline / LayeredLitTessellation

The script produces the following results:

该脚本产生以下结果:

UnstrippedStripped
Player Data Shader Variant Count24350 (100%)12122 (49.8%)
Player Data Size on disk511 MB151 MB
Player Build Time4864 seconds1356 seconds
不剥离 剥离
播放器数据着色器变体计数 24350(100%) 12122(49.8%)
磁盘上的播放器数据大小 511兆字节 151兆字节
玩家建立时间 4864秒 1356秒

Screenshot of the Fontainebleau Photogrammetry demo using the HD Render Pipeline from the standard PlayStation 4 1920×1080 resolution.

枫丹白露摄影测量演示的屏幕快照,使用的是标准PlayStation 4 1920×1080分辨率的HD渲染管线。

Furthermore, the Lightweight render pipeline for Unity 2018.2 has a UI to automatically feed a stripping script that can automatically strip up to 98% of the shader variants which we expect to be particularly valuable for mobile projects.

此外,Unity 2018.2的轻量级渲染管道具有一个UI,可以自动提供一个剥离脚本 ,该脚本可以自动剥离多达98%的着色器变体,我们希望这对于移动项目特别有价值。

为项目剥离着色器变体 (Shader variants stripping for a project)

Another use case is a script to strip all the rendering features of a render pipeline that are not used for a specific project. Using an internal test demo for the Lightweight rendering pipeline, we got the following results for the entire project:

另一个用例是一个脚本,用于剥离渲染管道中所有未用于特定项目的渲染功能。 使用针对Lightweight渲染管道的内部测试演示,我们获得了整个项目的以下结果:

UnstrippedStripped
Player Data Shader Variant Count310807056
Player Data Size on disk121116
Player Build Time839 seconds286 seconds
不剥离 剥离
播放器数据着色器变体计数 31080 7056
磁盘上的播放器数据大小 121 116
玩家建立时间 839秒 286秒

As we can see, using scriptable shader variant stripping can lead to significant results and with more work on the stripping script we could go even further.

如我们所见,使用可脚本化的着色器变体剥离可以带来显着的结果,并且通过对剥离脚本进行更多的工作,我们可以走得更远。

Screenshot of a Lightweight pipeline demo.

轻量级管道演示的屏幕截图。

编写着色器变体剥离代码的技巧 (Tips on writing shader variants stripping code)

改进着色器代码设计 (Improving shader code design)

A project may quickly run into a shader variants count explosion, leading to unsustainable compilation time and Player data size. Scriptable shader stripping helps deal with this issue, but you should reevaluate how you are using shader keywords to generate more relevant shader variants. We can rely on the #pragma skip_variants to test unused keywords in the editor.

一个项目可能很快会遇到一个着色器变体,数量激增,从而导致不可持续的编译时间和Player数据大小。 可脚本化的着色器剥离可帮助解决此问题,但您应该重新评估如何使用着色器关键字生成更相关的着色器变体。 我们可以依靠#pragma skip_variants在编辑器中测试未使用的关键字。

For example, in ShaderStripping/Color Shader the preprocessing directives are declared with the following code:

例如,在ShaderStripping / Color Shader中,预处理指令使用以下代码声明:

1

2
#pragma multi_compile COLOR_ORANGE COLOR_VIOLET COLOR_GREEN COLOR_GRAY // color keywords
#pragma multi_compile OP_ADD OP_MUL OP_SUB // operator keywords

1

2
#pragma multi_compile COLOR_ORANGE COLOR_VIOLET COLOR_GREEN COLOR_GRAY // color keywords
#pragma multi_compile OP_ADD OP_MUL OP_SUB // operator keywords

This approach implies that all the combinations of color keywords and operator keywords will be generated.

这种方法意味着将生成颜色关键字和操作员关键字的所有组合。

Let’s say we want to render the following scene:

假设我们要渲染以下场景:

COLOR_ORANGE + OP_ADD, COLOR_VIOLET + OP_MUL, COLOR_GREEN + OP_MUL.

COLOR_ORANGE + OP_ADD,COLOR_VIOLET + OP_MUL,COLOR_GREEN + OP_MUL。

First, we should make sure that every keyword is actually useful. In this scene COLOR_GRAY and OP_SUB are never used. If we can guarantee these keywords are never used, then we should remove them.

首先,我们应该确保每个关键字实际上都是有用的。 在此场景中,从不使用COLOR_GRAY和OP_SUB。 如果我们可以保证不使用这些关键字,则应将其删除。

Second, we should combine keywords that effectively produce a single code path. In this example, the ‘add’ operation is always used with the ‘orange’ color exclusively. So we can combine them in a single keyword and refactor the code as shown below.

其次,我们应该结合有效产生单个代码路径的关键字。 在此示例中,“添加”操作始终与“橙色”颜色一起使用。 因此,我们可以将它们组合为一个关键字,然后重构代码,如下所示。

1

2
3
4
5
6
7
8
9
10
11
12
#pragma multi_compile ADD_COLOR_ORANGE MUL_COLOR_VIOLET MUL_COLOR_GREEN
#if defined(ADD_COLOR_ORANGE)
#define COLOR_ORANGE
#define OP_ADD
#elif defined(MUL_COLOR_VIOLET)
#define COLOR_VIOLET
#define OP_MUL
#elif defined(MUL_COLOR_GREEN)
#define COLOR_GREEN
#define OP_MUL
#endif

1

2
3
4
5
6
7
8
9
10
11
12
#pragma multi_compile ADD_COLOR_ORANGE MUL_COLOR_VIOLET MUL_COLOR_GREEN
#if defined(ADD_COLOR_ORANGE)
#define COLOR_ORANGE
#define OP_ADD
#elif defined(MUL_COLOR_VIOLET)
#define COLOR_VIOLET
#define OP_MUL
#elif defined(MUL_COLOR_GREEN)
#define COLOR_GREEN
#define OP_MUL
#endif

Of course, it’s not always possible to refactor keywords. In these cases, scriptable shader variants stripping is a valuable tool!

当然,并非总是可以重构关键字。 在这些情况下,可脚本化的着色器变体剥离是一个有价值的工具!

使用callbackOrder在多个步骤中剥离着色器变体 (Using callbackOrder to strip shader variants in multiple steps)

For each snippet, all the shader variant stripping scripts are executed. We can order the scripts’ execution by ordering the value returned by the callbackOrder member function. The shader build pipeline will execute the callbacks in order of increasing callbackOrder, so lowest first and highest last.

对于每个片段,将执行所有着色器变体剥离脚本。 我们可以通过对callbackOrder成员函数返回的值进行排序来对脚本的执行进行排序。 着色器构建管道将按递增的callbackOrder顺序执行回调,因此,最低的优先和最高的最后。

A use case for using multiple shader stripping scripts is to separate the scripting per purpose. For example:

使用多个着色器剥离脚本的用例是按用途分隔脚本。 例如:

  • Script 2: Strips all the debug shader variants.

    脚本2:剥离所有调试着色器变体。

编写着色器变体剥离脚本的过程 (Process for writing a shader variants stripping script)

Shader variants stripping is extremely powerful but requires a lot of work to achieve good results.

着色器变体剥离功能非常强大,但需要大量工作才能达到良好的效果。

    下载示例项目 (Download the sample project)

    The example project used to illustrate this blog post can be downloaded here. It requires Unity 2018.2.0b1.

    可以在此处下载用于说明此博客文章的示例项目。 它需要Unity 2018.2.0b1 。

    在Unite Berlin上了解有关优化二进制部署大小的更多信息 (Learn more about optimizing binary deployment size at Unite Berlin)

    Come to Jonas Echterhoff’s June 21 talk and learn about all the new tools that give you more control over what ends up in your build!

    快来参加Jonas Echterhoff于6月21日发表的演讲,了解所有可以使您对构建最终结果有更多控制权的新工具!

    翻译自: https://blogs.unity3d.com/2018/05/14/stripping-scriptable-shader-variants/

    这篇关于剥离脚本化着色器变体的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



    http://www.chinasem.cn/article/174158

    相关文章

    基于Python编写一个git自动上传的脚本(打包成exe)

    《基于Python编写一个git自动上传的脚本(打包成exe)》这篇文章主要为大家详细介绍了如何基于Python编写一个git自动上传的脚本并打包成exe,文中的示例代码讲解详细,感兴趣的小伙伴可以跟... 目录前言效果如下源码实现利用pyinstaller打包成exe利用ResourceHacker修改e

    Linux下MySQL数据库定时备份脚本与Crontab配置教学

    《Linux下MySQL数据库定时备份脚本与Crontab配置教学》在生产环境中,数据库是核心资产之一,定期备份数据库可以有效防止意外数据丢失,本文将分享一份MySQL定时备份脚本,并讲解如何通过cr... 目录备份脚本详解脚本功能说明授权与可执行权限使用 Crontab 定时执行编辑 Crontab添加定

    Java调用Python脚本实现HelloWorld的示例详解

    《Java调用Python脚本实现HelloWorld的示例详解》作为程序员,我们经常会遇到需要在Java项目中调用Python脚本的场景,下面我们来看看如何从基础到进阶,一步步实现Java与Pyth... 目录一、环境准备二、基础调用:使用 Runtime.exec()2.1 实现步骤2.2 代码解析三、

    Python脚本轻松实现检测麦克风功能

    《Python脚本轻松实现检测麦克风功能》在进行音频处理或开发需要使用麦克风的应用程序时,确保麦克风功能正常是非常重要的,本文将介绍一个简单的Python脚本,能够帮助我们检测本地麦克风的功能,需要的... 目录轻松检测麦克风功能脚本介绍一、python环境准备二、代码解析三、使用方法四、知识扩展轻松检测麦

    基于Python Playwright进行前端性能测试的脚本实现

    《基于PythonPlaywright进行前端性能测试的脚本实现》在当今Web应用开发中,性能优化是提升用户体验的关键因素之一,本文将介绍如何使用Playwright构建一个自动化性能测试工具,希望... 目录引言工具概述整体架构核心实现解析1. 浏览器初始化2. 性能数据收集3. 资源分析4. 关键性能指

    shell脚本批量导出redis key-value方式

    《shell脚本批量导出rediskey-value方式》为避免keys全量扫描导致Redis卡顿,可先通过dump.rdb备份文件在本地恢复,再使用scan命令渐进导出key-value,通过CN... 目录1 背景2 详细步骤2.1 本地docker启动Redis2.2 shell批量导出脚本3 附录总

    Oracle数据库定时备份脚本方式(Linux)

    《Oracle数据库定时备份脚本方式(Linux)》文章介绍Oracle数据库自动备份方案,包含主机备份传输与备机解压导入流程,强调需提前全量删除原库数据避免报错,并需配置无密传输、定时任务及验证脚本... 目录说明主机脚本备机上自动导库脚本整个自动备份oracle数据库的过程(建议全程用root用户)总结

    linux下shell脚本启动jar包实现过程

    《linux下shell脚本启动jar包实现过程》确保APP_NAME和LOG_FILE位于目录内,首次启动前需手动创建log文件夹,否则报错,此为个人经验,供参考,欢迎支持脚本之家... 目录linux下shell脚本启动jar包样例1样例2总结linux下shell脚本启动jar包样例1#!/bin

    golang程序打包成脚本部署到Linux系统方式

    《golang程序打包成脚本部署到Linux系统方式》Golang程序通过本地编译(设置GOOS为linux生成无后缀二进制文件),上传至Linux服务器后赋权执行,使用nohup命令实现后台运行,完... 目录本地编译golang程序上传Golang二进制文件到linux服务器总结本地编译Golang程序

    利用Python脚本实现批量将图片转换为WebP格式

    《利用Python脚本实现批量将图片转换为WebP格式》Python语言的简洁语法和库支持使其成为图像处理的理想选择,本文将介绍如何利用Python实现批量将图片转换为WebP格式的脚本,WebP作为... 目录简介1. python在图像处理中的应用2. WebP格式的原理和优势2.1 WebP格式与传统