现代图形管线有多少个帧深度?

4
假设管道已经完全充满:GPU 等待垂直同步,GPU/驱动程序命令缓冲区全部充满,因此用户程序被阻塞。
(现代)管道中有多少帧数据?
例如:(4)
  1. 在 GPU 前缓冲区的帧
  2. 在 GPU 后缓冲区的帧
  3. 在 GPU 命令缓冲区的帧
  4. 在 CPU 驱动程序命令缓冲区的帧
2个回答

5
这要看你用的是哪种显卡,以及它处于哪种模式下,但一般来说,答案是1-3帧(或者2-4帧,如果你将被推入缓冲区的帧也算作帧数的话)。
没有启用垂直同步或任何其他双缓冲策略时,没有强制要求在任何给定时间内保持在内存中超过1个帧,因为新的帧一旦被推入缓冲区就会立即被覆盖。
当启用垂直同步时,新的帧被推入到帧缓冲区的第二部分,并延迟任何未来的命令执行,直到"垂直同步"触发,此时两个帧将被翻转。
第三种模式,对OpenGL不常见但Vulkan和DirectX用户熟悉的“Letterbox模式”,有时也称为“三倍缓冲”,保留两个“后备缓冲区”,总共三个缓冲区:
其中一个后备缓冲区保留用于垂直同步触发时使用。
另一个后备缓冲区直接接收完成的帧,无需延迟
每当发生垂直同步时,这两个后备缓冲区的角色都会互换。
需要注意的是,在三倍缓冲模式下,主机在缓冲区已满时不会被阻塞。
GPU可能会选择缓存其他帧,就像你的示例一样,但这更常见于OpenGL / DirectX11而不是Vulkan / DirectX12 +,因为在后者的API中,主机在GPU应该执行什么方面非常明确。我想不出一个程序员会有意扩展帧缓冲区。除了三倍缓冲已经提供的好处之外,它并没有很明显的好处。

好的。因此,根据经验,使用OpenGL和垂直同步 - 我注意到:(1)只要我能够在32.2ms内提交2个CPU帧(无论第一个花费27ms,第二个花费3ms),那么我就不会观察到任何丢帧。(2)然而,未能这样做会导致帧丢失。我可以得出什么关于平台管道的结论? - Kay
@user7226419 这是VSync的自然行为。如果第二帧甚至稍微超过了垂直同步的截止时间,GPU将等待下一帧再呈现该帧。 - Xirema
如果第一帧错过了截止时间,GPU根本不会等待。我猜这是因为在第一帧之前,管道中已经有了第0帧,GPU能够显示它?也就是说,管道中至少有1个“潜在”帧? - Kay
@user7226419 可能。当然要记住,OpenGL允许做很多“奇怪”的事情,因为它所代表的图形模型与现代GPU的工作方式非常不同,需要进行大量的驱动程序魔法来使一切符合规范。 - Xirema

4
对于传统的API(非命令缓冲器API),唯一重要的事情就是你使用了多少个缓冲区。图形管线可能被分段,但是这条管线并不是深入到可以在同一时间内处理多个完全分离的帧。因此,GPU的队列和GPU本身通常只会处理单个帧。

而且,在那些API中,没有真正的方法来为多个完整的帧构建命令数据,所以你可以在进行中的飞行过程中的帧数将受到实际使用的缓冲区数量的限制。延迟帧的数量通常是缓冲区的数量加1,代表你正在构建的帧。

对于命令缓冲器API,帧数通常基于你拥有的CPU内存数量。缓冲区的数量提供了一个最小值,但从技术上讲,你完全可以提前缓冲数十个甚至数百个帧。当然,这是在CPU内存之外。

当然,这假设所有每帧数据都存在于CBs中。如果任何其中的数据存在于GPU可访问的内存中(比如矩阵数组等),或者你需要在帧之间更改描述符集,则现在你有另一组需要缓冲的东西。这会给深入进行的事情带来额外的限制。


1
谢谢回复。我怎么知道我正在使用多少缓冲区?(这就是我拥有的图形知识水平:P)例如,在我的项目中,我只设置了一个帧缓冲区。 - Kay
在OpenGL中,您无法直接控制默认帧缓冲区中的缓冲区数量。因此,无论您是否能够获得计数,都不重要;您无法使用该信息执行任何操作。对于命令缓冲区API,您可以请求特定数量的缓冲区。 - Nicol Bolas
1
尽管不能控制缓冲区的数量,但一般会有X个缓冲区吗?例如:适用于iOS、Android上的OpenGLES 2.0实现。 - Kay
1
在GLES 2.0中,使用默认显示器时,默认有两个缓冲区:前缓冲区和后缓冲区。渲染循环后,您的应用程序必须调用eglSwapBuffer(display,surface)来交换前后缓冲区。 - Alex Byrth

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