windows - 如何找出实际屏幕刷新率(不是四舍五入的数字)

标签 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,但这并不令人满意。

最佳答案

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

祝你好运!

关于windows - 如何找出实际屏幕刷新率(不是四舍五入的数字),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18844654/

相关文章:

file - 带有 CreateFile() WinAPI 的本地驱动器的 Windows 文件和路径名

c++ - Win32 LoadBitmap 返回错误 1814

c++ - 3d 空间中两个 vector 之间的角度

directx - 如何判断系统DirectX是11还是11.1?

c++ - "Access violation reading location"从 directx 检索缓冲区时遇到问题

windows - Windows 中的 cmake 问题

python - 以编程方式发送键盘中断

windows - 使用Electron时,MongoDb连接的初始化和查询非常慢

windows - 通用 Windows 平台上的 Mono.data.sqlite

c++ - 为什么我的 WinAPI 上下文(弹出)菜单没有出现?