スワップ チェーン

スワップ チェーンはバック バッファーの回転を制御し、グラフィックス アニメーションの基礎を形成します。

概要

Direct3D 12 のスワップ チェーンのプログラミング モデルは、以前のバージョンの D3D と同じではありません。 たとえば、D3D10 および D3D11 に存在していた自動リソース ローテーションをサポートするプログラミングの利便性はサポートされなくなりました。 リソースの自動ローテーションにより、アプリは同じ API オブジェクトをレンダリングできるようになりましたが、レンダリングされる実際のサーフェスは各フレームを変更します。 Direct3D 12 ではスワップ チェーンの動作が変更され、Direct3D 12 の他の機能の CPU オーバーヘッドが少なくなっています。 自動カラーキーとマルチサンプリングはサポートされていませんが、なお、拡大/縮小と回転は引き続きサポートされています。

バッファーの有効期間

アプリは、バック バッファーを参照する事前に作成された記述子を格納できます。 これは、スワップ チェーンが所有するバッファーのセットがスワップ チェーンの有効期間中変更されないようにすることで有効になります。 IDXGISwapChain::GetBuffer によって返されるバッファーのセットは、特定の API が呼び出されるまで変更されません。

GetBuffer によって返されるバッファーの順序 変更されません。

IDXGISwapChain3::GetCurrentBackBufferIndex は、現在のバック バッファーのインデックスをアプリに返します。

スワップ効果

サポートされているスワップ効果は DXGI_SWAP_EFFECT_FLIP_SEQUENTIALDXGI_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;
}

スワップ チェーンの作成

CreateSwapChainForHwndCreateSwapChainForCoreWindow、または 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