2011-07-01 78 views
14

由于今天的卡片似乎保留了渲染命令列表,并且只在调用glFlushglFinish时才刷新,是否真的需要双缓冲?我在Linux上开发的OpenGL游戏(ATI Mobility radeon卡)与SDL/OpenGL实际上闪烁较少,当SDL_GL_swapbuffers()被替换为glFinish()SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,0)在init代码中时。这是我的卡片的特殊情况还是所有卡片上都有这种情况?是否需要双缓冲

编辑:我发现原因是KWin。看起来像datenwolf说的那样,没有同步的合成是原因。当我关闭KWin合成时,游戏无需任何源代码补丁即可正常工作

回答

19

双缓冲和glFinish是两个非常不同的东西。

glFinish会阻止程序,直到所有绘图操作完成。

双缓冲用于隐藏用户的渲染过程。如果没有双缓冲,假设显示刷新频率无限高,则每个绘图操作都将立即可见。在实践中,你会得到一些显示伪像,例如场景的一部分在一种状态下可见,其余部分不可见或在其他某种状态下,图像可能不完整等。双缓冲通过首先渲染到后台缓冲区中避免这种情况,并且只有在渲染完成后,将其与前端缓冲区交换后才会发送到显示设备。

现在合成窗口管理变得流行:Windows具有Aero,MacOS X Quartz Extreme,并且在Linux上至少Unity和GNOME3 shell使用合成(如果可用)。重点是:合成在技术上创建doublebuffering:Windows绘制到屏幕外的缓冲区,其中最后的屏幕是合成的。所以,如果你在一台合成机器上运行,那么如果在你的程序中执行双缓冲,那么它就是多余的,并且它只需要某种同步机制来告诉合成器下一帧何时准备就绪。 MacOS X有这个。 X11仍然缺乏一个适当的同步方案,看到这个帖子上的maillist:http://lists.freedesktop.org/archives/xorg/2004-May/000607.html

TL; DR:双缓冲和glFinish是不同的东西,你需要双缓冲(某种形式的)来使事情看起来不错。

+0

提到的帖子已超过6岁。 X11是否还缺少同步方案?那么Windows呢? –

+3

除了datenwolf的解释,你应该注意到你通常不会调用'glFlush'或'glFinish',除非在一些非常非常罕见的特殊情况下。 'glFinish'什么也不做('wgl | glx)SwapBuffers'没有做过(假设vsync被启用),'glFlush'只刷新排队的命令并且告诉服务器开始处理它们,这在最好的情况(但是是无用的调用和上下文切换),并且在最坏的情况下导致更差的性能(由于GPU资源的次优调度)。 – Damon

+1

理想情况下,您会希望尽可能多地在GL上执行命令,并尽可能扩展依赖关系(例如,如果使用纹理,首先发送命令来定义纹理图像,设置纹理状态等,然后发送一些执行其他操作的命令,然后只绘制使用此纹理的东西)。这可以确保:a)由于依赖关系,命令流中的命令不太可能被阻止; b)如果队列中的命令停顿,驱动程序可以安排其他一些命令来利用GPU(OpenCL或其他程序?)。 – Damon

2

我认为它与你的渲染或硬件有关的东西比任何可能泛化为不在你机器上的东西都要多。所以不:不要试图做到这一点。

哦,别忘了multisampling。许多实现仅对后台缓冲区进行多重采样;前端缓冲区不是多重采样的。进行交换将从多采样缓冲区下采样。