SRP Batcher:让CPU少为绘制“重复准备”
SRP Batcher 主要优化的是CPU 为连续绘制准备和绑定 Shader 数据的开销。它通常不会减少 Draw Call 数量也不会让 GPU 少画几个三角形。先记住这组对比GPU Instancing 多个实例尽可能放进一次绘制。 SRP Batcher 绘制次数可以不变 但让 CPU 更便宜地组织这些绘制。下面拆开讲。一、一个 Draw Call成本不只是“调用 Draw”假设场景里有三块石头石头 A红色材质 石头 B绿色材质 石头 C蓝色材质它们使用同一个 Shader Variant只是材质参数不同。CPU 在提交绘制之前通常需要准备使用哪个 Shader 使用哪个 Shader Variant 绑定哪些纹理 材质颜色、粗糙度等参数是什么 物体的变换矩阵是什么 使用哪个网格然后才是Draw可以用一个简化公式表示[T_{\text{CPU渲染}}T_{\text{剔除与排序}}T_{\text{状态和数据准备}}T_{\text{绘制命令组织}}]SRP Batcher 重点优化中间的“状态和数据准备”以及相关的绘制提交路径。它不是把全部 CPU 渲染成本都消除。二、传统路径的问题很多时间花在“准备画”而不是“画”用概念流程表示石头 A 整理材质数据 → 设置相关状态 → 绘制 石头 B 整理材质数据 → 设置相关状态 → 绘制 石头 C 整理材质数据 → 设置相关状态 → 绘制底层本来就可能有各种缓存并非每次都完全从零处理。但随着物体和材质增多CPU 仍可能花费大量时间在收集、整理 Shader 参数更新和绑定常量数据处理不同材质的设置重复经过较重的状态准备路径。尤其是大量物体使用不同材质但这些材质实际使用同一个 Shader Variant。SRP Batcher 正是针对这类情况提供高效路径。三、核心机制一让材质数据持久保存在 GPU 缓冲中考虑材质参数CBUFFER_START(UnityPerMaterial) float4 _BaseColor; float _Metallic; float _Smoothness; CBUFFER_END这些参数属于材质石头 A 材质 红色、金属度 0、光滑度 0.2 石头 B 材质 绿色、金属度 0、光滑度 0.4SRP Batcher 的一个关键思路是材质数据上传后在 GPU 侧持久保存材质未变化时避免反复重新准备、上传同一份数据。概念上GPU 材质数据区 材质 A → 一份参数数据 材质 B → 一份参数数据 材质 C → 一份参数数据绘制不同物体时使用对应的数据而不是每次都重新打包同样的材质参数。注意两点材质参数改变后相关数据仍然需要更新。“数据持久保存”不意味着不再绑定资源或完全没有状态切换。省掉的是大量重复工作不是让设置成本变成零。四、核心机制二高效处理每个物体自己的数据同一材质可以被多个物体使用但每个物体的位置不同石头 A位置 (0, 0, 0) 石头 B位置 (5, 0, 0) 石头 C位置 (10, 0, 0)因此不能把所有数据都当成材质数据。常见分类是数据类别例子常见常量缓冲约定每材质数据颜色、金属度、光滑度UnityPerMaterial每物体数据变换矩阵、部分光照相关数据UnityPerDraw每帧/相机等数据相机和环境相关参数由管线组织SRP Batcher 同时提供了更高效的每物体数据组织和绑定路径。但物体动了矩阵仍然要更新物体要画绘制命令仍然存在。它不是跳过必要工作而是让这些工作按运行时易于批量处理的数据布局进行。五、为什么名字叫 Batcher却不减少 Draw Call因为这里的 Batch不能直接理解成“一个绘制命令”。例如一个 SRP Batch ├── Draw 石头 A ├── Draw 石头 B ├── Draw 石头 C └── Draw 石头 D里面仍然可以有多个 Draw Call。它表示的是一段可以通过 SRP Batcher 高效连续处理的绘制序列。概念对比普通路径 较重的准备 → Draw 较重的准备 → Draw 较重的准备 → DrawSRP Batcher 路径 复用兼容的准备状态 ├── 较轻量的数据绑定 → Draw ├── 较轻量的数据绑定 → Draw └── 较轻量的数据绑定 → Draw所以看到开启前1000 Draw Calls 开启后1000 Draw Calls不能说明 SRP Batcher 没生效。要看 CPU 渲染相关耗时而不只是绘制次数。六、关键是 Shader Variant不是“材质必须相同”这是最容易混淆的地方。情况一材质不同但 Variant 相同材质 A红色 材质 B绿色 材质 C蓝色 全部使用 同一个 Shader 的同一个 Variant这是 SRP Batcher 很适合优化的情况。材质可以不同网格也可以不同。情况二Shader 文件相同但 Variant 不同例如材质 A开启 _NORMALMAP 材质 B关闭 _NORMALMAP 材质 C开启 _ALPHATEST_ON虽然都来自同一个 Shader但关键词组合不同可能对应不同的 Shader Variant。这会使连续绘制需要切换程序或相关状态影响批处理连续性。因此相同 Shader 文件 ≠ 相同 Shader Variant不过也不能认为“Variant 相同就一定进入同一个 SRP Batch”。实际分组还受 Pass、渲染顺序及其他条件影响。优化方向是减少不必要的 Variant 和状态切换而不是为了凑批次破坏正确的渲染顺序。七、Shader 怎样才算兼容典型要求包括1. 材质标量和向量等常量放入UnityPerMaterialCBUFFER_START(UnityPerMaterial) float4 _BaseColor; float4 _BaseMap_ST; float _Smoothness; CBUFFER_END纹理和采样器不是这样塞进常量缓冲TEXTURE2D(_BaseMap); SAMPLER(sampler_BaseMap);2. 引擎要求的每物体常量遵循UnityPerDraw布局使用 URP 提供的 Shader 库时相关声明通常由库处理不要随意重复定义。3. 多个 Pass 保持兼容的数据布局例如不能因为不同 Pass 或关键词随意改变同一材质常量缓冲的布局。最稳妥的方式是共享相应声明并参考当前 URP/HDRP 版本的官方 Shader。4. 注意MaterialPropertyBlock在常见的 Unity SRP Batcher 路径中使用MaterialPropertyBlock会使对应 Renderer 无法走 SRP Batcher 兼容路径。因此“用 MPB 避免创建材质实例”与“维持 SRP Batcher”之间可能需要权衡。具体应以项目 Unity 版本和实际渲染路径验证。八、它与 GPU Instancing 的区别对比SRP Batcher传统 GPU Instancing主要目的降低 CPU 状态和数据准备成本合并多个实例的绘制是否通常减少 Draw Call不一定通常不是核心收益是网格是否必须相同不要求同一实例化绘制通常要求相同网格材质是否必须相同不要求但需满足兼容条件通常共享材质和绘制状态差异数据如何处理材质和每物体数据路径实例数据典型场景很多不同物体和材质共用少量 Variant大量重复树木、石头、草等同一个物体不能想当然地同时吃到两者全部收益。Unity 会根据具体渲染路径和兼容条件选择处理方式传统 Renderer 路径与较新的 GPU 驱动渲染路径也不能简单混为一谈。九、什么时候效果明显什么时候几乎没用更容易获益物体数量多 材质数量多 Shader Variant 相对少 CPU 渲染准备成为瓶颈例如一个城市有大量不同建筑和材质但材质都基于少数几种 Shader Variant。提升可能不明显Draw Call 本来就少 大量时间消耗在其他 CPU 系统 GPU 已经成为主要瓶颈 大量绘制不兼容 SRP Batcher Variant 和状态频繁切换例如满屏透明粒子导致 GPU Overdraw 极高CPU 提交更快了 但 GPU 仍然要反复计算和混合大量像素帧率可能变化不大。SRP Batcher 不直接减少阴影采样、片元计算、透明叠加或纹理带宽。十、怎么确认它真的有用建议验证三个问题1. Shader 是否兼容检查 Shader Inspector 中的 SRP Batcher 兼容信息。具体界面随版本不同。2. 实际绘制是否走了对应路径使用 Frame Debugger 查看SRP Batch 分组使用的 Shader 和 Variant绘制之间为什么发生分组变化。不要只看项目里“已开启”这个选项。3. CPU 时间是否下降在相同场景、相同设置下对比开关主线程相关渲染耗时渲染线程耗时GPU 耗时最终帧时间。最好在目标设备的 Player 中测试并排除 Shader 首次使用、资源加载等干扰。最后一句话SRP Batcher 不是“让 GPU 少画”而是“让 CPU 少为每次绘制重复准备”。最典型的结果是物体数量不变 Draw Call 数量基本不变 画面不变 GPU 工作量大致不变 但 CPU 渲染提交更便宜了。

相关新闻

一文区分 装饰器模式 vs 代理模式

一文区分 装饰器模式 vs 代理模式

快速判断想控制能不能调用(权限、延迟创建)→ 代理想给对象叠加额外功能,可以自由多层套 → 装饰器核心区分:代理模式:控制访问,代理对象代替原始对象干活,可以做权限、日志、延迟加载&#xff…

2026/10/9 2:56:49 阅读更多 →
【ICRA 2026】VeriGraph:以场景图为可验证中间表示的机器人任务规划|从具身大模型规划验证视角

【ICRA 2026】VeriGraph:以场景图为可验证中间表示的机器人任务规划|从具身大模型规划验证视角

摘要 本文解读 ICRA 2026 论文《VeriGraph: Scene Graphs for Execution Verifiable Robot Planning》。该论文提出以场景图作为可执行验证的中间表示,通过融合场景图结构化表示、图编辑式动作建模与迭代式约束校验,让机器人在真正动手之前先证明计划做…

2026/10/9 2:56:49 阅读更多 →
《创业之路》-1024-细读商业经典 - AI 是一个普惠技术,其技术本身带来的原始创新能力,正在颠覆美国在原始创新上的优势。

《创业之路》-1024-细读商业经典 - AI 是一个普惠技术,其技术本身带来的原始创新能力,正在颠覆美国在原始创新上的优势。

AI 普惠时代:正在重构而非颠覆的全球创新格局这个判断切中了 AI 作为通用目的技术(GPT)最核心的革命意义:它不是一项普通的新产品,而是一种全新的创新生产工具 —— 它直接降低了 “原始创新” 的门槛,稀释…

2026/10/9 2:56:49 阅读更多 →

最新新闻

双指针算法全攻略:对撞、快慢、滑动窗口三大模板与实战总结

双指针算法全攻略:对撞、快慢、滑动窗口三大模板与实战总结

刷题刷到一定量,很多人会慢慢总结出一条规律:有一类题的解法特别“固定”——有序数组里找两个数凑目标值、链表中判断有没有环、字符串里找不重复的最长子串,题面长得完全不一样,翻开题解一看,底层全是同一个思路&…

2026/10/9 3:32:13 阅读更多 →
医疗NLP实战:词典构建与最大匹配实体标注

医疗NLP实战:词典构建与最大匹配实体标注

简介:一套基于Python与Jupyter构建的医疗实体识别模型资源,面向疾病、症状、身体部位三类实体,完整呈现词典构造、语料标注、模型训练与结果评估的工程化流程。压缩包共147个文件,约581MB,具体包含18个txt词典/文本、1…

2026/10/9 3:32:13 阅读更多 →
Git远程分支覆盖本地分支:reset、clean实操与急救指南

Git远程分支覆盖本地分支:reset、clean实操与急救指南

1. 什么时候需要“用远程分支覆盖本地分支”先聊个真实的场景。我在维护一个项目时,远程仓库里develop分支已经被同事 rebase 重新整理过,提交历史完全换了样子。我本地还停在老版本上,这时候直接git pull会提示分叉严重,甚至直接…

2026/10/9 3:32:13 阅读更多 →
Cache模拟器实战:从映射原理到命中率计算的完整工程解析

Cache模拟器实战:从映射原理到命中率计算的完整工程解析

简介:一份面向计算机组成原理与操作系统学习者的缓存模拟器源码,在Visual Studio 2010环境下编写,通过读取地址流文件模拟处理器访存行为,可设置缓存容量、块大小,并支持直接映射、组关联映射、全关联映射三种策略&…

2026/10/9 3:32:13 阅读更多 →
Servlet配置实战:web.xml与@WebServlet注解全面解析

Servlet配置实战:web.xml与@WebServlet注解全面解析

Servlet这个词,放在今天动辄微服务、云原生的大环境下,多少有点“老古董”的感觉。但你只要还在写Java后端,不管用Spring Boot还是Spring MVC,请求真正进来之后,最终处理的还是Servlet容器那一层。很多新人会直接跳过S…

2026/10/9 3:32:13 阅读更多 →
Claude Code与桌面版安装教程:环境配置、VS Code插件及MCP部署

Claude Code与桌面版安装教程:环境配置、VS Code插件及MCP部署

最近一直被同一个问题刷屏:“Claude到底怎么装?”尤其是Claude Code这三个月火起来之后,各大群里问安装的比问用法的还多。我前前后后帮朋友远程装过几十次,也踩了不少坑——什么安装到一半卡死、装完打开白屏、输入命令提示找不到…

2026/10/9 3:31:13 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 10:10:36 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 13:34:55 阅读更多 →