在iOS上,glDrawElements会导致大量的CPU使用。

5

硬件:iPad2
软件:OpenGL ES 2.0 C++

glDrawElements似乎占用了约25%的CPU。使得每帧CPU为18毫秒,GPU为10毫秒。

当我不使用索引缓冲区而是使用glDrawArrays时,速度更快,且glDrawArrays几乎不在分析器中显示出来。其他所有内容都相同,因为我必须在没有索引缓冲区的情况下在VBO中复制顶点。

到目前为止:

  • 两种方法之间的状态改变几乎相同
  • 顶点结构是两个浮点数(8字节)。
  • 索引缓冲区为16位(也尝试过32位)
  • 对于两个缓冲区均为GL_STATIC_DRAW
  • 缓冲区在加载后不会更改
  • 同一个VBO和索引缓冲区多次渲染每一帧,具有不同的偏移量和大小
  • 没有OpenGL错误

因此,看起来它正在进行某种软件回退。但是我无法弄清楚什么会导致OpenGL回退。

1个回答

2
有几件事情立即会影响到速度,就像你所描述的那样。
首先,为了减少总线转移的数量,许多命令被动地发出。它们排队等待下一批传输。状态更改、纹理更改和类似的命令都会累积。可能的情况是,在一个情况下绘制命令触发了更大的传输,而在另一个情况下没有触发,或者在一个情况下触发了更频繁的传输。其次,您特定的模型可能对其中一个绘制调用优化得更好。您需要查看它们有多大、是否重复使用索引值以及它们是否被优化或重新排序以进行呈现。glDrawArrays可能需要传输更多数据,但如果您的模型很小,则开销可能不是一个大问题。绘制频率变得重要,因为您希望频繁排队调用,以使卡忙碌并让CPU做其他工作,而不是只在命令缓冲区中累积等待发送,但这需要平衡,因为这些传输是有成本的。最后,当频繁重复使用索引值时,常规索引值可以从缓存效果中受益,但当它们被线性访问时,线性访问数组可以从缓存效果中受益。因此,您需要了解自己的数据,因为不同类型的数据受益于不同的方法。
即使是Apple似乎也不确定要使用哪种方法。
直到iOS7,版本及更早的IOS版OpenGL ES编程指南写道:
“为了获得最佳性能,应提交您的模型作为单个未索引的三角形带,使用尽可能少的重复顶点通过glDrawArrays进行呈现。如果您的模型需要重复许多顶点(...),则可以使用单独的索引缓冲区,并调用glDrawElements来获得更好的性能......为了获得最佳结果,请使用索引的和未索引的三角形条测试您的模型,并使用执行最快的那一个。”
但他们更新的iOS8适用的OpenGL ES编程指南提供了相反的建议:
“为了获得最佳性能,应提交您的模型作为单个索引三角形条。为避免在顶点缓冲区中多次指定相同的数据,请使用单独的索引缓冲区,并使用glDrawElements函数绘制三角形带。”
看起来在您的情况下,您已经尝试了两种方法,并发现其中一种方法更适合您的数据。

谢谢!我想我会进行一些绘制频率的测试。我还将与苹果双重检查我的配置文件,并查看驱动程序是否有任何可疑之处。 - myro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接