OpenGL ES 3.0 数据可视化 3:多次绘制调用(glDraw*)的性能问题

上一篇文档OpenGL ES 3.0 数据可视化 2:多重采样绘制光滑圆点实现了画多个圆点的功能,忽略其图像质量,还存在一些影响性能的代码。
本文档先讨论当前代码存在的性能问题,同时简要介绍OpenGL ES命令的工作方式。

OpenGL ES 3.0 数据可视化 2:多重采样绘制光滑圆点通过循环调用glDrawArrays绘制多个圆点,这种实现容易带来较大的CPU开销,因为OpenGL (ES)相关的函数是运行期间由CPU转成GPU命令并发送到GPU命令缓冲区中,在GPU命令缓冲区装满或调用glFlush之后,GPU异步读取命令并执行,如下示意图所示。

OpenGL ES 3.0 数据可视化 3:多次绘制调用(glDraw*)的性能问题_第1张图片
glDrawArrays从GL函数转成GPU命令

同时,GPU也维护了一个GPU命令缓冲区,CPU在操作系统内核维护的GPU命令缓冲区在装满或调用glFlush后,内核端的缓冲区及其相关数据被拷贝到GPU端缓冲区,此时,GPU再从该缓冲区中读取命令并执行,如下示意图所示。

OpenGL ES 3.0 数据可视化 3:多次绘制调用(glDraw*)的性能问题_第2张图片
GPU命令缓冲区

部分GL函数的翻译消耗较多资源,如glDrawArrays,虽然开发者只调用了glDrawArrays,它还有自己的调用栈,如下所示。因此,开发者应尽量减少这些高消耗函数的调用次数。

OpenGL ES 3.0 数据可视化 3:多次绘制调用(glDraw*)的性能问题_第3张图片
glDrawArrays内部调用栈

那么,说了半天,到底每次glDrawArray调用要花多长时间?没图没真相。方便起见,现截取Debug模式的性能数据,首先是每帧绘制的总耗时为10.72毫秒,然后是逐点的绘制耗时。它们符合一个规律:点越大,则光栅化出来的正方形也大,在片段着色器中需要判断的片段数量越多,同时出现更多被放弃(discard)的片元,计算耗时随之加大。

OpenGL ES 3.0 数据可视化 3:多次绘制调用(glDraw*)的性能问题_第4张图片
多次glDrawArrays画多个圆点的每帧资源消耗
OpenGL ES 3.0 数据可视化 3:多次绘制调用(glDraw*)的性能问题_第5张图片
每次glDrawArrays的耗时列表
OpenGL ES 3.0 数据可视化 3:多次绘制调用(glDraw*)的性能问题_第6张图片
圆点递增耗时

从前面的图表已知耗时信息,现在看看具体存在的性能问题,使用Xcode 8 Instruments提示如下。值得注意的是,Instruments 8.0 (8A218a)对于同一份代码的部分性能警告不同于Instruments 7.3 (7D175),我个人经实测,认为Instruments 7.3的提示更准确。

OpenGL ES 3.0 数据可视化 3:多次绘制调用(glDraw*)的性能问题_第7张图片
绘制多个圆点存在的性能问题

你可能感兴趣的:(OpenGL ES 3.0 数据可视化 3:多次绘制调用(glDraw*)的性能问题)