首页 > 解决方案 > glBufferSubData 在许多 android 设备上非常慢

问题描述

我请求了大约 2M gl 缓冲区用于共享,并使用 glBufferSubData 更新顶点和索引的数据,它在我的 iOS 设备上运行良好。同时,当我在我的安卓设备上测试它时,它非常非常慢。

我从官网找到了一些注释: https ://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBufferSubData.xhtml

“在更新数据存储之前,渲染必须从管道中排出”到底是什么意思?

标签: opengl-esopengl-es-2.0opengl-es-3.0

解决方案


您看到的性能差异可能不仅仅是 iOS/Android 的差异,而且对于您对 API 的使用和驱动程序中 glBufferSubData 的实现都非常具体。如果没有看到更多代码,或者不知道您正在收集哪些性能指标,很难进一步评论。

“在更新数据存储之前,渲染必须从管道中排出”到底是什么意思?

这里的想法是,虽然 OpenGL API 给人一种错觉,即每个命令在继续之前执行完毕,实际上,绘图通常是在后台异步完成的。这里的问题是 glBufferSubData 可能会添加一个同步点,这意味着驱动程序必须停止,直到之前使用该缓冲区的所有渲染都完成后才能继续。

考虑以下示例。在一个好的情况下,我们可能会有这样的事情:

  • 使用 ABCDE 将 glBufferSubData 放入缓冲区 1
  • 使用缓冲区 1 绘制调用
  • 使用 FGHIJ 将 glBufferSubData 放入缓冲区 2
  • 使用缓冲区 2 绘制调用
  • Swap buffers <----- 同步点,驱动必须等待渲染完成才能交换缓冲区

但是,如果您要覆盖相同的缓冲区,您将得到它。

  • 使用 ABCDE 将 glBufferSubData 放入缓冲区 1
  • 使用缓冲区 1 绘制调用
  • glBufferSubData 到缓冲区 1,用 FGHIJ <----- 覆盖同步点,因为驱动程序必须确保缓冲区已被第一次绘制调用使用完,然后再修改数据
  • 使用更新的缓冲区 1 绘制调用
  • Swap buffers <----- 同步点,驱动必须等待渲染完成才能交换缓冲区

如您所见,您最终可能会获得第二个同步点。但是,如前所述,这在某种程度上是特定于驱动程序的。例如,某些驱动程序可能能够检测到您正在更新的缓冲区部分未被先前的绘图调用使用的情况,而其他驱动程序可能不会。这种性质的东西可能是导致您看到的性能差异的原因。


推荐阅读