スワップ チェーンはバック バッファーの回転を制御し、グラフィックス アニメーションの基礎を形成します。
概要
Direct3D 12 のスワップ チェーンのプログラミング モデルは、以前のバージョンの D3D と同じではありません。 たとえば、D3D10 および D3D11 に存在していた自動リソース ローテーションをサポートするプログラミングの利便性はサポートされなくなりました。 リソースの自動ローテーションにより、アプリは同じ API オブジェクトをレンダリングできるようになりましたが、レンダリングされる実際のサーフェスは各フレームを変更します。 Direct3D 12 ではスワップ チェーンの動作が変更され、Direct3D 12 の他の機能の CPU オーバーヘッドが少なくなっています。 自動カラーキーとマルチサンプリングはサポートされていませんが、なお、拡大/縮小と回転は引き続きサポートされています。
バッファーの有効期間
アプリは、バック バッファーを参照する事前に作成された記述子を格納できます。 これは、スワップ チェーンが所有するバッファーのセットがスワップ チェーンの有効期間中変更されないようにすることで有効になります。 IDXGISwapChain::GetBuffer によって返されるバッファーのセットは、特定の API が呼び出されるまで変更されません。
GetBuffer によって返されるバッファーの順序 変更されません。
IDXGISwapChain3::GetCurrentBackBufferIndex は、現在のバック バッファーのインデックスをアプリに返します。
スワップ効果
サポートされているスワップ効果は DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL と DXGI_SWAP_EFFECT_FLIP_DISCARDのみです。バッファー数は 1 より大きい必要があります。
Tip
最小入力待機時間をターゲットとするゲームの場合は、 DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARINGでスワップ チェーンを作成し、 Present(0, DXGI_PRESENT_ALLOW_TEARING)を呼び出します。 これにより、コンポジターの vsync がバイパスされ、現在から表示までの待機時間が最も短くなります。 実行時に、この方法を使用する前に、DXGI_FEATURE_PRESENT_ALLOW_TEARING を指定して IDXGIFactory5::CheckFeatureSupport を呼び出し、ティアリングのサポートを確認してください。
Warning
フレーム ペーシングの一般的なバグは、CPU の作業を GPU フェンスと適切に同期せずに Present(1, 0) (vsync-on) を呼び出すことです。 これにより、CPU が先に実行され、入力待ち時間が長くなるフレーム キューが構築されます。 フレームカウント フェンスを常に使用して、実行中の CPU フレームを制限します (通常はバッファー数から 1 を引いた値)。
ウィンドウ モードと全画面表示モードの切り替え
Direct3D 12 では、全画面表示排他モード (FSE) はサポートされていません。 代わりに、ゲームが画面上で唯一目に見えるアプリケーションである場合、OS は全画面最適化 (FSO) と呼ばれる戦略を使用して、パフォーマンス上の欠点なしに FSE と同様の効果を実現します。 FSO の詳細については、「全画面表示最適化を説明する」を参照してください。
Direct3D 12 では、ウィンドウモードと全画面表示モードの切り替え後に、アプリケーションで ResizeBuffers を呼び出す必要がある制限が維持されます (D3D11 フリップ モデル スワップ チェーンには同じ制限があります)。
IDXGISwapChain::SetFullscreenState 遷移では、スワップ チェーン内のアプリに表示されるバッファーのセットは変更されません。 ResizeBuffers および ResizeTarget 呼び出しのみが、アプリから参照できるバッファーを作成または破棄します。 ただし、Direct3D 12 IDXGISwapChain::SetFullscreenState は全画面表示排他モードに入りません。解像度とリフレッシュ レートを変更するだけで、全画面表示の最適化が可能になります。 これらの変更は、このメソッドを使用せずにアプリによって行うことができます
IDXGISwapChain::Present または IDXGISwapChain1::Present が呼び出されるときは、提示するバック バッファは D3D12_RESOURCE_STATE_PRESENT 状態である必要があります。 これに当てはまらない場合、Present は DXGI_ERROR_INVALID_CALL を返して失敗します。
全画面表示のスワップ チェーンでは、スワップ チェーンの最終リリース前に SetFullscreenState(FALSE、NULL)呼び出す必要があるという制限が引き続き適用されます。 SetFullscreenState(FALSE) は、Direct3D 12 デバイスで実行されているスワップ チェーンで成功します。
現在の操作はスワップチェーンの作成時に提供される 3D キューで実行され、アプリは複数のスワップ チェーンを同時に表示したり、コマンド リストを記録および実行したりすることができます。
グラフィックス作業の最後の部分 (フレームの後処理など) がコンピューティング キューで行われる場合や、デバイスのグラフィックス キューが含まれていない場合は、表示する 2 番目の 3D キューを作成すると役に立ち、プレゼンテーションの待ち時間が次のフレームの開始を遅らせるのを防ぐことができます。
例
次のコード例は、メイン レンダリング ループに存在します。
Warning
次の例は、わかりやすくするために簡略化されています。 実稼働ゲーム ループでは、シミュレーションの更新をレンダリング頻度から切り離し (たとえば、できるだけ速くレンダリングしながらシミュレーションに 固定されたタイムステップ を使用するなど)、フェンスを使用して処理中のフレームを制限する必要があります。 フレーム フライト制限がないと、Present はフリップ モデルスワップ チェーンですぐに成功し、CPU が無制限にフレームをキューに入れ、入力待機時間を膨らませることができます。
void Present()
{
m_swapChain->Present(0, m_presentFlags);
m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount;
}
スワップ チェーンの作成
CreateSwapChainForHwnd、CreateSwapChainForCoreWindow、または CreateSwapChainForComposition呼び出しを使用する場合、pDevice パラメーターには、デバイスではなく Direct3D 12 のダイレクト コマンド キューへのポインターが実際に必要であることに注意してください。
Windows 7 でのプレゼンテーション
Windows 7 で Direct3D 12 を対象とする場合、Direct3D 12 に必要な DXGI の種類は存在しないため、D3D12On7 提供 ID3D12CommandQueueDownLevel (ダイレクト コマンド キューからクエリ) を使用して表示する必要があります。
オープン コマンド リストを Windows 7 の Present メソッドに渡すと、そのコマンド リストは使用された後に閉じられ、自動的にデバイスに送信されます。 アプリで作成する必要があり、コミットされたリソースである必要があり、単一サンプリングである必要があり、次のいずれかの形式である必要があるバック バッファーを指定する必要があります。
- DXGI_FORMAT_R16G16B16A16_FLOAT
- DXGI_FORMAT_R10G10B10A2_UNORM
- DXGI_FORMAT_R8G8B8A8_UNORM
- DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
- DXGI_FORMAT_B8G8R8X8_UNORM
- DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM
- DXGI_FORMAT_B8G8R8A8_UNORM
- DXGI_FORMAT_B8G8R8A8_UNORM_SRGB