次の方法で共有


記述子の概要

記述子は API 呼び出しによって作成され、リソースを特定します。

記述子のデータ

記述子は、オブジェクトを GPU に対して完全に記述するための比較的小さなデータであり、その形式は GPU 固有の不透明な形式です。 記述子には、レンダー ターゲット ビュー (RTV)、深度ステンシル ビュー (DSV)、シェーダー リソース ビュー (SRV)、順序指定されていないアクセス ビュー (UAV)、定数バッファー ビュー (CBV)、サンプラーなど、さまざまな種類があります。

記述子のサイズは、GPU ハードウェアによって異なります。 SRV、UAV、または CBV のサイズを照会するには、ID3D12Device::GetDescriptorHandleIncrementSize を呼び出します。 記述子は、このドキュメントでは不可分単位として示されています。例を次に示します。

srv, cbv, uav, and sampler

記述子は API 呼び出しによって作成され、このときに指定された情報 (リソースや MIP マップなど) が記述子に格納されます。

ドライバーが記述子への参照を追跡したり保持したりすることはありません。使用されている記述子の種類が正しいことと、情報が最新であることを保証するのは、アプリの責任です。 これには 1 つ小さな例外があり、ドライバーはレンダー ターゲットのバインディングを調べます。これは、スワップ チェーンを確実に正しく動作させるためです。

オブジェクトの記述子を解放することは必要ありません。 記述子が作成されるときに、ドライバーによって割り当てがアタッチされることはありません。 ただし、アプリケーションが他の割り当ての有効期間全体の所有権を持っている場合に、記述子がその割り当てへの参照をエンコードすることもできます。 たとえば、SRV の記述子のデータの中には、その SRV が参照する D3D リソース (たとえばテクスチャ) の仮想アドレスが含まれている必要があります。 この SRV 記述子が依存している D3D リソースが破棄されたときや変更が加えられた (たとえば、非常駐と宣言された) ときに、その SRV 記述子が使用されないようにするのはアプリケーションの責任です。

記述子の主な使い方は、記述子を記述子ヒープの中に配置することです。記述子ヒープとは、記述子のためのバッキング メモリです。

記述子のハンドル

記述子のハンドルとは、記述子の一意のアドレスです。 ポインターに似ていますが、ハードウェア固有の実装であるため、不透明です。 ハンドルはすべての記述子ヒープを通して一意です。したがって、たとえばハンドルの配列で複数のヒープの記述子を参照することができます。

CPU ハンドルは、即時使用のためのものです。たとえば、コピー時にコピー元とコピー先の両方を特定する必要がある場合に使用します。 これらは使用した (ID3D12GraphicsCommandList::OMSetRenderTargets の呼び出しなど) 直後に、再利用することも、その基になっているヒープを破棄することもできます。

GPU ハンドルは、即時使用のためのものではなく、コマンド リストから場所を特定して GPU 実行時に使用するためのものです。 これらは、それらを参照するコマンド リストが完全に実行されるまで保持する必要があります。

ヒープの開始を表す記述子ハンドルを作成するには、記述子ヒープ自体を作成した後に、次のメソッドの 1 つを呼び出します。

これらのメソッドは、次の構造体を返します。

記述子のサイズはハードウェアによって異なるため、ヒープ内の記述子間のインクリメントを取得するには次のメソッドを使用します。

ハンドルをコピーするときや、ハンドルを API 呼び出しに渡すときに、開始位置を数値またはインクリメントでオフセットしても問題ありません。 ハンドルを、有効な CPU ポインターと見なして逆参照することや、ハンドル内のビットを分析することは安全ではありません。

ハンドルの管理を多少簡単にするために、いくつかのヘルパー構造体が初期化メンバーと共に追加されています。

Null 記述子

アプリケーションで API 呼び出しを使用して記述子を作成するときに、記述子定義の中でリソース ポインターに対して NULL を渡すと、シェーダーによってアクセスされたときに何もバインドされないという効果を達成することができます。

記述子のそれ以外の部分は、可能な限り値を指定する必要があります。 たとえば、シェーダー リソース ビュー (SRV) の場合は、記述子を使用してビューの種類 (Texture1D、Texture2D など) を区別することができます。 ビュー記述子の数値パラメーター (たとえば MIP マップの数) はすべて、リソースに対して有効な値に設定されている必要があります。

多くの場合は、バインドされていないリソースにアクセスするときの動作が定義されています。たとえば SRV では既定値が返されます。 NULL 記述子にアクセスするときにこの定義のとおりになるには、シェーダー アクセスの種類が記述子の種類と対応していることが条件となります。 たとえば、シェーダーが Texture2D の SRV を必要としている場合に、アクセスした NULL SRV が Texture1D と定義されているときの動作は未定義であり、デバイスのリセットとなる可能性があります。

要約すると、NULL 記述子を作成するには、CreateShaderResourceView などのメソッドを使用してビューを作成するときに pResource パラメーターに null を渡します。 ビュー記述子パラメーター pDesc には、リソースが Null でない場合に機能する構成を設定します (このとおりでないときは、ハードウェアによってはクラッシュする可能性があります)。

ただし、ルート記述子を Null に設定してはなりません。

Tier1 ハードウェア (「ハードウェア層」を参照) では、(記述子テーブルを介して) バインドされているすべての記述子は、ハードウェアによってアクセスされない場合でも、実際の記述子または null 記述子として初期化する必要があります。そうしないと、動作が未定義となります。。

Tier2 ハードウェアでは、これはバインドされた CBV 記述子と UAV 記述子には適用されますが、SRV 記述子には適用されません。

Tier3 ハードウェアでは、初期化されていない記述子にアクセスしない限り、これに制限はありません。

既定の記述子

特定のビュー用に既定の記述子を作成するには、ビューの作成メソッド (CreateShaderResourceView など) に有効な pResource パラメータを渡し、pDesc パラメータには NULL を渡します。 たとえば、リソースの中に MIP が 14 個ある場合は、ビューの中に MIP が 14 個あることになります。 この既定のケースでは、リソースからビューへの最も明白なマッピングに対処できます。 この場合は、リソースが完全修飾形式名を使用して割り当てられている必要はありません (たとえば DXGI_FORMAT_R8G8B8A8_TYPELESS ではなく DXGI_FORMAT_R8G8B8A8_UNORM_SRGB)。

指定された pResource パラメータは NULL である必要があり、場所は D3D12_RAYTRACING_ACCELERATION_STRUCTURE_SRV を介して渡す必要があるため、既定の記述子はレイトレーシング アクセラレーション構造ビューでは使用できません。

記述子