游戏卡顿竟是因为DrawCall?到底什么是DrawCall?

在玩游戏时遇到的掉帧、操作延迟,大概率和一个叫Draw Call的指标有关。

它是游戏渲染的核心环节,也是性能优化绕不开的坎,哪怕是Unity、UE 引擎的资深开发者,也得在它身上下功夫。

什么是Draw Call?

Draw Call仅仅是一条指令。

是CPU向GPU发送的绘图指令,包含顶点、材质、纹理、着色器参数等,GPU接收后执行绘制。例如在Unity引擎中,每个使用独立材质的物体都会触发一次Draw Call,GPU接收到指令后执行顶点变换、光照计算、像素填充等操作,最终输出到显示设备。

就好比CPU是厨师长,下单(发Draw Call)告知GPU(厨师)做什么菜(绘图数据)、怎么炒(渲染状态),指令越多通信越耗时,越容易导致画面卡顿。

其核心流程包含三个阶段:

1、数据准备:CPU将这些数据从内存(RAM)传输至GPU显存(VRAM)

2、状态配置:设置渲染管线状态(如着色器、混合模式、深度测试)和全局参数(如光照、投影矩阵)

3、指令提交:调用glDrawElements或DrawIndexedPrimitive等API触发GPU渲染

关键特性:

命令缓冲区机制:CPU与GPU通过Command Buffer实现异步通信,CPU写入指令,GPU按队列顺序执行

渲染状态切换成本:每次材质、纹理或着色器变更需重新配置全局状态,产生额外开销

你在游戏里看到的每棵树、每个角色、每道特效,背后都需要CPU发一次(或多次)命令,告诉 GPU “该画这个东西了”。比如屏幕上有100棵树,默认情况下可能就有100个Draw Call,GPU收到命令后才会执行渲染操作。

这里要明确一个关键点:Draw Call就是一个命令,它的发起方是CPU,接收方是GPU。这个命令仅仅会指向一个需要被渲染的图元(primitives)列表,而不会再包含任何材质信息。

而Draw Call中造成性能问题的元凶其实不是的GPU真正“拖后腿”其实的是CPU

Draw Call多了会影响帧率?

举个栗子:先创建10000个小文件,每个文件的大小为1KB,然后把它们从一个文件夹复制到另一个文件夹。你会发现,尽管这些文件的空间总和不超过10MB ,但要花费很长时间。


然后再创建一个单独的文件,它的大小是10MB,然后也把它从一个文件夹复制到另一个文件夹。而这次复制的时间却少很多。

这是为什么呢?明明它们所包含的内容大小是一样的。原因在于,每一个复制动作需要很多额外的操作,例如分配内存、创建各种元数据等。

如你所见,这些操作将造成很多额外的性能开销,如果我们复制了很多小文件,那么这个开销将会很大。

渲染的过程虽然和上面的例子有很大不同,但也是类似的道理。在每次调用Draw Call之前, CPU需要向GPU发送很多内容,包括数据、状态和命令等。

在这一阶段, CPU需要完成很多工作,一旦CPU完成了这些准备工作, GPU就可以开始本次的渲染。

影像CPU还是GPU?

如果Draw Call的数量太多,CPU就会把大量时间花费在提交Draw Call上,造成CPU的过载,CPU会首先成为瓶颈。

其次是GPU,GPU的吞吐量其实远远大于CPU,但DrawCall过多也会在一定程度上影响GPU,这是由于数据没有组织好,导致GPU频繁切换硬件状态,频繁请求显存数据,频繁出现Cache Miss情况造成的。

所以对于开发者来说,Draw Call作为游戏性能的关键指标,优化的核心从来不是让GPU少画,而是让CPU少发命令

比如批处理的方法,很显然就是在CPU中把很多小的DrawCall合并成一个大的Draw Call,再发送给GPU。

而批处理也分静态和动态,由于需要在CPU的内存中合并,而合并的过程是需要消耗时间的。因此,批处理技术更加适合于那些静态的物体,例如不会移动的大地、石头等,对于这些静态物体只需要合并一次即可。


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

🙏感谢阅读、点赞和充电

更多游戏资讯请关注:电玩帮游戏资讯专区

电玩帮图文攻略 www.vgover.com