如何找出真正的屏幕刷新率(不是舍入的数字)

时间:2013-09-17 08:14:48

标签: windows winapi directx direct3d

根据this article by Microsoft,用户设置的屏幕刷新率可以是(并且大部分)是小数。用户设置59Hz,但屏幕按60Hz的屏幕显示运行,但实际上它是59.94Hz。我非常流畅的动画需要的是59.94Hz。

使用IDirect3DDevice9::GetDisplayMode我只得到一个 int 值,根据定义,它不能代表实际时间(EnumDisplaySettings也是如此)。我遇到一个关于每一秒的明显口吃,因为它报告圆形/截断59.如果我手动将我的应用程序中报告的时间校正到59.94,它会顺利运行。

有谁知道我如何检索真正的屏幕刷新率?

我目前的解决方法是将60Hz和59Hz都映射到恒定的59.94Hz,但这并不令人满意。

1 个答案:

答案 0 :(得分:9)

如果您的目标是Windows Vista或更高版本,答案取决于您的应用运行的模式。

如果是窗口应用程序(或全窗口窗口),则根据用户设置和其他因素通过桌面窗口管理器(DWM)控制刷新率。使用DwmGetCompositionTimingInfo并查看DWM_TIMING_INFO :: rateRefresh以获取显示器刷新率。

如果应用程序全屏为真,则您创建的全屏交换链将覆盖系统默认值。但是,您选择的刷新率(DXGI_SWAP_CHAIN_FULLSCREEN_DESC :: RefreshRate)应与监视器支持的刷新率之一匹配。您可以使用IDXGIOutput::GetDisplayModeList获取支持的刷新率列表。以下是如何执行此操作的示例:

UINT numModes = 0;
dxgiOutput->GetDisplayModeList(DXGI_FORMAT_B8G8R8A8_UNORM, 0, &numModes, NULL);
DXGI_MODE_DESC* modes = new DXGI_MODE_DESC[numModes];
dxgiOutput->GetDisplayModeList(DXGI_FORMAT_B8G8R8A8_UNORM, 0, &numModes, modes);
// see modes[i].RefreshRate

在任何情况下,如果你是三重缓冲,你不应该看到故障。您应该尽可能快地出现,操作系统将按时出现。如果你将三重缓冲与自定义管理帧定时相结合,你可以保证不会实际获得三重缓冲,并且你会在vblank阶段出现任何漂移时出现故障(即使你有一个完美的值,它也会逐渐发生)刷新率)。如果你想坚持三重缓冲,只要尽可能快地出现,让操作系统负责演示时间。如果您使用自己的计时来驱动Present()(例如,获得低延迟响应),则应该在另一个线程上调用IDXGIOutput::WaitForVBlank来帮助同步帧时序。如果你最终这样做,你也应该使用IDXGISwapChain::GetFrameStatistics来确保你从任何虚假故障中恢复过来,否则你将会落后一帧。

祝你好运!