DrawCall 是 CPU 向 GPU 发送的一次渲染指令,包含了 GPU 绘制所需的全部信息:几何数据、纹理、Shader、Buffer 等。
每次调用 DrawMesh、DrawRenderer 等,就是一个 Draw Call。GPU 收到命令后开始渲染对应的几何体。
1 | CPU 准备渲染数据 |
关键点:DrawCall 本身消耗资源,但准备阶段(SetPass Call)通常比 DrawCall 本身更耗性能。
开启批处理后,Unity 可以用一次 SetPass Call 复用同一材质状态,然后提交多个 DrawCall。所以降低 SetPass Call 往往比降低 DrawCall 更重要。
DrawCall(绘制调用)
CPU准备数据并通过调用图形API接口命令GPU对指定物体进行渲染一次的操作称为一次DrawCall。
当收到一个DrawCall时,GPU会按照指令,根据渲染状态和输入的顶点信息,指定一个网格(Mesh)进行渲染,绘制材质。
GPU 渲染时,同一批次的对象必须使用相同的材质和纹理。一旦纹理不同,就必须切换渲染状态,触发新的 DrawCall。
1 | Image A(纹理1)→ DrawCall 1 |
为了CPU和GPU可以进行并行工作,需要一个命令缓冲区,由CPU向其中添加命令,然后由GPU从中读取命令,这样就实现了通过CPU准备数据,通知GPU进行渲染。
SetPass Call
在 Draw Call 之前,如果需要切换渲染状态(shader、材质属性、纹理等),CPU 就要先做一次 SetPass Call 来通知 GPU 切换 Pass。
SetPass Call 才是真正的性能瓶颈,因为它涉及 shader 编译、状态切换等开销。
例如场景里有 5 个物体:
1 | 物体A - 材质1 (Shader: Standard, 纹理: tex_a) |
渲染顺序:
1 | SetPass Call → 切换到材质1 |
结果:5 个 Draw Call,3 个 SetPass Call。
Pass 是什么
一个 Pass 就是 shader 里的一次完整渲染流程,包含一套完整的顶点着色器 + 片元着色器,以及对应的渲染状态(混合模式、深度测试、剔除等)。
一个材质可以有多个 Pass,每个 Pass 对同一个物体渲染一遍。
- 具体例子:描边效果
描边通常需要两个 Pass:第一个 Pass 画描边(把模型沿法线方向放大,只渲染背面),第二个 Pass 画正常颜色。
1 | Shader "Custom/Outline" |
渲染这一个物体时,GPU 会走两遍:
1 | SetPass Call → 激活 Pass 0 (OUTLINE),设置 Cull Front 状态 |
所以 1 个物体、1 个材质,产生了 2 个 SetPass Call + 2 个 Draw Call。
Batching
静态合批: 将相同材质并且始终不动的的Mesh合并成为一个大Mesh,然后由CPU合并为一个批次发送给GPU处理,从而减少DrawCall带来的消耗。
动态合批: 相同材质并且会动的物体Mesh合并成为一个大Mesh
SRP Batcher: 将多个网格合并成单个批次进行渲染,从而提高性能。与其他合批不同,SRP Batcher将未改变属性的Mesh缓存起来,从而减少消耗
GPU Instancing: 使用一个DrawCall渲染多个相同材质的网格对象(如场景中大量重复的物体如树木和草地等),从而减少CPU和GPU的开销
Static Batching
针对静态物体(勾选 Static)。在构建时,Unity 把所有使用相同材质的静态 mesh 合并成一个大 mesh,存到内存里。运行时一次 Draw Call 画完。
1 | 场景里100棵树(同材质,Static): |
代价是内存,合并后的大 mesh 常驻内存,物体也不能移动。
Dynamic Batching
与静态合批不同,动态合批是的物体是可以运动的,针对动态小物体。每帧 CPU 实时把符合条件的 mesh 合并,然后一次提交。
条件很苛刻:顶点数 < 900,不能使用lightmap,不能使用多通道的shader,不能是缩放比不同的物体。
Unity 的 Dynamic Batching(动态批处理)是自动触发的。只要启用了该功能且物体满足特定条件(如使用相同材质、顶点数较少),Unity 引擎就会在运行时自动合并 Draw Call,无需手动干预。
1 | 每帧: |
代价是 CPU 每帧都要做合并,物体多了反而更慢,现在基本被 GPU Instancing 取代。
SRP Batcher
Batches draw calls by grouping objects that use the same shader variant, reducing SetPass calls
Shader properties stored in GPU buffers instead of individual material constants
使用条件:
- 不支持内置渲染管线,支持通用(URP)/高清(HDRP)/自定义(SRP)渲染管线
- 不使用 MaterialPropertyBlocks
- Materials must use SRP-compatible shaders
在标准的渲染流程下,CPU需要收集所有场景物体的参数,场景中的材质越多CPU提交给GPU的数据就越多。
而在SRP中流程下GPU拥有数据管理的 “生命权” ,管理大量不同材质但Shader变动较小的的内容。
让数据在GPU中持久存在,从而减少消耗(SetPass Call)。
SRP Batcher vs. Dynamic Batching
Both can be used together in SRP, but SRP Batcher takes precedence when enabled. For optimal performance in modern Unity projects, prefer SRP Batcher with proper shader setup.
Both Dynamic Batching and SRP Batcher are triggered automatically in Unity when their conditions are met:
- Unity automatically detects and performs Dynamic Batching on compatible objects at runtime
- SRP batcher automatically batches during render loop when objects use compatible shader variants enabled in the render pipeline settings (Window → Rendering → Render Pipeline → Universal Render Pipeline → General → SRP Batcher)
GPU Instancing
针对大量相同 mesh + 相同材质的物体(但允许不同的属性,比如颜色、位置)。CPU 只提交一次 mesh 数据,附带一个”实例属性数组”,GPU 自己循环绘制 N 次。
在 Unity 中,需要在材质属性中勾选 “Enable GPU Instancing”。
1 | // shader 里声明每个实例可以有不同颜色 |
使用条件:
- 材质需要支持GPU Instancing,例如默认标准材质就有
- Tranform信息需要有所不同,(完全重合了渲染出来也没有意义)
- 未使用SRP Batcher,如有会优先使用SRP Batcher。(在URP渲染管线中是默认开启的)
- 粒子对像不能合批
- 使用MaterialPropertyBlocks的游戏不能合批
- Shader必须是使用compatible的
此时的CPU依然只提交1次Drawcall
1 | 100棵树(同mesh,同材质,不同位置/颜色): |

