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



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

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

我在闪电战之后尝试了glFlush(),没有区别,然后在闪电战后尝试了glFinish(),我的帧速率提高了10倍。

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

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

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

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

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

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

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

参考:OpenGL同步

这里有一些单独的问题,它们之间也有一些联系。

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

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

3) 只是不要做单缓冲。没有任何性能优势,您正在偏离驾驶员的"好"道路。窗口管理器针对双缓冲opengl进行了超级优化。

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

最新更新