Draw Call

转自:http://blog.youkuaiyun.com/molti/article/details/42495993


开发游戏时,一定被时时提醒要减少 Draw Call,当然Unity也不例外。打开Game Window里的 Stats,可以看到 Draw Call 与 Batched 的数字。

但到底什么是 Draw Call?影响的效能是来自 CPU?还是 GPU?

 

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

“一个 Draw Call,等于调用一次 DrawIndexedPrimitive (DirectX) or glDrawElements (OpenGL),等于一个 Batch”。

摸过 DirectX 或 OpenGL 的人来说,对 DrawIndexedPrimitive 与 glDrawElements 这 2个API 一定不陌生。 

当我们准备好资料 (通常为三角面的顶点信息), 要 GPU 画出来时,一定得调用这个函数。换句话说,如果在画面上有一张 “木" 椅子、一张 “铁" 桌子,那理论上就会有两个 Draw Call。有看到特别点出 “木" 与 “铁"吗?这代表两物件是使用不同材质球或者不同的 Shader。在 DirectX 或 OpenGL 里,对不同物件指定不同贴图或不同 Shader 的描述,就会需要调用两次Draw Call。 


Procedure code如下: 

SetShader("Diffuse") ;

SetTexture("铁");

DrawPrimitive(DeskVertexBuffer) ; 

SetShader("Diffuse") ;

SetTexture("木") ;

DrawPrimitive (ChairVertexBuffer) ;

 

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

再来谈到 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:


浅谈Draw Call和Batch的区别

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

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

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

Unity在 Player Setting 里的两个功能选项 Static Batching 与 Dynamic Batching。功能描述如下:

  1. Static Batching 是将标明为 Static 的静态物件,如果在使用相同材质球的条件下,Unity 会自动帮你把这两个物件合并成一个 Batch,送往 GPU 来处理。这功能对效能上非常的有帮助,所以是需要付费版(Pro专业版)才有的。
  2. Dynamic Batching 是在物件小于300面的条件下(不论物件是否为静态或动态),在使用相同材质球下,Unity就会自动帮你合合并成一个 Batch 送往 GPU 来处理。

根据上述的说明,相信大家对降低 Draw Call 这件事有更深一层的认识吧!还有什么不清楚或者错误的地方,还请大家能够留言回复。

以上转自:《浅谈Draw Call和Batch的区别


注:

1 原文:“一个 Draw Call,等于调用一次DrawIndexedPrimitive (DirectX) or glDrawElements(OpenGL),等于一个 Batch”。

简单的说:CPU调用一次GPU,叫做一次Draw Call 。

一个Batch,是对Draw Call的一次批量处理,或者是对Draw Call的一次合并处理。参考注2。


2 原文:每次对 Shader 的更动或者贴图的更动,基本上就是对 Rendering Pipeline 的设定做修改,所以需要不同的 Draw Call 来完成物件的绘制。

也就是说,当材质和贴图相同的时候,处理代码可以变成:

SetShader ("Diffuse") ;

SetTexture(“木和铁采用同一个贴图”) ;

DrawPrimitive("木和铁两者的顶点buffer") ;


如果可以变成这段处理流程,那么,因为只调用了一次DrawPrimitive(),所以Draw Call由2次变为了1次。

但是木和铁本身是不同的贴图和顶点,怎么能够一起处理呢?

答案是合并。通过合并纹理(Texture),和合并网格(Mesh)。将木和铁的贴图放在一张做成图集,然后开启Unity的批量处理,Unity3D就会自动合并网格。

或者借助一款强大的工具可以实现纹理和网格的合并,从而减少DrawCall:Mesh Baker工具。

合并后,注1中的Batch数就会跟着增加。

或许有人有疑惑:即便通过合并可以减少Draw Call次数,但是CPU传送给GPU的数据变多,GPU需要绘制的数据也变多,这些不会增加处理时间吗?

这个目前我还没有理论上的证明,但是根据网上的一些资料,GPU绘制一个1000面的物体,和绘制1000个1个面的物体,处理上是没有区别的。

FairyGUI 是一个基于 Unity 的 UI 框架,广泛用于游戏开发中。在实际开发过程中,Draw Call 的优化是提升 UI 性能的关键之一。Draw Call 是指 GPU 渲染每一帧时对绘制命令的调用,频繁的 Draw Call 或不必要的状态切换会导致性能下降。 以下是一些针对 FairyGUI 优化 Draw Call 的方法: ### 减少 Atlas 图集切换 FairyGUI 使用图集(Atlas)来合并纹理,以减少 Draw Call。如果多个 UI 元素使用相同的图集,它们可以在一次 Draw Call 中完成渲染。因此,尽量将常用的 UI 元素放入同一个图集中,以减少图集切换的次数 [^1]。 ### 合并相同材质的 UI 元素 FairyGUI 支持通过材质共享来合并多个 UI 元素。如果多个对象使用相同的材质,它们可以被合并到一个 Draw Call 中。例如,多个文本标签使用相同的字体和颜色时,可以尝试将它们设置为相同的材质属性。 ### 使用 Batch Mode FairyGUI 内部支持 UI 元素的批处理(Batching),通过将多个 UI 元素合并到一个网格中,从而减少 Draw Call 的数量。可以通过设置 `GComponent` 的 `batching` 属性来启用批处理功能。 ### 避免频繁的状态切换 状态切换包括材质切换、混合模式切换等。FairyGUI 在渲染时会尽量减少这些切换,但开发过程中应尽量避免频繁更改材质属性或渲染状态。例如,避免在运行时频繁修改 UI 元素的颜色、透明度等属性。 ### 使用 Sprite 的共享模式 FairyGUI 提供了 Sprite 的共享模式,可以将多个 Sprite 合并为一个绘制单元。通过 `GSprite` 的 `useSharedMaterial` 属性,可以启用共享材质模式,从而减少 Draw Call 和材质切换。 ### 优化 UI 层级结构 减少不必要的嵌套层级,可以降低渲染时的复杂度。FairyGUI 的层级结构会影响渲染顺序和批处理效率。尽量将 UI 元素扁平化管理,避免过多的嵌套。 ### 启用 GPU Instancing 如果 FairyGUI 的 UI 元素支持 GPU Instancing,可以启用该功能以进一步优化 Draw Call。GPU Instancing 允许在同一 Draw Call 中绘制多个相同的对象,适用于大量重复的 UI 元素。 ### 示例代码:启用批处理 ```csharp // 启用 GComponent 的批处理功能 GComponent component = ...; component.batching = true; ``` ### 示例代码:共享材质 ```csharp // 设置共享材质 GObject obj = ...; obj.material = sharedMaterial; ``` 通过以上方法,可以有效优化 FairyGUI 的 Draw Call 性能,从而提升整体渲染效率。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值