我制作了一个游戏内图形分析器(CPU 和 GPU),Nvidia 驱动程序有一个奇怪的行为,我不确定如何处理。
这是正常情况下的截图:
您可以在这里看到连续 3 帧,GPU 在顶部,CPU 在底部。两个图是同步的。
“END FRAME”栏仅包含对 的调用SwapBuffers
。在 GPU 完成所有工作之前它一直处于阻塞状态似乎很奇怪,但这就是驱动程序有时在 vsync 开启时选择做的事情,并且所有工作(CPU 和 GPU)都可以在 16 毫秒内完成(AMD 也是如此)。我的猜测是它这样做是为了最大限度地减少输入滞后。
现在我的问题是它并不总是这样做。根据帧中发生的情况,图表有时看起来像这样:
这里实际发生的是,第一个 OpenGL 调用是阻塞的,而不是对
SwapBuffers
. 在这种特殊情况下,阻塞调用是glBufferData
. 如果我添加一个可以做到这一点的虚拟代码(创建一个统一缓冲区,用随机值加载它并销毁它),它会更加明显:
这是一个问题,因为这意味着图表中的条形可能会无缘无故变得非常大。看到这一点的人可能会得出关于某些代码运行缓慢的错误结论。
所以我的问题是,我该如何处理这种情况?我需要一种始终显示有意义的 CPU 计时的方法。
添加一个加载统一缓冲区的虚拟代码不是很优雅,并且可能不适用于未来版本的驱动程序(如果驱动程序只阻塞绘图调用怎么办?)。
与 a 同步glClientWaitSync
看起来也不是一件好事,因为如果帧速率下降,驱动程序将停止阻塞以允许 CPU 和 GPU 帧并行运行,我需要检测到停止调用glClientWaitSync
(但我'不知道该怎么做。)
(欢迎提出更好的标题建议。)
编辑:当 GPU 成为瓶颈时,这是没有 vsync 时会发生的情况:
GPU 帧比 CPU 帧花费的时间更长,因此驱动程序决定在
glBufferData
GPU 赶上之前阻塞 CPU。
条件不一样,但问题是:CPU时序是“错误的”,因为驱动程序做了一些OpenGL功能块。这实际上可能是一个比打开 vsync 的例子更容易理解的例子。