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

Ste*_*nas 5 windows directx winapi direct3d

根据微软这篇文章,用户设置的屏幕刷新率可以是(并且大部分)是一个小数.用户设置59Hz,但屏幕按60Hz的屏幕显示运行,但实际上它是59.94Hz.我非常流畅的动画需要的是59.94Hz.

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

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

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

Moo*_*oys 10

如果您的目标是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
Run Code Online (Sandbox Code Playgroud)

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

祝好运!

  • 我不想要自己的时间安排。我只想预测我现在生成的帧将显示的确切时间戳,因为这会影响我需要绘制的内容。由于我使用 DirectX9,我不确定是否可以使用 DXGI 功能。但据我所知,返回值是一个有理数,希望足够准确。 (2认同)