7

Microsoft のこの記事によると、ユーザーが設定した画面のリフレッシュ レートは分数である可能性があります (ほとんどの場合)。ユーザーは 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

いずれにせよ、トリプル バッファを使用している場合、グリッチは発生しません。OS は時間通りに表示されます。トリプル バッファリングをカスタム マネージド フレーム タイミングと組み合わせると、実際にはトリプル バッファリングが得られないことが保証され、vblank フェーズにドリフトがあるたびにグリッチが発生します (これは、完全な値を持っている場合でも徐々に発生します)。リフレッシュレート)。トリプル バッファリングに固執したい場合は、できるだけ早くプレゼンテーションを行い、OS にプレゼンテーションのタイミングを任せてください。独自のタイミングを使用して Present() を駆動している場合 (たとえば、待機時間の短い応答を取得するため)、別のスレッドでIDXGIOutput::WaitForVBlankへの呼び出しをスローして、フレーム タイミングの同期を支援する必要があります。最終的にそれを行う場合は、次も使用する必要がありますIDXGISwapChain::GetFrameStatisticsを使用して、誤ったグリッチから確実に回復できるようにします。そうしないと、1 フレーム遅れてしまいます。

幸運を!

于 2013-09-19T18:11:45.037 に答える