【问题标题】:double buffering with FBO+RBO and glFinish()使用 FBO+RBO 和 glFinish() 进行双缓冲
【发布时间】:2013-07-12 05:58:59
【问题描述】:

我使用的是 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() 吗?

【问题讨论】:

  • “然后我在 blit 之后尝试了 glFinish(),我得到了 10 倍 fps 的提升” - 听起来像是你的计时方法有问题,就像它是不能与您的 GPU 很好地同步(glFinish 当然可以实现)。更多代码会很有趣。
  • 考虑到诸如三重缓冲、自适应垂直同步等驱动程序中的所有内容,我不认为重新实现双缓冲会更好。
  • @BartekBanachewicz 如果您需要用于屏幕和屏幕外渲染的缓冲区,这是有道理的,但您确实需要做很多工作来(重新)优化屏幕部分。
  • 你真的看到帧率的不同了吗?您应该注意到在更复杂的场景中下降了 90%,尤其是在移动时。另外:FPS 是一个令人困惑的性能测量单位,通常首选渲染时间(例如每帧 X 毫秒)。

标签: opengl opengl-3


【解决方案1】:

我认为这是与同步相关的问题。

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

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

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

参考: OpenGL Synchronization

【讨论】:

  • CPU 发出越来越多的命令不应该让实际渲染变得更糟,但是它会使 CPU 和 GPU 不同步,CPU 可能认为它已经渲染了 20 帧,而GPU只完成了1个。但我认为CPU在队列中发布许多命令不会对可见帧率产生太大影响(虽然是测量帧率......)。但是,这只是一点直觉,现在不能尝试:)。
【解决方案2】:

这里有不同的问题,也有一点联系。

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

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

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

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

【讨论】:

    猜你喜欢
    • 2011-02-20
    • 2010-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-26
    • 1970-01-01
    • 2018-09-14
    • 1970-01-01
    相关资源
    最近更新 更多