Shader优化-变体

介绍Shader变体的优化方法。

shader_feature 和 multi_complie 是两个很相似的预编译指令,声明Keyword(宏标识符)。在Shader代码中控制开启宏或关闭宏时物体的渲染过程。最终编译的时候也是根据这些不同的宏来编译生成多种组合形式的Shader源码。其中每一种组合就是这个Shader的一个变体(Variant)。

优化思路大致是四个方面:控制总量,剔除冗余,精准加载,加载策略

一 Keyword关键字

Global Keyword关键字限制

早期版本256,不能满足更复杂项目的需求。
在2020.3,数量限制是384。
建议升级到2021.2以上,来规避这个Keyword上限约束。

Unity can use up to 4,294,967,294 global shader keywords. Individual shaders and compute shaders can use up to 65,534 local shader keywords.

Keyword越多、变体越多,其内存占用越大。可以使用shader_feature代替multi_compile。

二 剔除

上文提到,特别是URP管线出现之后,Keywords数量快速增长,编译后的变体数量更是指数级增长,所以无效变体的剔除是打包过程中必须的一步操作。

如图ShaderLab总内存控制在30M左右没有问题,但是PBR_SceneCommon Shader很⼤,可以分析变体关键字,去除不⽤的变体。

可以参考:Stripping scriptable shader variants | Unity Blog

三 Warmup

未做Warmup的Shader,第一次渲染时有CreateGPUProgram的开销。

(1) 常驻的Shader

一些通用的基础的Shader,配置在Always include预加载Shader列表,再调用Shader.WarmupAllShaders。

WarmupAllshader不影响Shader的加载,是提前将所有已加载的Shader都做一次快速渲染/初始化,防止这部分开销(CreateGPUProgram)分散出现在运行时一些总开销较高的时候。

(2) 动态加载的Shader

通过创建SVC,加载,再ShaderVariantCollection.WarmUp。

四 加载优化

(1) Dynamic shader variant loading
对于Shader变体较多的shader,Unity新引入了Dynamic shader variant loading功能。
Dynamic Shader Variant Loading

(2) 可控的Shader变体加载
在运行时,动态收集特定时间段内的shader变体使用情况。保存为SVC,方便开发者对shader的变体使用进行控制

五 Editor Project Settings

Built-in管线

URP管线

参考