7

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

使用IDirect3DDevice9::GetDisplayMode我只得到一个int值,根据定义,它不能代表实际时间(对于EnumDisplaySettings也是如此)。我每秒都会遇到明显的卡顿,因为它报告了舍入/截断的 59。如果我手动将我的应用程序中报告的时间更正为 59.94,它运行平稳。

有人知道我如何检索真实的屏幕刷新率吗?

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

4

1 回答 1

13

如果您的目标是 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以确保您从任何虚假故障中恢复,否则您最终会落后一帧。

祝你好运!

于 2013-09-19T18:11:45.037 回答