23

游戏性能优化杂谈(五)

 3 years ago
source link: https://zhuanlan.zhihu.com/p/268617799
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

在当代游戏引擎当中,CPU负责生成GPU命令队列,并提交给GPU执行。因为这个命令队列是生成在内存空间当中然后提交给GPU的,所以无论对于CPU还是GPU来说,这其实也是一种IO操作。

特别是,在PC等通用环境下,为了提高系统的鲁棒性和兼容性,通常这部分被设计为一种拷贝操作:由用户应用所构建的GPU命令队列,往往并不会直接被提交,而是会被显卡驱动复制出一份之后,将复制出的这份提交给GPU执行。这样做的好处是CPU端在提交之后可以立即重用这块buffer开始记录新的绘图命令,不用去担心GPU何时开始使用它,何时结束。也就是使用起来方便,而且也给了驱动对命令队列进行一些调整的空间,但是缺点也很明显,多了一次内存拷贝的开销。

而且,当代的商用游戏引擎多为跨平台引擎。为了能够柔软对应不同平台的不同图形API,这些引擎往往在生成平台相关的绘图指令之前,首先会生成一个平台无关的绘图指令序列。这有些类似基于LLVM的编译器在编译的时候,总是先将源代码翻译成为LL中间语言字节码,然后再将其翻译成为平台本地二进制代码。

这样做的好处当然是可以让引擎脱离对于特定平台的依赖,并且,可以在中间语言级别进行很多优化,而这种优化对于各个平台都有效。然而缺点也一样明显,由于中间层的引入,需要消耗额外的CPU资源,带来更大的延迟。

在这种情况下,DrawCall的数量,往往对于CPU端的性能有十分显著的影响。这也是为啥我们在一些行业分享会上,经常会听到“要削减DrawCall”这种说法。本质上,削减DrawCall就是削减CPU生成的GPU命令数量,主要减少的就是CPU与GPU之间的IO时间。

而主机上由于软硬件环境十分固定,往往采用的是直接将CPU生成的绘图命令提交给GPU读取的方法,图形驱动基本上只是搬砖,什么都不做。而面向特定主机平台定制的一些in hourse引擎也直接输出平台特定的绘图命令,而不是引入一个中间层(用编译器来类比的话,更加类似gcc)。在这种情况下,其实主机对于DrawCall并没有那么敏感,过度优化DrawCall反而可能导致模型过大裁剪效率变低,或者CPU端动态合并DrawCall带来额外开销的问题。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK