现代图形管线有多少帧深?
How many frames deep is a modern graphics pipeline?
假设管道已满:GPU 等待 vsync,GPU/driver 命令缓冲区已满,因此用户程序被阻止。
(现代)管道中有多少帧数据?
例如:(4)
- GPU 前端缓冲区中的帧
- GPU 后缓冲区中的帧
- GPU 命令缓冲区中的帧
- CPU 驱动程序命令缓冲区中的帧
这取决于您使用的是哪种显卡,以及您将其置于哪种模式,但一般来说,答案是 1-3 帧(或者 2-4,如果您计算帧数被作为帧推入缓冲区)。
- 如果没有 Vsync 或任何其他类型的双缓冲策略,则不会强制在任何给定时间将超过 1 帧的帧保留在内存中,并在将新帧推入缓冲区时立即覆盖。
- 启用 VSync 后,新帧被推入帧缓冲区的第二部分,并延迟执行任何未来的命令,直到 "Vertical Sync"(显然因此得名)触发,此时翻转了两帧。
- 第三种模式,OpenGL 不常见但 Vulkan 和 DirectX 用户熟悉,称为 "Letterbox mode",有时称为 "Triple Buffering",保留两个 "Back Buffers" 总共三个缓冲区:
- 其中一个后台缓冲区保留供垂直同步触发时使用。
- 另一个后台缓冲区直接接收完成的帧,没有延迟
- 每当发生垂直同步时,这两个后台缓冲区的角色就会互换。
请注意,使用三重缓冲时,主机不会在缓冲区已满时被阻塞。
GPU 可能会选择缓冲额外的帧,就像在您的示例中一样,尽管这在 OpenGL/DirectX11- 中比在 Vulkan/DirectX12+ 中更常见,因为在后者的 API 中,主机在 GPU 应该做什么方面更加明确,我无法想象一个程序员会故意扩展帧缓冲区。除了 Triple Buffering 已经提供的功能之外,它还能提供什么好处还不是很清楚。
对于传统 API(非命令缓冲区 API),唯一真正重要的是您使用了多少缓冲区。图形管线可能是管线式的,但管线没有那么深以至于多个完全独立的帧可以同时被处理。所以 GPU 的队列和 GPU 本身通常只会处理一个帧。
并且由于这些 API 中没有真正的方法来为多个完整帧构建命令数据,因此您可以在飞行中拥有的帧数将受到您使用的实际缓冲区数的限制。延迟的帧数通常是缓冲区数 + 1,代表您正在构建的帧。
对于命令缓冲区 API,帧数通常取决于您有多少 CPU 内存。缓冲区的数量提供了最小值,但从技术上讲没有什么可以阻止您提前缓冲数十或数百帧。 CPU 内存之外。
当然,这是假设您所有的每帧数据都存在于 CB 中。如果其中任何数据位于 GPU 可访问的内存中(例如,矩阵数组等),或者您需要在帧之间更改描述符集,那么您现在有另一组内容需要缓冲。这对事物的深度施加了额外的限制。
假设管道已满:GPU 等待 vsync,GPU/driver 命令缓冲区已满,因此用户程序被阻止。
(现代)管道中有多少帧数据?
例如:(4)
- GPU 前端缓冲区中的帧
- GPU 后缓冲区中的帧
- GPU 命令缓冲区中的帧
- CPU 驱动程序命令缓冲区中的帧
这取决于您使用的是哪种显卡,以及您将其置于哪种模式,但一般来说,答案是 1-3 帧(或者 2-4,如果您计算帧数被作为帧推入缓冲区)。
- 如果没有 Vsync 或任何其他类型的双缓冲策略,则不会强制在任何给定时间将超过 1 帧的帧保留在内存中,并在将新帧推入缓冲区时立即覆盖。
- 启用 VSync 后,新帧被推入帧缓冲区的第二部分,并延迟执行任何未来的命令,直到 "Vertical Sync"(显然因此得名)触发,此时翻转了两帧。
- 第三种模式,OpenGL 不常见但 Vulkan 和 DirectX 用户熟悉,称为 "Letterbox mode",有时称为 "Triple Buffering",保留两个 "Back Buffers" 总共三个缓冲区:
- 其中一个后台缓冲区保留供垂直同步触发时使用。
- 另一个后台缓冲区直接接收完成的帧,没有延迟
- 每当发生垂直同步时,这两个后台缓冲区的角色就会互换。
请注意,使用三重缓冲时,主机不会在缓冲区已满时被阻塞。
GPU 可能会选择缓冲额外的帧,就像在您的示例中一样,尽管这在 OpenGL/DirectX11- 中比在 Vulkan/DirectX12+ 中更常见,因为在后者的 API 中,主机在 GPU 应该做什么方面更加明确,我无法想象一个程序员会故意扩展帧缓冲区。除了 Triple Buffering 已经提供的功能之外,它还能提供什么好处还不是很清楚。
对于传统 API(非命令缓冲区 API),唯一真正重要的是您使用了多少缓冲区。图形管线可能是管线式的,但管线没有那么深以至于多个完全独立的帧可以同时被处理。所以 GPU 的队列和 GPU 本身通常只会处理一个帧。
并且由于这些 API 中没有真正的方法来为多个完整帧构建命令数据,因此您可以在飞行中拥有的帧数将受到您使用的实际缓冲区数的限制。延迟的帧数通常是缓冲区数 + 1,代表您正在构建的帧。
对于命令缓冲区 API,帧数通常取决于您有多少 CPU 内存。缓冲区的数量提供了最小值,但从技术上讲没有什么可以阻止您提前缓冲数十或数百帧。 CPU 内存之外。
当然,这是假设您所有的每帧数据都存在于 CB 中。如果其中任何数据位于 GPU 可访问的内存中(例如,矩阵数组等),或者您需要在帧之间更改描述符集,那么您现在有另一组内容需要缓冲。这对事物的深度施加了额外的限制。