URP 渲染实战 / 第 2 章 URP 架构与一帧的流程 / 案例 2.6
案例 2.6兼容与不兼容 SRP Batcher 的 Shader入门
目标:对比两个功能完全相同的 Shader,一个兼容 SRP Batcher,一个不兼容,并学会检查兼容性。
Assets/Cookbook/Ch02/SrpBatcherCompatible.shader(节选:cbuffer)
// 纹理对象本身不进 CBUFFER,但它的 _ST(缩放平移)是数值,要进 TEXTURE2D(_BaseMap); SAMPLER(sampler_BaseMap); CBUFFER_START(UnityPerMaterial) float4 _BaseMap_ST; half4 _BaseColor; CBUFFER_END
Assets/Cookbook/Ch02/SrpBatcherBroken.shader(节选:broken)
TEXTURE2D(_BaseMap); SAMPLER(sampler_BaseMap); float4 _BaseMap_ST; // ✗ 不在 UnityPerMaterial 里 half4 _BaseColor; // ✗ 不在 UnityPerMaterial 里
两个 Shader 都能正常编译、正常显示,区别只在声明位置。选中 Shader 资产,Inspector 里会显示 “SRP Batcher: compatible” 或 “not compatible” 以及原因。本书在批处理模式下读取了同一个检查结果(Shader Inspector 背后的接口),得到的原因原文是:
SrpBatcherCompatible : OK SrpBatcherBroken : Material property is found in another cbuffer than "UnityPerMaterial" (_BaseColor) LightModeDemo : OK (三个 Pass 共用同一个 UnityPerMaterial)
常见的不兼容原因:
- 材质属性写在 CBUFFER 外(本例);或者不同 Pass 的
UnityPerMaterial内容不一致(例如某个 Pass 用UsePass引用了别的 Shader 的 Pass,而两者的 CBUFFER 布局不同)。 - 纹理的
_ST、_TexelSize等数值属性忘了放进 CBUFFER。注意纹理对象本身(TEXTURE2D)不放进 CBUFFER。 - 不是 Shader 的问题,而是用法的问题:对 Renderer 使用了
MaterialPropertyBlock,该物体就退出 SRP Batcher;粒子系统等非 MeshRenderer/SkinnedMeshRenderer 的渲染器也不参与。
验证是否真正生效:打开 Frame Debugger,选中某个绘制事件,右侧会显示它是否属于一个 SRP Batch,以及“为什么没有和上一个合批”的原因(例如 “Node use different shader keywords”——不同的关键字组合是不同的 Shader 变体,无法合进同一个 SRP Batch)。第 29 章会系统地讨论 SRP Batcher、GPU Instancing 与静态合批的取舍。
本案例出自《URP 渲染实战》第 2 章「URP 架构与一帧的流程」。在章节中阅读上下文 →