目录
目录
Shader compilation
Conditionals in shaders
Different types of conditionals
Switch code branch at runtime
Branching in shaders
Static branching
How to use static branching
Dynamic branching
How to use dynamic branching
Shader variants
Deduplication of shader variants
Check how many shader variants you have
获取editor下使用的变体数量
获取build时的变体数量
Shader keywords
Definition type: “multi compile” or “shader feature”
Local or global scope
Stage-specific keywords
Create a shader variant for disabled keywords
Using shader keywords with C# scripts
Local Shader Keywords:
Global Shader Keywords:
How Unity loads and uses shaders
Prewarming shader variants
Profiler 中对shader loading 的标记:
1. 编译分为两种:Editor、Runtime
Editor:
Runtime:
2. 不同的平台,Shader编译器会有所不同
3. 一个shader包含在多个material里面,打进assetbundle中,会导致有多份shader,同时也打断了合批,可以使用 Asset Bundle Browser 来检查bundle的依赖
shader 使用条件的方法有下面三种:
使用 shader variants 这种方法,build的时候会剔除未使用的变体,所以这种情况,应该避免在c#中enable/disable
shader_feature
keywords,因为有可能启用的变体,没有打到包里,如果该变体没有,则会选择一个默认的使用如果需要在c#中enable/disable
shader_feature
keywords,则应该让所有的shader变体都包含在包体里面,采用下面两种方法:
- 创建一个 shader variant collection 资源,包所有的变体,添加进去
- Include a Material in your build for every combination of
shader_feature
keywords you want to use.
在c#代码中切换shader的分支,有两种方法:
#pragma shader_feature REFLECTION_TYPE1 REFLECTION_TYPE2 REFLECTION_TYPE3
Shader directive | Branching type | Shader variants Unity creates |
---|---|---|
shader_feature |
Static branching | Variants for keyword combinations you enable at build time (只是enable的shader_feature的组合) |
multi_compile |
Static branching | Variants for every possible combination of keywords |
dynamic_branch |
Dynamic branching | No variants |
根据shader 执行branch 的方式,分为两种:
在运行之前就已经编译好的叫静态branch
三种方法:
if
statements can also be used for dynamic branches, the compiler detects the compile-time constant value and creates a static branch instead.Note: Static branching is available only in hand-coded shaders. You cannot create static branches in Shader Graph.
它又分为两种:
基于uniform variables通常更有效,因为uniform variables对于整个drawcall是恒定的
Note:所有的分支都会编译成程序,写进shader里面,这会增加文件的大小,但是相比较多个变体来说,它还是小的
You can use dynamic branching in your shaders in the following ways:
使用 shader keywords.来配置variants,构建的时候,每一个变体,都是一段shader 代码
Select Save to asset… to create a shader variant collection asset.
打开Editor.log
文件(menu: Window > General > Console and select Open Editor Log from the Console window menu.),搜索 Compiling shader
通过shader keywords 的方法,可以在shader 里面使用条件语句
一个集合的keywords 叫作Keyword,里面的单个keyword叫作state
shader 中声明keywords的type有两种:
1.multi compile:这里面声明的任何keyword 都会编译成变体
2.shader feature:只有enable的keyword才会编译成变体打进包里,其它的都被裁剪了
Note: 如果把shader添加projectsetting->graphics-> Always Included Shaders 里面,unity 会把它里面的所有keyword都包含在包体里面,即使type 是 shader_feature.
默认声明的keyword 都是global的,但是可以在声明keyword type的时候,加上后缀_local 来表示是local的,加上之后表示不可override的,也就是同名的不能复写它
默认,Unity为每个stage声明相同的变体,比如, shader中包含 vertex stage and a fragment stage, Unity 会为它们声明同样的变体,假如只在一个stage中用到了keywords,就会导致变体在另一个stage中是重复的,Unity 会自动识别,并裁剪它们,所以不会增加包体大小, but they still result in wasted compilation time, increased shader loading times, and increased runtime memory usage.
为了避免这个问题,在声明keywords type的时候,加上特定的后缀,表示是哪个stage用的
比如:
_vertex
_fragment
_hull
_domain
_geometry
_raytracing
#pragma shader_feature_fragment RED GREEN BLUE--表明是在fragment stage用的
如果用 shader_feature
创建 single keyword, 当该keyword disable 的时候Unity 会自动创建second variant. This helps reduce the number of keywords you need to enable and disable. For example, the following code creates 2 variants:
#pragma shader_feature EXAMPLE_ON
如果使用 multi_compile/
shader_feature
创建 two or more keywords, 使用 _
,当该集合中的所有关键字被禁用时,创建一个着色器变体
#pragma multi_compile _ EXAMPLE_ON
#pragma shader_feature _ RED GREEN BLUE WHITE
在运行时,切换不同的变体,容易对性能造成影响,如果该变体之前没有加载过,且是复杂的变体,容易造成画面卡顿的情况。如果使用global keywords,同时修改多个shader,也容易造成同样的问题
为了避免使用时,加载出停滞的情况,可以采用预加载的方式:
也可以在projectsetting->graphics 里面配置Preloaded shaders section of the Graphics Settings window. Unity uses the ShaderVariantCollection.WarmUp
API to load and prewarm the shader variant collections when your built application starts.
Shader.ParseThreaded、
Shader.ParseMainThread
for Unity loading the shader object from serialized data.Shader.CreateGPUProgram
for Unity creating a GPU-specific version of a shader variant