VBO 与即时模式性能

Posted

技术标签:

【中文标题】VBO 与即时模式性能【英文标题】:VBO vs Immediate Mode Performance 【发布时间】:2014-09-27 17:40:33 【问题描述】:

如果我有一个顶点不断变化的模型,因此我需要在每一帧重新绑定我的 VBO 上的所有信息,使用立即模式会不会更高效?或者所有数据都同时传递到 GFX 卡的事实仍然是 VBO 的一个赎回因素?

根据第一个问题的答案,这是否意味着为每个网格保留一个世界矩阵比简单地转换几何图形并重新创建 VBO 更好?

【问题讨论】:

【参考方案1】:

与几乎所有性能问题一样,答案是:视情况而定。很多因素都会发挥作用,主要是您的确切使用模式以及 OpenGL 实现的特征。

虽然即时模式在很大程度上被认为已过时,并且已从现代 OpenGL 版本中删除,但如果您的几何图形高度动态,则很难通过 VBO 获得更好的性能。

作为一个案例研究,我从事一个爱好项目 (1) 已经有相当长的时间了(并且有很长的休息时间)。在这种情况下,所有顶点坐标都是动态计算的,并且只用于渲染一次。最初的版本使用立即模式,因为它在这种情况下很方便,而且当我编写它时,立即模式还没有那么过时。几年后我再次选择它并将其移植到 Core Profile 和 ES 3.0 时,我最初很难获得相同的性能。

您必须尝试各种选项才能找到最适合您的用例和平台的选项。常见的选项包括:

将顶点数据写入本地内存,并使用glBufferSubData() 将其分批输入VBO。 通过使用 NULL 数据指针调用 glBufferData() 创建一个足够大的 VBO 以保存您的数据。然后使用glMapBuffer()glMapBufferRange()映射缓冲内存,将你的顶点数据写入映射内存。 对于之前的方法,您可能还想尝试使用多个缓冲区并循环访问它们,以减少 CPU 和 GPU 之间的同步。

关于即时模式在当前 GPU 上的工作方式存在一个常见的误解(部分反映在其他答案中)。当前没有 GPU(据我所知)实际上支持即时模式。当您进行即时模式调用时,驱动程序通常会将顶点数据放在缓冲区中,并在稍后将这些缓冲区提交给 GPU。所以 GPU 最终会执行几乎相同的绘图。唯一的区别是您是构建缓冲区(通过使用基于 VBO 的绘图),还是让驱动程序处理它(通过使用立即模式)。

立即模式绘图通常效率低下的主要原因是它需要如此多的 API 调用,而不是因为 GPU 最终执行了什么。

(1) 无耻插件,如果有人想看看它是什么:http://retokoradi.com/volume-rendering/。

【讨论】:

The OpenGL wiki has a nice article on streaming buffer objects 感谢您提供如此深入的回答!特别是关于 API 调用的部分,老实说,我认为效率低下是在立即模式使用的方法上。有用的信息! 更新链接:The OpenGL wiki has a nice article on streaming buffer objects【参考方案2】:

是的,几乎总是最好使用矩阵来转换几何。顶点着色器将每个顶点乘以一个世界矩阵。而且这一切都在多线程 GPU 上,这意味着即使在复杂的几何图形上也能获得良好的性能。

【讨论】:

【参考方案3】:

VBO 的性能会更好,因为正如您所说,它会一次将所有数据发送到 GPU。如果您使用双缓冲解决方案,它通常会运行得更快,在这种解决方案中,您为下一帧准备 VBO,而 GPU 正在渲染前一帧的帧,因为它不会停止等待来自 CPU 的更多数据。

是的,如果您的转换可以用这样的矩阵充分描述,那么为每个 VBO 存储一个单独的世界矩阵会好得多。您将在每帧更改更少的数据,从而减少必须通过总线传输到 GPU 的数据。

【讨论】:

以上是关于VBO 与即时模式性能的主要内容,如果未能解决你的问题,请参考以下文章

VBO 中的交错是帮助还是阻碍性能?

为啥分配大量 VBO 会导致性能问题?

在 Android 中使用带有 OpenGL ES 的 VBO 性能不佳

共享内存架构中的 OpenGL (ES 2.0) VBO 性能

即时通讯开发中的高性能网络编程I/O模型

我使用多少个 VBO?