I am porting my code to D3D12 from D3D11 and I'm trying to obtain display's refresh rate on D3D12. I use the refresh rate for precise animation timing (this is a hard requirement). This code works on D3D11:
HRESULT GetRefreshRate(IUnknown* device, IDXGISwapChain* swapChain, double* outRefreshRate)
{
Microsoft::WRL::ComPtr<IDXGIOutput> dxgiOutput;
HRESULT hr = swapChain->GetContainingOutput(&dxgiOutput);
if (FAILED(hr))
return hr;
Microsoft::WRL::ComPtr<IDXGIOutput1> dxgiOutput1;
hr = dxgiOutput.As(&dxgiOutput1);
if (FAILED(hr))
return hr;
DXGI_MODE_DESC1 emptyMode = {};
DXGI_MODE_DESC1 modeDescription;
hr = dxgiOutput1->FindClosestMatchingMode1(&emptyMode, &modeDescription, device);
if (SUCCEEDED(hr))
*outRefreshRate = (double)modeDescription.RefreshRate.Numerator / (double)modeDescription.RefreshRate.Denominator;
return hr;
}
Unfortunately, ID3D12Device does not implement IDXGIDevice interface, and FindClosestMatchingMode1 therefore fails with this error:
DXGI ERROR: IDXGIOutput::FindClosestMatchingMode: pConcernedDevice doesn't support the IDXGIDevice interface [ MISCELLANEOUS ERROR #69: ]
Is there a way to obtain IDXGIDevice when using D3D12? Alternatively, how do I determine display's refresh rate on D3D12?
I know about EnumDisplaySettings
however it returns an integer and therefore lacks precision, causing drift in animations. I also found DwmGetCompositionTimingInfo
, however, it seems to only support getting info for the main monitor.
I also need a solution that would work on both traditional Win32 and UWP applications. I am open to having to use two code paths for different application models if needed.
IDXGISwapChain->GetDesc()
, then you will get RefreshRate atDXGI_SWAP_CHAIN_DESC -> DXGI_MODE_DESC -> RefreshRate
. – Fructidor