According to this article by Microsoft the screen refresh rate set by the user can be (and is mostly) a fractional number. The user sets 59Hz but the screen runs according to the on screen display at 60Hz, but in reality it's 59.94Hz. What I need for a extremely smooth animation is the 59.94Hz.
Using IDirect3DDevice9::GetDisplayMode I only get an int value which cannot by definition represent the real timing (same goes for EnumDisplaySettings). I encounter a visible stutter about every second because it reports the rounded/truncated 59. If I manually correct the reported timing in my application to 59.94 it runs smooth.
Anybody knows how I can retrieve the real screen refresh rate?
My current workaround is mapping 60Hz and 59Hz both to constant 59.94Hz but that's not satisfying.
I know of two ways of getting the screen refresh rate on Windows. The first is the simple EnumDisplaySettings function, which fills a struct that contains a rounded screen refresh rate value in fps.
There is no reason you cannot use DX to get the more precise refresh rate if you want, DX has been an Operating System component since Win95 OSR2 (which is incidentally when OpenGL was introduced as well). Getting the refresh rate is going to be platform-specific no matter how you look at it, so use whatever tools your platform offers.
Although the perception of a screen with a high refresh rate is quite high, we realize just manipulating the interface of the terminal, it is true that we do not always have the certainty that the phone is working at the refresh rate promised by the manufacturer or that we have chosen in the terminal settings themselves.
You can get the list of supported refresh rates using IDXGIOutput::GetDisplayModeList. Here's an example of how to do so: In any case, you shouldn't see glitching if you're triple-buffered. You should just present as fast as you can and the OS will present on time.
If you are targeting Windows Vista or later, the answer depends on the mode in which your app is running.
If it is a windowed app (or windowed full-screen), refresh rate is controlled via the Desktop Window Manager (DWM) according to user settings and other factors. Use DwmGetCompositionTimingInfo and look at DWM_TIMING_INFO::rateRefresh to get the monitor refresh rate.
If the app is true full-screen, then the full-screen swap chain you create overrides the system default. However, your selected refresh rate (DXGI_SWAP_CHAIN_FULLSCREEN_DESC::RefreshRate) should match one of the monitor-supported refresh rates. You can get the list of supported refresh rates using IDXGIOutput::GetDisplayModeList. Here's an example of how to do so:
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
In any case, you shouldn't see glitching if you're triple-buffered. You should just present as fast as you can and the OS will present on time. If you combine triple-buffering with custom managed frame timing, you're guaranteed to not actually get triple-buffering, and you'll get glitches any time there's drift in the vblank phase (which happens gradually even if you have a perfect value for refresh rate). If you want to stick with triple-buffering, just present as fast as you can and let the OS take care of presentation timing. If you're using your own timing to drive Present()s (for example, to get low-latency response), you should throw in a call to IDXGIOutput::WaitForVBlank on another thread to help synchronize frame timings. If you end up doing that, you should also use IDXGISwapChain::GetFrameStatistics to make sure you recover from any spurious glitches, otherwise you'll end up a frame behind.
Good luck!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With