Unity优化篇之SRP Batching

发布于:2025-06-09 ⋅ 阅读:(14) ⋅ 点赞:(0)
  • 原理
  • 使用条件
  • 对 Shader 的要求
  • 成功与失败的判断标准
  • 优缺点
  • 与其他技术的关系

🚀 Unity SRP Batcher 深度解析:原理、优势、限制与最佳实践

Unity 的 SRP Batcher 是现代渲染管线(URP/HDRP)中最重要的性能优化技术之一,合理使用可显著减少 CPU 开销、提升大规模场景下的渲染效率。


📌 什么是 SRP Batcher?

SRP Batcher(Scriptable Render Pipeline Batcher) 是 Unity 在 URP 和 HDRP 渲染管线中提供的一种批处理优化机制。

它的目标是:

减少 CPU 与 GPU 之间频繁的材质状态(Shader 常量)设置,从而降低 SetPass Call 数量,提升渲染效率。


🧠 它是怎么工作的?

在传统渲染中,每个物体渲染前,CPU 都需要将该物体使用的材质属性上传给 GPU:

[每个物体] → [Shader 参数打包 → 上传 GPU] → [Draw]

这种频繁的数据上传,会导致:

  • 大量 CPU 时间耗在 SetPass 阶段
  • GPU 等待 CPU 指令完成

SRP Batcher 的优化方式是:

[多个物体使用同 Shader/Variant] → [预缓存参数块] → [只更新偏移指针] → [Draw]

即:将每个材质使用的属性缓存在 GPU 的统一结构中,同一 Shader Variant 的材质只切换缓存偏移,无需重新上传整个参数列表!


✅ SRP Batcher 的核心优化点

优化项 描述
✅ 减少 SetPass Call 合并多个材质的上传流程
✅ 材质常量重用 避免重复上传一致结构的参数
✅ 批量提交 Draw Call 保持每个材质独立,但处理统一结构更高效

📦 开启 SRP Batcher 的方式

  1. 使用 URP 或 HDRP 管线(即 SRP 系列)

  2. 在对应 Render Pipeline Asset 中勾选 ✅ SRP Batcher

    • Project Settings > Graphics > Render Pipeline Asset > SRP Batcher

SRP Batcher 默认是启用的,但不是所有 Shader 都自动兼容它!


🎨 Shader 的要求

要让 Shader 支持 SRP Batcher,需要满足以下结构和编写方式:

要求 说明
✅ 使用 HLSL + ShaderLab 写法 Surface Shader 不支持 SRP Batcher
✅ 所有材质属性必须在 CBUFFER_START(UnityPerMaterial) 内声明 SRP Batcher 依赖此结构统一参数布局
✅ 不使用全局变量、uniform 单独声明 所有属性必须集中封装
✅ 不使用 Material.SetXXX() 修改属性 会破坏 SRP 缓存结构,打断合批
✅ 不使用 MaterialPropertyBlock 设置非 instanced 属性 也会打断 SRP Batcher 合批(可以用 instancing)

✅ 示例 Shader(支持 SRP Batcher)

Shader "MySRP/Simple"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
    }
    SubShader
    {
        Tags { "RenderPipeline"="UniversalRenderPipeline" }

        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

            // ✅ SRP Batcher 要求
            CBUFFER_START(UnityPerMaterial)
                float4 _Color;
            CBUFFER_END

            struct Attributes { float4 positionOS : POSITION; };
            struct Varyings { float4 positionHCS : SV_POSITION; };

            Varyings vert (Attributes v)
            {
                Varyings o;
                o.positionHCS = TransformObjectToHClip(v.positionOS);
                return o;
            }

            half4 frag (Varyings i) : SV_Target
            {
                return _Color;
            }

            ENDHLSL
        }
    }
}

🧪 如何确认 SRP Batcher 生效?

✅ 使用 Frame Debugger 检查:

  1. 打开 Window > Analysis > Frame Debugger
  2. 启用调试
  3. 查看某个 Draw Call
  4. 在右侧详情中查找:
SRP Batcher enabled: true

如为 false,说明你的 Shader/材质不满足条件。


❌ SRP Batcher 失效的常见原因

原因 描述
❌ Shader 使用 Surface Shader 写法 Surface Shader 不支持 SRP 架构
❌ 材质属性未放入 CBUFFER SRP Batcher 识别不到统一结构
❌ 使用了 Material.SetFloat() 会创建一个新的 GPU 实例缓存,打断 SRP 合批
❌ 使用了 Shader Keywords 但 Variant 不一致 变体不同视为不同 Shader,不可合批
❌ 使用 ShaderGraph 但未设为 SRP 兼容结构(极少见) 可通过 ShaderGraph 默认行为规避

✅ 优点总结

优点 描述
✅ 极大减少 SetPass Calls 同一 Variant 的材质只上传一次结构描述
✅ 保留每个材质独立参数 不需要合并网格、材质等
✅ 和 GPU Instancing 可并用 双重优化,性能爆发
✅ 无需修改场景结构 比 Static Batching 灵活、安全

⚠️ 局限与限制

局限点 说明
❌ 不支持 Surface Shader 完全不兼容
❌ 不支持非 SRP 管线(内置管线) Built-in 无法使用 SRP Batcher
⚠️ 不支持动态材质修改 不能在运行时用 material.SetFloat(),否则打断合批
⚠️ 不支持关键字变化材质 Shader Variant 不一致会被视作不同 Program
⚠️ 不支持用非 CBUFFER 定义属性 使用 uniform float _X 会被视为不兼容

🔥 与其他优化方式的关系

技术 可组合使用? 优化目标
✅ GPU Instancing ✔ 可以 减少 Draw Call
✅ SRP Batcher ✔ 可以 减少 SetPass Call
❌ Static Batching ✖️ 不建议配合使用 会破坏 SRP Batcher 性能优势
⚠️ MaterialPropertyBlock ✔ 仅用于 instanced 属性 不要修改非 instanced 参数,否则打断合批

✅ 最佳实践建议

实践建议 原因
使用 ShaderGraph 或 HLSL + CBUFFER 写法 自动兼容 SRP Batcher
Instanced 属性不要放进 CBUFFER 它属于实例缓冲,另处理
尽量减少 Shader Keyword 变体组合 Variant 不一致也会导致拆批
用 MaterialPropertyBlock 配合 instanced 属性 可实现 per-instance 参数变化而不打断合批
构建前启用 Variant Stripping(Shader Settings) 减少冗余变体,构建更快,加载更轻

✅ 总结

**SRP Batcher 是现代 Unity 渲染系统中最重要的 CPU 性能优化利器之一。**它不减少 Draw Call,但能显著减少 CPU 到 GPU 的材质状态开销,是大规模场景、高并发渲染中不可或缺的优化手段。


✅ 快速判断能否进入 SRP Batcher:

项目 能否进入 SRP Batcher
使用 URP / HDRP ✅ 是
Shader 用 CBUFFER 编写 ✅ 是
不使用动态 SetXXX() 改属性 ✅ 是
相同 Shader + Variant ✅ 是
材质值不同(颜色等) ✅ 可以