7

我正在使用 FBO+RBO,而不是在默认帧缓冲区上进行常规双缓冲,而是绘制到 RBO,然后在单个缓冲 OpenGL 上下文中直接在默认 FBO (0) 的 GL_FRONT 缓冲区上进行 blit。

这很好,我没有任何闪烁,但如果场景变得有点复杂,我会经历 fps 的巨大下降,这太奇怪了,我知道一定有问题。而且我的意思不是因为跳过同步而从 1/60 到 1/30,我的意思是 90% 的 fps 突然下降。

我在 blit 之后尝试了 glFlush() - 没有区别,然后我在 blit 之后尝试了 glFinish(),我得到了 10 倍的 fps 提升。

因此,我在默认帧缓冲区和 swapbuffers() 上使用了常规双缓冲,并且 fps 也得到了提升,就像使用 glFinish() 时一样。

我无法弄清楚发生了什么。为什么 glFinish() 在不应该的情况下会产生如此大的影响?并且,可以直接在前端缓冲区上使用 RBO 和 blit,而不是在双缓冲上下文中使用 swapbuffers 调用吗?我知道我缺少 vsync,但复合管理器无论如何都会同步(事实上我没有看到任何撕裂),就好像监视器缺少 10 帧中的 9 帧。

只是出于好奇,本机 swapbuffers() 在 windows 或 linux 上使用 glFinish() 吗?

4

2 回答 2

1

这里有单独的问题,也有一点联系。

1)自己重新实现双缓冲,虽然在规格上是一样的,但对驱动程序来说不是一回事。驱动程序针对常见情况进行了高度优化。例如,许多芯片具有不同的 2d 和 3d 单位。swapBuffers 中的交换通常由 2d 单元处理。Blitting 缓冲区可能仍然使用 3d 单元完成。

2) 许多驱动程序忽略了 glFlush(和 Finish)。Flush 是客户端服务器渲染的遗物。Finish 用于分析。但是它被滥用来解决驱动程序错误。因此,现在驱动程序经常忽略它以提高使用 Finish 作为解决方法的遗留代码的性能。

3)只是不要做单缓冲。没有性能优势,并且您正在按照驱动程序的“好”路径工作。窗口管理器针对双缓冲 opengl 进行了超级优化。

4)您所看到的看起来很像您只是在泄漏资源。您是否分配缓冲区而不释放它们?一种快速而肮脏的检查方法是是否有任何 glGen* 函数返回不断增加的 id。

于 2013-08-13T06:03:25.217 回答
1

我相信这是一个与同步相关的问题。

当直接渲染到 RBO 并传输到前端缓冲区时,根本没有任何同步。因此,在复杂场景中,GPU 命令队列将很快填满,然后 CPU 驱动程序队列也将很快填满,直到在 OpenGL 命令期间驱动程序强制执行 CPU 同步。此时 CPU 线程将停止。

我的意思是,如果没有任何形式的同步,复杂的渲染(将一个或多个 OpenGL 命令放入队列中的渲染)总是会导致 CPU 线程在某个时候停止,因为队列会填满, CPU 将发出越来越多的命令。

为了获得流畅(更稳定)的用户交互,需要同步(使用特定于平台的 swapbuffers() 或 glFinish())以阻止 CPU 发出越来越多的命令(在turn 会使 CPU 线程稍后停止)

参考:OpenGL同步

于 2013-07-12T08:19:34.813 回答