performance - 分析 OpenGL 应用程序 - 当驱动程序阻塞 CPU 端时

标签 performance opengl rendering nvidia vsync

我制作了一个游戏内图形分析器(CPU 和 GPU),但我不确定如何处理 Nvidia 驱动程序的一种奇怪行为。

这是正常情况下的屏幕截图: GPU Profiler, vysnc on 你在这里看到的是连续的 3 帧,GPU 在上面,CPU 在下面。两个图是同步的。

“END FRAME”栏仅包含对 SwapBuffers 的调用。在 GPU 完成所有工作之前它一直处于阻塞状态,这看起来很奇怪,但这是驱动程序有时选择在 vsync 开启时执行的操作,并且所有工作(CPU 和 GPU)都可以在 16 毫秒内完成(AMD 也是如此)。我的猜测是它这样做是为了最大限度地减少输入延迟。

现在我的问题是它并不总是这样做。根据框架中发生的情况,图表有时如下所示: GPU Profiler, vysnc on, V2 这里实际发生的是第一个 OpenGL 调用是阻塞的,而不是对 SwapBuffers 的调用。在这种特殊情况下,阻塞调用是 glBufferData。如果我添加一个执行此操作的虚拟代码(创建一个统一缓冲区,用随机值加载它并销毁它),它会更加明显:

GPU Profiler, vysnc on, V2 with dummy code

这是一个问题,因为这意味着图表中的条形可能会无缘无故地变得非常大。看到这一点的人可能会得出错误的结论,认为某些代码很慢。

所以我的问题是,我该如何处理这种情况?我需要一种方法来始终显示有意义的 CPU 时序。

添加加载统一缓冲区的虚拟代码不是很优雅,并且可能不适用于驱动程序的 future 版本(如果驱动程序只阻塞绘制调用怎么办?)。

glClientWaitSync 同步看起来也不是一件好事,因为如果帧速率下降,驱动程序将停止阻塞以允许 CPU 和 GPU 帧并行运行并且我需要检测到停止调用 glClientWaitSync(但我不确定该怎么做。)

(欢迎提出更好的标题建议。)

编辑:当 GPU 成为瓶颈时,如果没有垂直同步会发生以下情况: GPU Profiler, vysnc off, V2 GPU 帧花费的时间比 CPU 帧长,因此驱动程序决定在 glBufferData 期间阻塞 CPU,直到 GPU catch 。

条件不一样,但问题是:CPU 时序“错误”,因为驱动程序制作了一些 OpenGL 功能 block 。这实际上可能是一个比打开垂直同步的例子更容易理解的例子。

最佳答案

这实际上是按预期工作的。在调用 SwapBuffers (...) 期间,VSYNC 导致的阻塞不一定会发生,VSYNC 导致阻塞的原因有很多,而且它们几乎完全不受您的控制。

当交换链充满等待交换的后备缓冲区(通常只有 1 个后备缓冲区)时,在交换完成之前不得执行会修改帧缓冲区的命令。这会导致流水线停顿,并且是第一次罢工。请记住,即使管道停滞,GL 仍可能在此状态下排队命令。

在大多数平台上,没有允许您明确请求窗口系统交换链中的后台缓冲区数量的 API。您可以请求缓冲,驱动程序可能会将双缓冲解释为 2 或更多(您会看到标记为“启用三重缓冲” 在某些驱动程序中)。

第二击来自所谓的“提前渲染”。这是 GL 在拒绝接受新命令之前将排队的特定于驱动程序的工作量。再次声明,作为 OpenGL 软件的开发者,您对此没有任何控制权。在某些驱动程序中,您可以深入挖掘并手动配置。增加该值将允许 CPU 在管道停滞时排队更多的工作,但往往会增加延迟(特别是 D3D 实现它的方式,它禁止丢帧)。

一旦渲染管道因等待缓冲区交换而停止,并且您用尽了渲染提前限制,那就是三击。调用线程将阻塞下一个 GL 命令,直到 VBLANK 回滚并疏通管道。


glClientWaitSync (...),正如您所描述的,将有效地消除所有提前渲染。这可能是希望最大限度地减少时序变化,但如果您在达到刷新率时遇到困难,则会对整体帧率产生负面影响。

自适应 VSYNC 应该是您追求的第一件事。在支持此功能的驱动程序上,您可以通过设置负交换间隔来启用它,并且当您无法维持刷新率时它会避免阻塞。实际上,自适应 VSYNC 的目的是在您绘制速度过快时限制渲染。如果您的绘图速度快于显示器的处理速度,那么分析 GL API 调用似乎并不特别重要。

在最坏的情况下,您始终可以完全禁用 VSYNC。在引入的现代合成窗口管理器(如 Windows Vista)中,无论是否启用 VSYNC,都可以在窗口模式下防止撕裂。 VSYNC 在那种情况下真的只是节省电力,关闭它以获得更准确的分析可能是一个可以接受的妥协。您可以轻松地实现自己的节流机制,以防止您的引擎以高得离谱的帧速率进行绘制,而不会出现 VSYNC 引入的不可预测的行为。

关于performance - 分析 OpenGL 应用程序 - 当驱动程序阻塞 CPU 端时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28662628/

相关文章:

arrays - 阵列访问/写入性能差异?

performance - Node 的 SDCH 压缩?

Linux 文件和进程级 I/O 性能指标

c++ - 绘制动态几何的正确或最佳方法是什么

opengl - glDrawArrays 如何知道要绘制什么?

c++ - 为什么我的 HUD 未在 OpenGL 中渲染?

performance - 乌龟 Mercurial 慢

c++ - 在 OpenGL 中创建 GUI,可能吗?

opengl - 如何在不停止管道的情况下读取像素深度值?

testing - 在哪里可以获得样本 3d 环境?