DXGI フリップ モデル
Windows 8は、DXGI 1.2 でフリップ プレゼンテーション モデルとそれに関連する現在の統計のサポートを追加します。 Windows 8の DXGI フリップ プレゼンテーション モデルは、Windows 7 の Direct3D 9EX フリップ モード プレゼンテーションに似ています。 ゲームなどのビデオまたはフレーム レートベースのプレゼンテーション アプリは、フリップ プレゼンテーション モデルを使用することで最も役立ちます。 DXGI フリップ プレゼンテーション モデルを使用するアプリは、システム リソースの負荷を軽減し、パフォーマンスを向上させます。 アプリでは、リアルタイムのフィードバックと修正メカニズムを提供することで、プレゼンテーションの速度をより適切に制御するために、フリップ プレゼンテーション モデルで現在の統計の機能強化を使用することもできます。
DXGI フリップ モデルと BitBlt モデルの比較
ランタイムは、ビット ブロック転送 (bitblt) とフリップ プレゼンテーション モデルを使用して、ディスプレイ モニターにグラフィックス コンテンツを表示します。 bitblt プレゼンテーション モデルとフリップ プレゼンテーション モデルの最大の違いは、バックバッファーコンテンツが合成のためにWindows 8 DWM に到達する方法です。 bitblt モデルでは、 IDXGISwapChain1::P resent1 を呼び出すたびに、バック バッファーの内容がリダイレクトサーフェイスにコピーされます。 フリップ モデルでは、すべてのバック バッファーがデスクトップ ウィンドウ マネージャー (DWM) と共有されます。 したがって、DWM は、追加のコピー操作を行わずに、それらのバック バッファーから直接作成できます。 一般に、フリップ モデルの方が効率的です。 また、フリップ モデルには、現在の統計情報の拡張など、より多くの機能も用意されています。
WINDOWS グラフィックス デバイス インターフェイス (GDI) を使用して HWND に直接書き込むレガシ コンポーネントがある場合は、ビットレット モデルを使用します。
DXGI フリップ モデルのパフォーマンスの向上は、アプリがウィンドウ モードの場合に重要です。 この表のシーケンスと図は、メモリ帯域幅の使用量と、ビットモデルと反転モデルを選択するウィンドウアプリのシステム読み取りと書き込みを比較したものです。
手順 | DWM に存在する BitBlt モデル | DWM に存在する DXGI フリップ モデル |
---|---|---|
1. | アプリはフレームを更新します (書き込み) |
アプリはフレームを更新します (書き込み) |
2. | Direct3D ランタイムは、サーフェスの内容を DWM リダイレクト サーフェイスにコピーします (読み取り、書き込み) |
Direct3D ランタイムがアプリ サーフェイスを DWM に渡す |
3. | 共有サーフェスのコピーが完了すると、DWM によってアプリ画面が画面にレンダリングされます (読み取り、書き込み) |
DWM によってアプリ画面が画面にレンダリングされます (読み取り、書き込み) |
フリップ モデルでは、DWM によるウィンドウ フレーム構成の Direct3D ランタイムによる読み取りと書き込みの数を減らすことで、システム メモリの使用量が削減されます。
DXGI フリップ モデルの使用方法
Windows 8を対象とする Direct3D 11.1 アプリでは、DXGI_SWAP_CHAIN_DESC1構造体のSwapEffect メンバーにDXGI_SWAP_EFFECT_FLIP_SEQUENTIAL列挙値が設定されたスワップ チェーンを作成することで、反転モデルを使用します。 SwapEffect を DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL に設定する場合は、DXGI_SWAP_CHAIN_DESC1のこれらのメンバーも指定された値に設定します。
- BufferCount を 2 ~ 16 の値に設定すると、DWM で前のプレゼンテーション バッファーが解放されるのを待機した結果、パフォーマンスが低下するのを防ぐことができます。
- DXGI_FORMAT_R16G16B16A16_FLOAT 、DXGI_FORMAT_B8G8R8A8_UNORM、またはDXGI_FORMAT_R8G8B8A8_UNORMに書式設定する
- SampleDesc メンバーが 1 に指定し、複数のサンプルアンチエイリアシング (MSAA) がサポートされていないため、DXGI_SAMPLE_DESCの Quality メンバーを 0 に指定するDXGI_SAMPLE_DESC構造体の Count メンバー
Windows 7 以前のオペレーティング システムで DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL を使用する場合、デバイスの作成は失敗します。 フリップ モデルを使用する場合は、全画面表示の表示統計をウィンドウ モードで使用できます。 全画面表示の動作は影響を受けません。 ウィンドウスワップ チェーンの IDXGIFactory2::CreateSwapChainForHwnd の pFullscreenDesc パラメーターに NULL を渡し、SwapEffect をDXGI_SWAP_EFFECT_FLIP_SEQUENTIALに設定すると、ランタイムは追加のバック バッファーを 1 つ作成し、プレゼンテーション時にフロント バッファーになるバッファーに属するハンドルを回転させます。
フリップ モデルを使用する場合は、次のヒントを考慮してください。
- HWND ごとに 1 つのフリップ モデル スワップ チェーンを使用します。 複数のフリップ モデル スワップ チェーンを同じ HWND にターゲットにしないでください。
- GDI の ScrollWindow 関数または ScrollWindowEx 関数では、フリップ モデルスワップ チェーン を 使用しないでください。 一部の Direct3D アプリでは、GDI の ScrollWindow 関数と ScrollWindowEx 関数を使用して、ユーザーのスクロール イベントが発生した後にウィンドウの内容を更新します。 ScrollWindow と ScrollWindowEx は、ユーザーがウィンドウをスクロールすると、画面にウィンドウの内容のビットレットを実行します。 これらの関数には、GDI および Direct3D コンテンツのビットレット モデルの更新も必要です。 いずれかの関数を使用するアプリでは、アプリがウィンドウ モードのときに画面にスクロールするウィンドウの内容が必ずしも表示されるとは限りません。 GDI の ScrollWindow 関数と ScrollWindowEx 関数を使用せず、スクロールに応じて GDI と Direct3D の内容を画面上で再描画することをお勧めします。
- DXGI ビットレット プレゼンテーション モデル、Direct3D の他のバージョン、GDI など、他の API の対象にもなっていない HWND でフリップ モデルを使用します。 bitblt モデルではサーフェスの追加のコピーが保持されるため、Direct3D と GDI からの段階的な更新を通じて、GDI やその他の Direct3D コンテンツを同じ HWND に追加できます。 フリップ モデルを使用すると、ランタイムが DWM に渡すフリップ モデル スワップ チェーン内の Direct3D コンテンツのみが表示されます。 ランタイムは、他のすべてのビットモデル Direct3D または GDI コンテンツの更新を無視します。
DXGI フリップ モデル アプリのフレーム同期
現在の統計情報は、メディア アプリがビデオストリームとオーディオストリームを同期し、ビデオ再生の不具合から回復するために使用するフレームタイミング情報です。 アプリでは、現在の統計情報のフレーム タイミング情報を使用して、ビデオ フレームのプレゼンテーション速度を調整して、よりスムーズなプレゼンテーションを行うことができます。 現在の統計情報を取得するには、 IDXGISwapChain::GetFrameStatistics メソッドを呼び出して 、DXGI_FRAME_STATISTICS 構造体を取得します。 DXGI_FRAME_STATISTICS には、 IDXGISwapChain1::P resent1 呼び出しに関する統計情報が含まれています。 フリップ モデル スワップ チェーンは、ウィンドウモードと全画面表示モードの両方で、現在の統計情報を提供します。 ウィンドウ モードの bitblt モデル スワップ チェーンの場合、 すべてのDXGI_FRAME_STATISTICS 値は 0 です。
フリップ モデルの存在統計の場合、 IDXGISwapChain::GetFrameStatistics は次の状況で DXGI_ERROR_FRAME_STATISTICS_DISJOINT を返します。
- シーケンスの先頭を示す GetFrameStatistics の最初の呼び出し
- モードの変更: 全画面表示または全画面表示から全画面表示への切り替えのいずれかのウィンドウ モード
DXGI_FRAME_STATISTICSの PresentRefreshCount、SyncRefreshCount、および SyncQPCTime メンバーの値には、次の特性があります。
- PresentRefreshCount は、アプリがすべての vsync に表示される場合、 SyncRefreshCount と同じです。
- SyncRefreshCount は、存在が送信された vsync 間隔で取得されます。 SyncQPCTime は、vsync 間隔に関連付けられたおおよその時間です。
IDXGISwapChain::GetLastPresentCount メソッドは、スワップ チェーンに関連付けられているディスプレイ デバイスによって最後に成功した IDXGISwapChain1::P resent1 呼び出しの現在の ID を返します。 この現在の ID は、DXGI_FRAME_STATISTICS構造体の PresentCount メンバーの値です。 bitblt モデルスワップ チェーンの場合、ウィンドウ モードでは、 すべてのDXGI_FRAME_STATISTICS 値は 0 です。
グリッチの回避、検出、回復
フレームプレゼンテーションの不具合を回避、検出、回復するには、次の手順を実行します。
キュー IDXGISwapChain1::P resent1 呼び出し (つまり、 IDXGISwapChain1::P resent1 を複数回呼び出すと、キューで収集されます)。
present-queue 構造体を作成して、正常に送信されたすべての IDXGISwapChain1::P resent1 の現在の ID ( IDXGISwapChain::GetLastPresentCount によって返されます) と、関連する計算値または予想される PresentRefreshCount 値を格納します。
不具合を検出するには:
- IDXGISwapChain::GetFrameStatistics を呼び出します。
- このフレームでは、オペレーティング システムが最後のイメージをモニターに提示した現在の ID (PresentCount) と vsync 数を取得します (PresentRefreshCount)。
- 現在の ID に関連付けられている、および以前に present-queue 構造体に格納した、予期される PresentRefreshCount を取得します。
- 実際の PresentRefreshCount が予想される PresentRefreshCount より後の場合は、不具合が発生しました。
グリッチから回復するには:
グリッチから回復するためにスキップするフレームの数を計算します。 たとえば、手順 3 で、現在の ID (PresentCount) に予想される vsync カウント (PresentRefreshCount) が 5 で、現在の ID の実際の vsync カウントが 8 である場合、グリッチから回復するためにスキップするフレームの数は 3 フレームです。
この数の IDXGISwapChain1::P resent1 の呼び出しで SyncInterval パラメーターに 0 を渡して、このフレーム数を破棄してスキップします。
Note
グリッチが多数のフレームで構成されている場合は、 IDXGISwapChain1::P resent1 を呼び出し、 Flags パラメーターを DXGI_PRESENT_RESTART に設定して、キューに登録されているすべての未処理のプレゼンテーションを破棄してスキップします。
フレームプレゼンテーションの不具合から回復するシナリオの例を次に示します。
この例のシナリオでは、vsync カウントが 1 のフレーム A が画面に表示されます。 しかし、実際には、フレーム A が画面に 4 として表示される vsync 数を検出します。 そのため、不具合が発生したと判断します。 その後、3 つのフレームを破棄できます。つまり、IDXGISwapChain1::P resent1 への 3 つの呼び出しで、SyncInterval パラメーターに 0 を渡すことができます。 上記のシナリオ例では、グリッチから復旧するには、合計 8 個の IDXGISwapChain1::P resent1 呼び出しが必要です。 その後、9 番目のフレームは、予想される vsync 数に従って表示されます。
プレゼンテーション イベントのタイム ラインを次に示します。 各垂直線は vsync を表します。 水平方向は時間であり、右側に増加します。 図を使用して、グリッチがどのように発生するかを想像できます。
この図は、次のシーケンスを示しています。
アプリは vsync で起動し、青色をレンダリングし、 IDXGISwapChain1::P resent1 を呼び出してスリープ状態に戻ります。
グラフィックス処理装置 (GPU) はアイドル状態から復帰し、青色にレンダリングを実行してからスリープ状態に戻ります。
DWM は次の vsync で起動し、そのバック バッファーに青を構成し、 IDXGISwapChain1::P resent1 を呼び出してスリープ状態に戻ります。
アプリが起動し、緑色にレンダリングされ、 IDXGISwapChain1::P resent1 が呼び出され、スリープ状態に戻ります。
Note
GPU が青の作成を実行している間、アプリは同時に実行されます。
次に、アプリの GPU が緑色でレンダリングされます。
最後に、デジタルアナログコンバータ(DAC)は、次のvsync上のモニタ上のDWMコンポジションの結果を示します。
タイム ラインから、現在の統計の待機時間と、異常が発生する方法を想像できます。 たとえば、画面に表示される緑色の DWM グリッチを表示するには、緑/赤のボックスの右側が紫色/赤のボックスの右側に一致するように、緑/赤のボックスを広げることを想像してください。 このシナリオでは、DAC には青の 2 つのフレームと緑のフレームが表示されます。 現在の統計を読み取ると、この不具合が発生したことがわかります。
関連トピック