[Unity3D] [转] 什么是DrawCall和Batch?

什么是Draw Call?

开发游戏时,一定被时时提醒要减少Draw Call,当然UNITY也不例外,打开Game Window里的Stats,可以看到Draw Call 与Batched 的数字。但到底什么是Draw Call?影响的效能是来自CPU?还是GPU?让UnityIN 一次告诉你。

首先,让我们定义何为“Draw Call”:

一个Draw Call,等于呼叫一次 DrawIndexedPrimitive (DX) or glDrawElements (OGL),等于一个Batch

摸过DirectX或OpenGL的人来说,对 DrawIndexedPrimitive 与 glDrawElements 这API一定不陌生。当我们准备好资料(通常为三角面的顶点资讯)要GPU划出来时,一定得呼叫这个函式。换句话说,如果在画面上有一张“木”椅子、一张“铁”桌子,那理论上就会有两个Draw Call。

有看到特别点出“木” 与“铁” 吗?这代表两物件是使用不同材质球或者不同的Shader。在DirectX 或OpenGL 里,对不同物件指定不同贴图或不同Shader 的描述,就会需要呼叫两次Draw Call。Procedure code如下:

1
2
3
SetShader( “Diffuse" ); 
SetTexture( “铁" );
DrawPrimitive( DeskVertexBuffer );

1
2
3
SetShader( “VertexLight" ); 
SetTexture( “木" );
DrawPrimitive( ChairVertexBuffer );

每次对Sahder的更动或者贴图的更动,基本上就是对 Rendering Pipeline 的设定做修改,所以需要不同的Draw Call来完成物件的绘制。现在了解为什么UNITY官方文件里,老是要你尽量使用同样材质球,以减少Draw Call数量了吧!


什么是Batch?

在来谈到Batch,其实也是Draw Call 的另一种称呼。你可以想成每一次的Draw Call 会产生一个Batch,而Batch 里装的是物件顶点资料,Batch 由CPU 透过“驱动程式” 将顶点资料送往GPU,GPU接手后将物件画在画面上。由此可知,越多Draw Call,CPU 就越忙碌。这下更清楚知道Draw Call 数量所影响的是CPU 效能而非GPU。

NVIDIA 在GDC 曾提出,25K batchs/sec 会吃满1GHz 的CPU,100% 的使用率。所以他们推出了一条公式,来预估游戏中大概可以Run 多少个Batch:

举个例子:如果你的目标是游戏跑30FPS、使用2GHz的CPU、20%的工作量拨给Draw Call来使用,那你每秒可以有多少Draw Call呢?

333 Batchs/Frame = 25K 2 (0.2/30)

那既然Batch 是个箱子,里头装着物件的顶点资料,再依据我们上面的描述,那表示同样材质或Shader 的物件,可以合并成一个Batch 送往GPU,这样就是最省事的方法搂?BINGO!就是这样没错!

UNITY在 Player Setting 里的两个功能选项Static Batching与Dynamic Batching。功能描述如下:
+ Static Batching 是将标明为Static 的静态物件,如果在使用相同材质球的条件下,UNITY 会自动帮你把这两个物件合并成一个Batch,送往GPU 来处理。这功能对效能上非常的有帮助,所以是需要付费才有的。
+ Dynamic Batching 是在物件小于300面的条件下(不论物件是否为静态或动态),在使用相同材质球下,UNITY就会自动帮你合并成一个Batch 送往GPU 来处理。


From Here