Contents

Draw Call

什么是Draw Call?

Draw Call本身的含义很简单,就是CPU调用图像编程接口

OpenGL中的glDrawElements命令 或者 DirectX中的DrawIndexedPrimitive命令

以命令GPU进行渲染的操作。


CPU和GPU是如何并行工作的?

如果没有流水线化,CPU需要等GPU完成上一个渲染任务才能再次发送渲染命令,这种渲染方法效率比较低。

因此我们需要让CPU和GPU可以并行工作,解决方法就是命令缓冲区(Command Buffer)

命令缓冲区包含了一个命令队列,由CPU向其添加命令,由GPU读取命令。

添加和读取的过程相互独立,

当CPU需要渲染一些对象时,它可以向命令缓冲区中添加命令

当GPU完成上一次渲染任务后,他就可以从命令队列中再取出一个命令执行

命令缓冲区中的命令有很多种,Draw Call是其中的一种,其他命令还有改变渲染状态,着色器,使用不同的纹理等。

/usr/uploads/2025/05/1082672713.png


为什么Draw Call多了会影响帧率?

一个常见的误区是,DrawCall中造成问题的元凶是GPU,认为GPU上的状态切换是耗时的,

其实不是的,真正“拖后腿”的是CPU

我们来做个实验:

创建10000个小文件,每个文件大小为1KB,然后从一个文件夹复制到另一个文件夹。

会发现尽管文件大小总和不超过10MB,但需要花费很长时间。

现在创建单独的文件 他的大小是10MB,然后从一个文件夹复制到另一个文件夹。

但这次事件却少很多。

因为每一个复制动作都需要很多额外操作,例如分配内存,创建元数据等。

这些操作会造成额外的开销,如果复制了很多小文件 这些开销会很大。

渲染的过程也是类似的

CPU在每次调用Draw Call前,都需要向GPU发送很多内容,包括数据、状态、命令等。

这一阶段 CPU需要完成很多工作 例如检查渲染状态。

一旦CPU完成了这些准备工作 GPU就可以开始本次渲染。

GPU的渲染能力是很强的 渲染200个还是2000个三角网络 通常没什么区别。

因此渲染速度往往快于提交命令(DrawCall)的速度。

如果DrawCall数量太多,CPU就会把大量时间花费在提交Draw Call上。

/usr/uploads/2025/05/1926298104.png


如何减少Draw Call?

可以使用批处理的方式,把很多小的Draw Call合并成一个大的DrawCall。

需要注意的是,由于我们需要在CPU的内存中合并网络,而合并的过程是需要消耗时间的。

批处理技术更加适合一些静态的物体,大地石头等。

当然我们也可以对动态的物体进行批处理,但是由于这些物体是不断运动的,因此每一帧都需要重新进行合并再发给GPU,这对时间和空间都会造成一些影响。同时Unity对动态合批也有一定的限制。

开发游戏的过程中应避免使用大量很小的网络,当不可避免的需要使用时 考虑是否可以合并。

同时要避免使用过多的材质,尽量在不同的网络之间 共用一个材质。


来源作者:《UnityShader入门精要》冯乐乐