Unity3D之DrawCalls、Batches和SetPassCalls的关系

接触过项目优化的人相信对这三个词组不陌生,优化很大部分时间可能最终就是在优化这三个东西,让它们保持在一个相对稳定合理的数值,太高肯定是不好。这三个数值也能直接在Unity上显示出来,在Unity界面Game窗口右上角有一个“Status”按钮,点击打开Statistics窗口,这个渲染统计窗口(或渲染数据统计窗口)展示了图像渲染、网络状况等多种统计信息。在Unity4.x版本,DrawCalls数据就可以在这里看到,但并没有显示SetPassCalls的数据;在Unity5.x版本之后,DrawCalls数据不再显示在这里,取而代之的是SetPassCalls和Batches的数据,SetPassCalls是Unity5.x才出现的,不过DrawCalls的数据依旧可以在Profiler窗口(Window->Profiler)的Rendering或者Frame Debugger(Window->Frame Debugger)中看到,而且在Frame Debugger中还能看到每一帧的渲染数据。

都知道DrawCalls太高会影响游戏性能,但是究竟DrawCalls是什么,DrawCalls、Batches和SetPassCalls这三者有什么关系,很多人估计很难说清楚,至今Unity官方也没有给出详细的文档。有些地方为了容易理解,简单的把SetPassCalls等同于DrawCalls了,但是这两者却不是一个东西,虽然它们之间确实是有相互影响。

DrawCall:CPU每次调用图像编程接口 glDrawElements(OpenGl中的图元渲染函数)或者 DrawIndexedPrimitive(DirectX中的顶点绘制方法)命令GPU渲染的操作称为一次Draw Call。Draw Call就是一次渲染命令的调用,它指向一个需要被渲染的图元(primitive)列表,不包含任何材质信息,glDrawElements 或者 DrawIndexedPrimitive 函数的作用是将CPU准备好的顶点数据渲染出来。

Batch:把数据加载到显存,设置渲染状态,CPU调用GPU渲染的过程称之为一个Batch。这其实就是渲染流程的运用阶段,最终输出一个渲染图元(点、线、面等),再传递给GPU进行几何阶段和光栅化阶段的渲染显示。一个Batch必然会触发一次或多次DrawCall,且包含了该对象的所有的网格和顶点数据以及材质信息。把数据加载到显存是指把渲染所需的数据从硬盘加载到内存(RAM),再将网格和纹理等加载到显卡(VRAM),这一步比较耗时。设置渲染状态就是设置场景中的网格的顶点(Vertex)/片元(Fragment)着色器,光源属性,材质等。Unity提供的动态合批(Dynamic Batching )合并的就是这一过程,将渲染状态相同的对象合并成一个Batch,减少DrawCall。

SetPassCall:Shader脚本中一个Pass语义块就是一个完整的渲染流程,一个着色器可以包含多个Pass语义块,每当GPU运行一个Pass之前,就会产生一个SetPassCall,所以可以理解为一次完整的渲染流程次数。

由此可见,一个Batch包含一个或多个DrawCall,都是产生是在CPU阶段,而目前普遍渲染的瓶颈恰恰就是CPU,GPU的处理速度比CPU快多了,Draw Call太高,CPU会把大量时间花费在处理Draw Call调用上。如果Batch太大,CPU需要频繁的从硬盘加载数据,切换渲染状态,这个消耗要比DrawCall大,所以后面Unity才逐渐弱化了DrawCall的显示。

Unity3D之DrawCalls、Batches和SetPassCalls的关系_第1张图片

Unity3D之DrawCalls、Batches和SetPassCalls的关系_第2张图片

再提一下,优化的时候还要关注下Statistics窗口上的三角形数(Tris)顶点数(Verts),这两个数据也是会影响到性能,比如单个物体的顶点数最好不要超过900,不然会影响到Unity的动态合批。Unity的Statistics窗口上的三角形数(Tris)和顶点数(Verts)并不仅仅是视锥中的梯形内的三角形数和顶点数,而是Camera中 field of view所有取值下的三角形数和顶点数。也就是说,即使当前Game视图中看不到这个 cube,只有 field of view在1-179 范围内都看不到这个cube,stats面板才不会统计,GPU才不会渲染,否则都会渲染,而且Unity不会把模型拆分,这个模型哪怕只有1个顶点需要渲染,Unity也会把整个模型都渲出来。

参考:

Draw Calls vs Batches optimization? [Unity 5]

Render Hell 2.0

How to see why your draw calls are not batched in 5.6

你可能感兴趣的:(游戏开发)