使用FBO + RBO和glFinish()进行双缓冲

时间:2013-07-12 05:59:00

标签: opengl opengl-3

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

很好,我没有任何闪烁,但如果场景变得有点复杂,我会遇到fps的巨大下降,有些奇怪,我知道有些事情是错的。我不是指从1/60到1/30,因为跳过同步,我的意思是突然下降了90%fps。

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

所以我在默认的framebuffer和swapbuffers()上使用了常规的doble缓冲,并且fps也得到了提升,就像使用glFinish()时一样。

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

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

2 个答案:

答案 0 :(得分:1)

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

当直接渲染到RBO并向前缓冲区进行blitting时,根本就没有同步。因此,在复杂场景中,GPU命令队列将非常快速地填充,然后CPU驱动程序队列也将快速填充,直到驱动程序在OpenGL命令期间强制CPU同步。此时CPU线程将暂停。

我的意思是,在没有任何形式的同步的情况下,复杂的渲染(将一个或多个OpenGL命令放入队列中的渲染)将始终导致CPU线程在某个时刻停止,因为作为队列将填写,CPU将发出越来越多的命令。

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

参考: OpenGL Synchronization

答案 1 :(得分:1)

这里有单独的问题,也有点连接。

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

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

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

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