Direct3D 11 on 12

D3D11On12 は、開発者が D3D11 のインターフェイスとオブジェクトを使って D3D12 API を駆動するためのメカニズムです。 D3D11on12 を利用すると、D3D11 を使ってプログラミングされたコンポーネント (たとえば D2D テキストと UI) と、D3D12 API をターゲットとしてプログラミングされたコンポーネントとを連動させることができます。 D3D11on12 は、D3D11 から D3D12 へのアプリケーションの段階的移植にも利用できます。つまり、アプリの一部分は引き続き D3D11 をターゲットとして単純化を図る一方で、それ以外の部分はパフォーマンス向上のために D3D12 をターゲットとすることが可能であり、常に完全で正確なレンダリングを行うことができます。 D3D11On12 を利用するほうがこのことを簡単に実現できるので、相互運用手法を使用して 2 つの API の間でリソースを共有して作業を同期させる必要はなくなります。

D3D11On12 の初期化

D3D11On12 の使用を開始するための最初のステップは、D3D12 のデバイスとコマンド キューを作成することです。 これらのオブジェクトは、初期化メソッド D3D11On12CreateDevice に入力として渡されます。 このメソッドは、仮想ドライバーの種類が D3D_DRIVER_TYPE_11ON12 の D3D11 デバイスを作成すると考えることができます。ここで、D3D11 ドライバーはオブジェクトの作成とコマンド リストの D3D12 API への送信を担当します。

プログラムの中で D3D11 デバイスとイミディエイト コンテキストを入手したら、このデバイスに対して QueryInterface を実行して ID3D11On12Device インターフェイスを入手します。 これは D3D11 と D3D12 との相互運用に使用されるプライマリ インターフェイスです。 D3D11 のデバイス コンテキストと D3D12 のコマンド リストの両方が同じリソースに対して動作できるようにするには、"ラップされたリソース" を CreateWrappedResource API を使用して作成する必要があります。 このメソッドによって D3D12 のリソースが "昇格" し、D3D11 で理解されるようになります。 ラップされたリソースの最初の状態は "取得済み" となります。このプロパティは、AcquireWrappedResources メソッドと ReleaseWrappedResources メソッドで操作されます。

使用例

D3D11On12 の一般的な用途としては、D2D を使用してテキストまたは画像を D3D12 バック バッファーに重ねてレンダリングすることが考えられます。 コード例については、D3D11On12 のサンプルを参照してください。 その手順の概要を次に示します。

  • D3D12 デバイス (D3D12CreateDevice) と D3D12 スワップ チェーン (CreateSwapChainID3D12CommandQueue を入力とする) を作成します。
  • D3D12 デバイスを使用して D3D11On12 デバイスを作成します。同じコマンド キューを入力とします。
  • スワップ チェーン バック バッファーを取得し、バッファーのそれぞれに対して D3D11 のラップされたリソースを作成します。 使用される入力状態は、D3D12 が最後に使用した方法 (たとえば、RENDER_TARGET) であり、出力状態は D3D11 が完了した後に D3D12 が使用する方法 (PRESENT など) である必要があります。
  • D2D を初期化し、D3D11 のラップされたリソースを D2D に渡してレンダリングに備えます。

次に、各フレームで次を実行します。

  • D3D12 のコマンド リストを使用して現在のスワップ チェーン バック バッファーにレンダリングし、それを実行します。
  • 現在のバック バッファーのラップされたリソースを取得します (AcquireWrappedResources)。
  • D2D レンダリング コマンドを発行します。
  • ラップされたリソースを解放します (ReleaseWrappedResources)。
  • D3D11 イミディエイト コンテキストをフラッシュします。
  • 提示します (IDXGISwapChain1::Present1)。

背景

D3D11On12 は体系的に動作します。 D3D11 API の各呼び出しは、通常の実行時の検証を通過してドライバーに到達します。 ドライバー レイヤーで、特殊な 11on12 ドライバーが状態を記録し、レンダリング操作を D3D12 コマンド リストに対して発行します。 このコマンド リストは必要に応じて提出されますが (たとえば、クエリの GetData やリソースの Map のときにコマンドのフラッシュが必要になることがあります)、Flush で要求されたときにも提出されます。 D3D11 のオブジェクトを作成すると、一般的には、対応する D3D12 のオブジェクトが作成されます。 D3D11 での固定関数レンダリング操作の中には、GenerateMipsDrawAuto のように、D3D12 ではサポートされないものがあるため、D3D11On12 はシェーダーと追加のリソースを使用してこのような操作をエミュレートします。

相互運用ができるようにするには、アプリによって作成され提供された D3D12 オブジェクトと D3D11On12 がどのように相互作用するかを理解しておくことが重要です。 作業が確実に正しい順序で行われるようにするには、D3D11 のイミディエイト コンテキストをフラッシュしてからでなければ、D3D12 の追加作業をそのキューに送ることはできません。 また、D3D11On12 に渡されたキューがいつでもドレイン可能であるようにすることも重要です。 つまり、キューに対する待機がある場合は、D3D11 レンダリング スレッドが無期限にブロックしていたとしても、そのような待機がいつかは満たされる必要があります。 D3D11On12 によるフラッシュや待機の挿入のタイミングに依存しないよう注意してください。これは、将来のリリースで変更される可能性があるからです。 さらに、D3D11On12 自身もリソースの状態を追跡して操作します。 状態遷移の一貫性を確実にする唯一の方法は、取得/解放の API を利用してアプリのニーズに一致するように状態の追跡を操作することです。

クリーンアップしています

D3D11On12 のラップされたリソースを解放するには、次の 2 つのことを、ここに示す順序で行う必要があります。

  • リソースへのすべての参照 (これにはリソースのビューも含まれます) が解放される必要があります。
  • 遅延破棄処理が行われる必要があります。 これが確実に行われるようにする最も簡単な方法は、イミディエイト コンテキスト Flush API を呼び出すことです。

これらのステップが両方とも完了すると、ラップされたリソースによって取得された参照はすべて解放された状態になり、D3D12 のリソースは D3D12 コンポーネントによって排他的に所有されるようになります。 このようにする場合も、D3D12 は GPU の完了を待機する必要があり、その後でリソースが完全にリリースされることに注意してください。そのため、上記の 2 つのステップを実行する前に、必ずそのリソースに対する参照を保持してください (GPU がそのリソースを使用しなくなったことを確認済みの場合を除きます)。

D3D11On12 によって作成されたその他のリソースやオブジェクトはすべて、適切なタイミングで、つまり GPU による使用が完了したときに、D3D11 の遅延破棄メカニズムを使用してクリーンアップされます。 ただし、D3D11On12 デバイス自体を解放しようとしたときに GPU がまだ実行中の場合は、GPU が完了するまで破棄がブロックされる可能性があります。

制限事項

D3D11On12 レイヤーによって、D3D11 API のかなりの部分が実装されますが、いくつかの既知のギャップがあります (他にも、実装のバグによってレンダリングが不正確になる可能性があります)。

Windows 10 バージョン 1809 (10.0、ビルド 17763) からは、D3D11On12 を実行するドライバーでシェーダー モデル 6.0 以降がサポートされている場合に限り、インターフェイスを使用するシェーダーを実行できます。 それよりも前のバージョンの Windows では、シェーダー インターフェイス機能が D3D11On12 で実装されていないため、この機能を使用しようとするとエラーが発生してデバッグ メッセージが表示されます。

Windows 10 バージョン 1803 (10.0、ビルド 17134) からは、スワップ チェーンが D3D11On12 デバイスでサポートされます。 それよりも前のバージョンの Windows では、そうではありません。

D3D11On12 のパフォーマンスの最適化は行われていません。 CPU オーバーヘッドは標準の D3D11 ドライバーと比べて中程度と考えられ、最小限の GPU オーバーヘッドがあり、かなりのメモリ オーバーヘッドがあることがわかっています。 そのため、D3D11On12 の使用は、複雑な 3D シーンにはお勧めできませんが、代わりに、シンプルなシーンや 2D レンダリングにはお勧めします。

API

11on12 レイヤーを構成する API の説明は、「11on12 リファレンス」を参照してください。

D3D11on12 使用した D2D のチュートリアル

Direct3D 12 とは

Direct3D 11、Direct3D 10、Direct2D での作業