Direct3D 12 は、Direct3D 11 プログラミング モデルからの大幅な逸脱を表します。 Direct3D 12 を使用すると、アプリをこれまで以上にハードウェアに近づけることができます。 ハードウェアに近づくと、Direct3D 12 はより高速で効率的になります。 ただし、Direct3D 12 の速度と効率が向上したアプリのトレードオフは、Direct3D 11 よりも多くのタスクを担当していることです。
- 明示的な同期 の
- 物理メモリ常駐管理 の
- パイプライン状態オブジェクト を する
- コマンド リストとバンドル
- 記述子ヒープとテーブル
- Direct3D 11 からの 移植
- 関連トピック
Direct3D 12 は、低レベルプログラミングへの復帰です。これにより、パイプラインの全体的な状態を表すオブジェクト、作業送信用のコマンド リストとバンドル、リソース アクセス用の記述子ヒープとテーブルなどの新しい機能が導入され、ゲームやアプリのグラフィカル要素をより詳細に制御できます。
アプリは Direct3D 12 の速度と効率を向上させましたが、Direct3D 11 よりも多くのタスクを担当します。
明示的な同期
- Direct3D 12 では、CPU-GPU 同期がアプリの明示的な役割となり、Direct3D 11 と同様にランタイムによって暗黙的に実行されなくなります。 この事実は、Direct3D 12 によってパイプラインの危険性の自動チェックが実行されていないことも意味するため、これもアプリの責任です。
- Direct3D 12 では、アプリはデータ更新のパイプライン処理を担当します。 つまり、Direct3D 11 の "Map/Lock-DISCARD" パターンは、Direct3D 12 で手動で実行する必要があります。 Direct3D 11 では、D3D11_MAP_WRITE_DISCARDを使用して ID3D11DeviceContext::Map呼び出したときに GPU がまだバッファーを使用している場合、ランタイムは古いバッファー データではなく、メモリの新しい領域へのポインターを返します。 これにより、アプリが新しいバッファーにデータを配置している間、GPU は古いデータを引き続き使用できます。 アプリで追加のメモリ管理は必要ありません。古いバッファーは、GPU が終了すると自動的に再利用または破棄されます。
- Direct3D 12 では、すべての動的更新 (定数バッファー、動的頂点バッファー、動的テクスチャなど) がアプリによって明示的に制御されます。 これらの動的更新には、必要な GPU フェンスまたはバッファリングが含まれます。 このアプリは、メモリが不要になるまで使用可能な状態を維持する役割を担います。
- Direct3D 12 では、インターフェイスの有効期間に対してのみ COM スタイルの参照カウントが使用されます (デバイスの有効期間に関連付けられている Direct3D の弱参照モデルを使用)。 すべてのリソースと説明のメモリの有効期間は、適切な期間維持するアプリの唯一の責任であり、参照カウントされません。 Direct3D 11 では、参照カウントを使用して、インターフェイスの依存関係の有効期間も管理します。
物理メモリ常駐管理
Direct3D 12 アプリケーションでは、複数のキュー、複数のアダプター、および CPU スレッド間の競合状態を防ぐ必要があります。 D3D12 では、CPU と GPU が同期されなくなり、リソースの名前変更やマルチバッファリングのための便利なメカニズムもサポートされません。 フェンスは、別の処理ユニットがメモリの使用を終了する前に、メモリの過剰書き込みを回避するために使用する必要があります。
Direct3D 12 アプリケーションでは、GPU がデータを読み取る間、データがメモリに常駐していることを確認する必要があります。 各オブジェクトで使用されるメモリは、オブジェクトの作成時に常駐します。 これらのメソッドを呼び出すアプリケーションでは、GPU が削除されたオブジェクトにアクセスしないようにフェンスを使用する必要があります。
リソース バリアは、リソースとサブリソースの遷移を非常に細かいレベルで同期するために使用される、必要な同期のもう 1 つの種類です。
Direct3D 12 でのメモリ管理のを参照してください。
パイプライン状態オブジェクト
Direct3D 11 では、多数の独立したオブジェクトを介してパイプライン状態を操作できます。 たとえば、入力アセンブラーの状態、ピクセル シェーダーの状態、ラスタライザーの状態、出力マージャーの状態はすべて個別に変更できます。 この設計は、グラフィックス パイプラインの便利で比較的高度な表現を提供しますが、主にさまざまな状態が相互に依存するため、最新のハードウェアの機能は利用されません。 たとえば、多くの GPU では、ピクセル シェーダーと出力マージャーの状態が 1 つのハードウェア表現に結合されます。 ただし、Direct3D 11 API ではこれらのパイプライン ステージを個別に設定できるため、ディスプレイ ドライバーは、状態が終了するまでパイプライン状態の問題を解決できません。これは描画時間までではありません。 このスキームにより、ハードウェア状態のセットアップが遅れます。つまり、余分なオーバーヘッドが発生し、フレームあたりの最大描画呼び出し数が少なくなります。
Direct3D 12 では、パイプライン状態の多くを不変のパイプライン状態オブジェクト (PSO) に統合することで、このスキームに対処します。これは、作成時に最終処理されます。 ハードウェアとドライバーは、GPU 作業を実行するために必要なハードウェア ネイティブ命令と状態に PSO をすぐに変換できます。 使用中の PSO を動的に変更することはできますが、これを行うには、ハードウェアの状態をその場で計算するのではなく、事前に計算された最小限の状態をハードウェア レジスタに直接コピーするだけで済みます。 PSO を使用すると、描画呼び出しのオーバーヘッドが大幅に削減され、フレームごとにさらに多くの描画呼び出しが発生する可能性があります。 PSO の詳細については、「Direct3D 12でのグラフィックス パイプラインの状態の管理」を参照してください。
コマンド リストとバンドル
Direct3D 11 では、すべての作業の送信は、GPU に送信されるコマンドの単一のストリームを表す 即時コンテキストを介して行われます。 マルチスレッド スケーリングを実現するために、ゲームには遅延コンテキスト 用意されています。 Direct3D 11 の遅延コンテキストはハードウェアに完全にマップされないため、比較的少ない作業を実行できます。
Direct3D 12 では、GPU で特定のワークロードを実行するために必要な情報全体を含むコマンド リストに基づいて、新しい作業送信モデルが導入されています。 各新しいコマンド リストには、使用する PSO、必要なテクスチャリソースとバッファー リソース、すべての描画呼び出しの引数などの情報が含まれています。 各コマンド リストは自己完結型であり、状態を継承しないため、ドライバーは必要なすべての GPU コマンドを事前に、フリー スレッド方式で事前に計算できます。 必要な唯一のシリアル プロセスは、コマンド キューを介して GPU にコマンド リストを最終的に送信することです。
コマンド リストに加えて、Direct3D 12 では、2 番目のレベルの作業の事前計算も導入されています。バンドル。 完全に自己完結型であり、通常は構築、送信、破棄されるコマンド リストとは異なり、バンドルは、再利用を可能にする状態継承の形式を提供します。 たとえば、ゲームでテクスチャが異なる 2 つのキャラクター モデルを描画する場合、1 つの方法は、同じ描画呼び出しの 2 つのセットでコマンド リストを記録することです。 ただし、もう 1 つの方法は、1 つのキャラクター モデルを描画する 1 つのバンドルを "記録" し、別のリソースを使用してコマンド リストでバンドルを 2 回 "再生" することです。 後者の場合、ディスプレイ ドライバーは 1 回だけ適切な命令を計算する必要があり、基本的に 2 つの低コストの関数呼び出しに相当するコマンド リストを作成します。
コマンド リストとバンドルの詳細については、「Direct3D 12の作業提出」を参照してください。
記述子ヒープとテーブル
Direct3D 11 のリソース バインドは非常に抽象化され、便利ですが、最新のハードウェア機能の使用率は低く残されています。 Direct3D 11 では、ゲームはリソースのオブジェクト ビュー 作成し、パイプラインのさまざまなシェーダー ステージで 複数の スロットにそれらのビューをバインドします。 シェーダーは、描画時に固定された明示的なバインド スロットからデータを読み取ります。 このモデルは、ゲームが異なるリソースを使用して描画するたびに、異なるビューを異なるスロットに再バインドし、再び描画を呼び出す必要があることを意味します。 このケースは、最新のハードウェア機能を完全に利用することで排除できるオーバーヘッドも表します。
Direct3D 12 では、最新のハードウェアに合わせてバインド モデルが変更され、パフォーマンスが大幅に向上します。 Direct3D 12 では、スタンドアロン のリソース ビューとスロットへの明示的なマッピングを必要とするのではなく、ゲームがさまざまなリソース ビューを作成する記述子ヒープが提供されます。 このスキームは、GPU がハードウェアネイティブ リソース記述 (記述子) をメモリに直接書き込むためのメカニズムを提供します。 特定の描画呼び出しでパイプラインによって使用されるリソースを宣言するために、ゲームでは、完全な記述子ヒープのサブ範囲を表す 1 つ以上の記述子テーブルを指定します。 記述子ヒープには、適切なハードウェア固有の記述子データが既に設定されているため、記述子テーブルの変更は非常に低コストの操作です。
Direct3D 12 では、記述子ヒープとテーブルによって提供されるパフォーマンスの向上に加えて、シェーダーでリソースのインデックスを動的に作成することもできます。これにより、かつてないほどの柔軟性が提供され、新しいレンダリング手法のロックが解除されます。 たとえば、最新の遅延レンダリング エンジンは、通常、ある種のマテリアルまたはオブジェクト識別子を中間 g バッファーにエンコードします。 Direct3D 11 では、1 つの g バッファーに含めすぎると最終的なレンダリング パスが大幅に遅くなる可能性があるので、これらのエンジンでは、マテリアルの使用が多くなりすぎないように注意する必要があります。 動的にインデックスを作成できるリソースを使用すると、1000 個のマテリアルを持つシーンを、わずか 10 個のシーンと同じくらい迅速に最終処理できます。
記述子ヒープとテーブルの詳細については、「リソース バインド」および「Direct3D 11 からのバインド モデルのの相違点」を参照してください。
Direct3D 11 からの移植
Direct3D 11 からの移植は、Direct3D 11 から Direct3D 12 への移植に関する説明に含まれるプロセスです。 また、「Direct3D 11、Direct3D 10、および Direct2Dを使用する」のオプションの範囲を参照してください。
関連トピック
-
Direct3D 12 について