5

我刚刚阅读了 DirectX 文档,并在IDirect3DDevice9::BeginScene的页面中遇到了一些有趣的事情:

为了在 CPU 和图形加速器之间实现最大并行性,在 调用 present 之前尽可能早地调用IDirect3DDevice9::EndScene是有利的。

我已经习惯于编写我的游戏循环来处理输入等,然后绘制。我是不是倒过来了?也许游戏循环应该更像这样:(显然是半伪代码)

while(running) {
    d3ddev->Clear(...);
    d3ddev->BeginScene();
    // draw things
    d3ddev->EndScene();

    // handle input
    // do any other processing
    // play sounds, etc.

    d3ddev->Present(NULL, NULL, NULL, NULL);
}

根据文档的那句话,这个循环将“启用最大并行性”。

这通常是这样做的吗?像这样订购游戏循环有什么缺点吗?在第一次迭代后,我认为它没有真正的问题......而且我知道了解此类事情的实际速度增加的最佳方法是对其进行实际基准测试,但有其他人已经尝试过这个并且你能证明任何实际的速度提升?

4

3 回答 3

2

值得注意的是,几乎所有 PC 硬件 BeginScene 和 EndScene 什么都不做。事实上,驱动程序会缓冲所有绘制命令,然后当您调用 present 时,它甚至可能不会开始绘制。它们通常缓冲几帧绘制命令以平滑帧速率。通常,驱动程序会根据当前调用来做事。

当帧速率不是特别高时,这可能会导致输入延迟。

我敢打赌,如果您在当前之前立即进行渲染,您会注意到上面给出的循环没有任何区别。当然,在一些奇怪的硬件上,这可能会导致问题,所以一般来说,你最好按照上面的建议进行循环。

于 2010-05-03T08:23:24.350 回答
2

简短的回答是肯定的,这就是通常的做法。看看下面关于 PS3 战神 III 游戏循环的演示:

http://www.tilander.org/aurora/comp/gdc2009_Tilander_Filippov_SPU.pdf

如果您以 30 fps 的速度运行双缓冲游戏,则输入延迟将为 1 / 30 ~= 0.033 秒,这对于人类来说太小了(相比之下,100 米上任何低于 0.1 秒的反应时间都是被认为是一个错误的开始)。

于 2010-05-03T05:14:14.753 回答
2

因为我一直觉得在模拟前绘制很“尴尬”,所以我倾向于将抽奖推迟到更新之后,也包括在“现在”调用之后。例如

while True:
   Simulate()
   FlipBuffers()
   Render()

虽然在第一帧你什么都没有翻转(你需要设置一些东西,以便第一次翻转确实翻转到一个已知状态),这总是让我觉得比把 Render() 先好一点,即使一旦你开始,操作的顺序是相同的。

于 2010-05-03T19:44:54.870 回答