QT - 如何正确处理Vsync和多个QGLWidgets

3
我正在同一个主线程中使用三个不同的QGLWidgets,希望以60fps渲染,但是我无法达到更高的20fps。这似乎是由于Vsync引起的,因为每个小部件可能会独立地尝试与刷新率同步,从而它们会被锁定。如果我只使用两个小部件,我可以达到30fps。或者,如果我将一个小部件的更新速率固定为10fps,那么我在其他两个上可以达到25fps(10 + 25 + 25 = 60)。无论我使用setSwapInterval(int)设置什么值,swapInterval()始终返回0。有什么想法吗?我能禁用Vsync吗?或者问题可能是由其他原因引起的吗?

你找到解决方案了吗? - maddin45
不幸的是,我有一个丑陋的解决方法,就是简单地隐藏小部件,因为我并不总是同时使用它们,但当然这不是一个可接受的解决方案。 - Marc
真可惜,我真的很想知道问题出在哪里。 - maddin45
2个回答

3

看起来这是Qt 5.0的一个bug - https://bugreports.qt.io/browse/QTBUG-29073

关闭Vsync将解决在QGLWidget之间分配更新率的问题,您的显卡将根据您设置或其能力尽可能快地渲染到屏幕上。但您必须在显卡设置中禁用VSync。只设置fmt.setSwapInterval(0)将没有任何作用。

不幸的是,另一个问题出现了,如果您正在播放包含水平移动的视频,则会出现撕裂。

希望Qt 5.3可以修复此错误。


谢谢!出于某些神秘的原因,我从未想过禁用Vsync可能实际上是一个显卡设置 - 问题解决了 ;) - Marc

2
对于那些仍在苦苦挣扎的人,我的简短回答是:在尝试其他任何方法之前:安装Qt 5.4。
更详细的回答:
我从未遇到过使用Qt 4.8禁用VSync的问题。
在使用Qt 5.3.1(在Kubuntu 14.04 64位系统中),我从未能够强制我的QGLWidget不与VBlank同步,这意味着swapBuffers()无论如何都会阻塞。我在“桌面效果”面板和NVidia控制面板中都禁用了VSync,并将setSwapInterval(0)设置为无效。因此,我的fps始终被限制为60fps / numOfQGLWidget(除非我使用SingleBuffering,但在我的应用程序中闪烁是不可忍受的)。使用多线程,理论上应该可以启用VSync(因此没有撕裂),并为多个QGLWidget实现60fps,但我也无法使其正常工作。
今天,我刚刚安装了Qt 5.4,它神奇地解决了这个问题:我成功地拥有了一个非阻塞的swapBuffers(),就像我在Qt 4.8中使用的那样。我认为Qt 5.3无论你的驱动程序设置如何都会强制执行VSync。但在Qt 5.4中不再是这种情况,至少在我的配置中不是这样。Qt团队似乎为Qt 5.4改进了OpenGL(特别是他们引入了QOpenGLWidget类),因此我向任何使用Qt的OpenGL用户建议升级到Qt 5.4,它可能会让你的生活更轻松。

有没有关于如何在QOpenGLWidget中实现垂直同步的建议?我正在使用QOpenGLWidget作为视频渲染窗口的基类,但是出现了撕裂现象。 - SPlatten
1
@SPlatten 在你的 main() 函数中,在构建 QApplication 之前,构建一个 QSurfaceFormat format,设置 format.setSwapInterval(0),然后 QSurfaceFormat::setDefaultFormat(format)。详情请见 http://doc.qt.io/qt-5/qsurfaceformat.html#setSwapInterval 和 http://doc.qt.io/qt-5/qsurfaceformat.html#setDefaultFormat 。希望这样做可以解决问题。否则,你可能需要查看你的图形驱动程序设置或操作系统/桌面环境,因为它们可能会覆盖这些设置。一般来说,很难以可移植的方式确保垂直同步(VSync)被启用。 - Boris Dalstein
1
谢谢,我会尝试一下。 - SPlatten

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