等待VBLANK以窗口模式出现在Windows 10上的正确方法是什么?目前,我正在执行以下操作:
D3DKMTWaitForVerticalBlankEvent(&waitData);
swapchain->Present(0, 0);
但是,这会导致偶尔的断断续续。我目前关于口吃的理论如下:
DWM在VBLANK事件之前的某个时候完成合成,然后在VBLANK间隔期间,DWM尝试尽可能快地写入前端缓冲区。因此,如果在VBLANK间隔中调用
Present
,则可能在DWM已写入前端缓冲区之后发生。这是我脑海中的照片:因此,更正确的方法是在VBLANK之前调用
Present(1, 0)
,以将窗口的后台缓冲区与DWM排队。然后调用D3DKMTWaitForVerticalBlankEvent
等待下一个VBLANK。那是:swapchain->Present(1, 0);
D3DKMTWaitForVerticalBlankEvent(&waitData);
带有相应的图片:
第二种方法似乎完美地工作,不再有结结巴巴的情况。
我的问题是:
在VBLANK间隔中呈现的正确方法是什么?
我的理论是正确的还是发生了更复杂/更简单的事情?
还有没有资源可以了解有关此交互作用的更多信息?
可能有用的链接:
MSDN
Present
DXGI Best Practices
DXGI Waitable Swap Chain
D3DKMTWaitForVerticalBlankEvent
编辑:
不知道这应该是答案还是编辑。
经过一番谷歌搜索后,我发现this explanation by Nicholas Steel似乎与我的理论相符
因此,最好的办法是:
if (DWM.isEnabled())
{
present();
DwmFlush();
}
else
{
waitForVBlank();
present();
}
另一个编辑:
对于将来的读者,还有其他两种等待VBLANK的方式,我不知道它们是
IDXGIOutput::WaitForVBlank
和IDirectDraw7::WaitForVerticalBlank
(后者已弃用)。 最佳答案
您为什么要在窗口模式下等待VBLANK? DWM将确保复合表面在VBLANK区域内翻转。
当您说“DWM在VBLANK事件之前的某个时间完成合成”时,什么使DWM启动合成?在出现任何应用程序或焦点应用程序之后,都不会发生这种情况。 VBLANK发生时实际上开始合成。它可能会完成并翻转VBLANK中的合成表面,或者可能最终实际上翻转了下一个VBLANK(因此您可能会在等待时间中得到额外的帧持续时间)。不过,这不在您的控制范围内-它取决于编写的持续时间,而不取决于应用程序的当前状态。
在带窗口的应用程序中,当您调用present时,它只会翻转应用程序的交换链-不会翻转显示的表面。 DWM将处理该问题。因此,“只要合成器处于 Activity 状态,您就不必再担心自己轮询VBlank了。”
但是,使用DwmFlush()来实现“在每个VBlank周期之间最多将1个新的视频帧呈现给合成器”并不是必须的。除非您确实只想在每个监视器周期显示1帧,否则您可以这样做(尽管我不确定DwmFlush()是否是最优雅的方法)。但是在大多数情况下,我认为强制执行该限制是不可取的。
关于winapi - 在窗口模式下在Windows 10上等待VBLANK的正确方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49244480/