【问题标题】:OpenGL and CPU/GPU timer synchronizationOpenGL 和 CPU/GPU 定时器同步
【发布时间】:2015-01-23 15:53:48
【问题描述】:

我正在尝试制作一个用于视频游戏的 CPU 和 GPU 分析器。目标是在屏幕上显示 2 个图表,显示帧的不同任务所花费的时间。这是对其外观的非常粗略的说明:

我使用 QueryPerformanceCounter(在 Windows 上)获取 CPU 时间,使用 glQueryCounter(GL_TIMESTAMP) 获取 GPU 时间。

问题是我得到的 CPU 和 GPU 的时间不是相对于同一个来源。我第一次尝试解决这个问题是在应用程序初始化期间对 GPU 时间戳(使用 glGetInteger64v(GL_TIMESTAMP))进行阻塞调用,紧随其后的是获取 CPU 时间。两次之间的差异使我基本上可以将 GPU 时间转换为 CPU 时间,并使两个图同步。但几秒钟(或几分钟)后,时间开始漂移,我的图表不再正确同步。

在游戏开始后,我无法再进行一次阻塞调用来获取 GPU 时间,因为我不想丢失帧并让游戏卡顿。

有没有人尝试过这样的事情,或者对如何在不影响性能的情况下同步 CPU 和 GPU 时间有任何建议?

我有另一个想法,但我不知道它是否会正常工作:让一个单独的线程进行阻塞调用以获取 GPU 时间,同时获取 CPU 时间并以某种方式将差异发送回主线程。然后线程将休眠几秒钟并重新启动。如果这似乎运作良好,我会尝试并更新帖子。

编辑:我在 AMD 和 NV 卡上都尝试了上面的想法,它似乎工作正常。即使多次调用 glGetInteger64v(GL_TIMESTAMP) (每次调用之间只有 1ms 的睡眠),它似乎对性能没有影响。我仍然需要进行更深入的测试,但到目前为止,这看起来是一个不错的解决方案。

【问题讨论】:

  • 虽然我对你的问题没有答案,但我绝对不会使用“其他想法”的方法:如果你在两个线程中使用相同的上下文,那么该块将停止游戏,就好像您只使用了一个线程。当为每个线程使用单独的上下文时,每当你执行阻塞调用时,驱动程序都会换掉你的渲染上下文,这也会导致你的游戏卡顿。为了完整起见:在我使用过的所有 GPU 上,gpu 和 cpu 之间的时间并没有随着时间的推移而相差太大。在我目前的 nvidia 680 上,它大约是每小时几分之一毫秒。
  • 同步...不影响性能...不太可能 IMO
  • 另一个想法:阻塞 OpenGL 调用的问题是,它们会刷新你的管道并等到这个。在交换缓冲区之后直接同步怎么样,因为这已经刷新了管道?在这种情况下,glGetInteger64v 应该立即返回
  • @BDL “驱动程序将换出你的渲染上下文”是什么意思?时间戳查询是否被视为需要自己的命令缓冲区的绘图调用?这似乎令人惊讶。在这种情况下,在主线程中进行查询并在另一个线程中等待它完成可能会起作用,对吧?为了完整起见:我尝试了 GTX 660,时间每分钟漂移大约一毫秒(大约)。我还尝试了 Radeon HD 7950 和它在同一个范围内(但漂移似乎在另一个方向:o)。你用什么方法来测量 CPU 时间?
  • 我和你一样使用了 QueryPerformanceCounter

标签: opengl


【解决方案1】:

我创建了一个单独的线程来阻塞调用 glGetInteger64v(GL_TIMESTAMP)。即使在每次调用之间等待像 1 毫秒这样愚蠢的小东西时,它的性能也没有明显的差异。虽然需要注意的是,在这个修改之前我已经有几个 OpenGL 上下文了。

在最终代码中,我在每次调用 glGetInteger64v(GL_TIMESTAMP) 之间等待 30 秒。这似乎足以避免在我测试的所有 PC 上出现任何明显的漂移。

我在 Nvidia 显卡(GTX 460、GTX 660、GTX 780ti、GTX 780M)和 AMD(Radeon HD 7950)上进行了测试,所有显卡均采用 Intel CPU。

【讨论】:

    猜你喜欢
    • 2018-10-17
    • 1970-01-01
    • 1970-01-01
    • 2018-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-11
    相关资源
    最近更新 更多