【发布时间】:2015-04-24 02:50:11
【问题描述】:
我制作了一个游戏内图形分析器(CPU 和 GPU),但我不知道如何处理 Nvidia 驱动程序的一个奇怪行为。
以下是正常情况的屏幕截图: 在这里你可以看到连续 3 帧,GPU 在顶部,CPU 在底部。两个图都是同步的。
“END FRAME”栏只包含对SwapBuffers 的调用。在 GPU 完成所有工作之前它会阻塞似乎很奇怪,但这就是驱动程序有时在 vsync 开启时选择做的事情,并且所有工作(CPU 和 GPU)都可以在 16 毫秒内完成(AMD 也是如此)。我的猜测是这样做是为了最大限度地减少输入延迟。
现在我的问题是它并不总是这样做。根据框架中发生的情况,图表有时如下所示:
这里实际发生的是,第一个 OpenGL 调用是阻塞的,而不是对SwapBuffers 的调用。在这种特殊情况下,阻塞调用是glBufferData。如果我添加一个可以做到这一点的虚拟代码(创建一个统一缓冲区,用随机值加载它并销毁它),它会更加明显:
这是一个问题,因为这意味着图表中的条形可能会无缘无故变得非常大。看到这一点的人可能会得出关于某些代码运行缓慢的错误结论。
所以我的问题是,我该如何处理这种情况?我需要一种方法来始终显示有意义的 CPU 计时。
添加一个加载统一缓冲区的虚拟代码不是很优雅,并且可能不适用于未来版本的驱动程序(如果驱动程序只阻塞绘制调用怎么办?)。
与glClientWaitSync 同步看起来也不是一件好事,因为如果帧速率下降,驱动程序将停止阻塞以允许 CPU 和 GPU 帧并行运行,我需要检测到这一点停止拨打glClientWaitSync(但我不知道该怎么做。)
(欢迎提出更好的标题建议。)
编辑:当 GPU 成为瓶颈时,如果没有 vsync,会发生以下情况:
GPU 帧比 CPU 帧花费的时间更长,因此驱动程序决定在 glBufferData 期间阻塞 CPU,直到 GPU 赶上。
条件不一样,但问题是:CPU时序“错误”,因为驱动程序做了一些OpenGL功能块。这实际上可能比打开 vsync 的例子更容易理解。
【问题讨论】:
-
好吧,GL 可能会在任何时候阻塞,出于任何特定于实现的原因。 OTOH,即使 vsync 开启,SwapBuffers 也不能保证阻塞。例如,Windows 上的 nvidia 驱动程序甚至有一个配置选项,它可以在必须阻止之前提前缓冲多少帧 - 但是,这也不是一个可靠的最小值,如果你在一帧中做了很多工作,它可能会更早地阻止,或强制进行一些隐式或显式同步。我曾经观察到一个奇怪的问题,即 nvidia 驱动程序在 1 帧和 2 帧延迟之间交替,产生生涩的动画,而平均速度仍为 60 fps。
-
我真的不知道如何解释我在您的任何屏幕截图中在 CPU 分析器中看到的内容,因此您在编辑中所做的更改并没有它们应有的洞察力。不过,我彻底概述了 VSYNC 导致不可预知的阻塞行为的原因……您可能会发现这很有用。
-
在上一个截图中,GPU 帧比 CPU 帧花费的时间更长,因此驱动程序会在某个时刻阻塞 CPU 以等待 GPU。这可能发生在 SwapBuffer 或其他地方,比如屏幕截图。但是,是的,您的回答很有见地,谢谢。
-
你正在使用 imgui ,不错的库
标签: performance opengl rendering nvidia vsync