在现代游戏中,双重或三次缓冲解决了什么问题?


31

我想检查一下我对使用双(或三)缓冲的原因的理解是否正确:

刷新频率为60Hz的监视器每秒可显示60次。如果监视器刷新监视器显示,则他将像素更新为像素,将行更新为行。监视器从视频存储器中请求像素的颜色值。

如果我现在运行一个游戏,则该游戏会不断操纵该视频内存。

如果此游戏不使用缓冲策略(双缓冲等),则可能会发生以下问题:

监视器现在正在刷新其监视器显示。此时,显示器已经刷新了上半部分显示器的显示。同时,游戏用新数据操纵了视频存储器。现在,监视器访问下半部分监视器,显示来自视频存储器的新操作数据。问题可能是撕裂或闪烁。

我对使用缓冲策略的案例的理解正确吗?还有其他原因吗?

Answers:


62

从根本上讲,渲染的核心目标是使监视器上显示的每一帧呈现单个连贯的图像。为了达到此目的,已经或已经使用了几种不同的策略。

在下面,我提到“ vsync”。Vsync是监视器开始绘制新屏幕图像的时刻;在传统的CRT屏幕上,这是“ vblank”开始的地方,扫描线会暂时停止绘制并移回监视器顶部。对于许多框架连贯性的方法,这一刻非常重要。

当屏幕在同一帧内从两个不同的图像进行渲染时,我们称之为“撕裂”。例如,如果我绘制了两个屏幕图像,它们打算一个接一个地显示,但是监视器却显示了第一帧的上半部分和第二帧的下半部分,那就是“撕裂”。这是由于在绘制监视器时而不是在vblank期间更改了监视器读取的数据。(在现代程序中,这通常是由于用户在驱动程序设置中禁用了等待vsync而发生的)

零缓冲

在最旧的硬件上,通常没有足够的内存来保存全屏图像,因此,在监视器正在绘制该线的过程中,您需要为每个扫描线分别指定颜色,而不是绘制屏幕图像。例如,在Atari 2600上,您只有76个机器指令周期来指定在电视机开始实际绘制扫描线之前,扫描线的每个像素采用哪种颜色。然后,您有76个指令周期来提供一条扫描线的内容,依此类推。

单缓冲器

在“单缓冲区”上下文中绘制时,您将直接绘制到监视器正在读取的VRAM中。在这种方法中,您“使用扫描线”。通常的想法是,当扫描线开始在屏幕顶部绘制上一帧的内容时,您将后面绘制VRAM 。因此,当扫描线绘制最后一帧的屏幕图像时,您将在扫描线后面绘制下一帧。

通常,您要通过再次走过来并超越所绘制的像素来完成在扫描线“重叠”之前完成下一帧图像的绘制,并且永远不要超越扫描线,否则您的新框架可能会吸引到原先的框架中。

因此,单缓冲区渲染通常通过从上到下以及从左到右绘制扫描线来工作。如果以其他顺序绘制,则扫描线可能会再次出现,并发现尚未绘制的“下一个”图像的某些位。

请注意,在现代操作系统中,您通常永远没有机会绘制单缓冲区,尽管这在30年前是相当普遍的。(天哪,我现在感觉很老-这是我刚开始游戏开发时所做的事情)

双缓冲

这比以前的任何一种策略都简单得多。

在双缓冲系统中,我们有足够的内存来存储两个不同的屏幕图像,因此我们将其中一个指定为“前缓冲区”,将另一个指定为“后缓冲区”。“前缓冲区”是当前显示的内容,“后缓冲区”是我们当前绘制的位置。

在完成向后缓冲区绘制屏幕图像之后,我们等待直到vsync,然后交换两个缓冲区。这样,后缓冲区变成前缓冲区,反之亦然,并且整个交换发生在监视器没有绘制任何内容的时候。

三重缓冲

双缓冲区方法经常引起的一个问题是,当我们完成向后缓冲区的绘制后,我们必须等待vsync,然后才能交换缓冲区并继续工作。在那段时间内我们可能一直在进行计算!而且,在我们一直等待缓冲区之间交换的所有时间中,该后缓冲区中的图像越来越老,从而增加了用户的感知延迟。

在三缓冲区系统中,我们为自己创建了三个缓冲区-一个前缓冲区和两个后缓冲区。这个想法是这样的:

监视器正在显示前缓冲区,而我们正在绘制后缓冲区#1。如果我们在监视器完成绘制前缓冲区之前完成绘制到后缓冲区#1中,那么我们不必等待vsync,而是立即开始将下一帧绘制到后缓冲区#2中。如果我们完成并且vsync仍然没有来,我们就开始退回到1号后备缓冲区,依此类推。这个想法是,当vsync最终发生时,一个或另一个后缓冲区将完成,并且可以将其中一个替换为前缓冲区。

三重缓冲的好处是,我们不会浪费在双缓冲方法中等待vsync所花费的时间,并且交换到前缓冲区的映像可能比正在等待vsync的映像“刷新”了。 8毫秒 三重缓冲的缺点是,我们需要额外的内存来存储多余的屏幕图像,并且CPU / GPU的使用率会更高(再次,因为我们不会放慢等待vsync的速度)。

通常,现代驱动程序通常会在后台透明地执行三重缓冲。您编写代码以进行双缓冲,驱动程序实际上将尽早将控制权归还给您,并且仅在内部处理它想使用的多个后备缓冲区之间的交换,而您的代码从未意识到这一点。

GPU供应商当前建议您不要自己实现三重缓冲-驱动程序会自动为您完成。


7
这是一个非常详细的答案,并解释了为什么很多事情都按原样完成(例如屏幕坐标空间等)。还回答了我的问题“为什么没有四倍的缓冲区?五倍?” 我没有意识到缓冲区交换是在后台发生的,这意味着需要两个后备缓冲区。已投票。
Lunchmeat317 2014年

实际上,存在四元缓冲。这是立体视图的双重缓冲。swiftless.com/tutorials/opengl/smooth_rotation.html
Narek

@Narek号。从链接中引用:“由于没有实际意义,因此您不能在计算机图形环境中真正启用实际的四元缓冲”。暗示同时在两个不同的视图上执行双缓冲将是“四级缓冲”,只是在玩文字游戏。不是真实的东西。
特雷弗·鲍威尔

@TrevorPowell添加了您忘记包括的部分:“好吧,通常,四缓冲是指在立体环境中的双缓冲。例如:您有两个显示器,通常用于3D目的,并且每只眼睛都是双缓冲的。” 现在,上下文可能更加清晰。
纳雷克

@TrevorPowell您的观点虽然很清楚。一个渲染缓冲区具有三个以上的缓冲区是没有意义的。
纳雷克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.