サブリソース (Direct3D 12 グラフィックス)

リソースをサブリソースに分割する方法と、1 つのサブリソース、複数のサブリソース、またはサブリソースのスライスを参照する方法について説明します。

サブリソースの例

1 つのリソースの内容がバッファー 1 つである場合は、サブリソースが 1 つあることになり、そのインデックスは 0 です。 そのリソースの内容がテクスチャ (またはテクスチャ配列) である場合は、そのサブリソースの参照はより複雑になります。

API の中には、リソース全体にアクセスするものもあれば (たとえば ID3D12GraphicsCommandList::CopyResource メソッド)、リソースの一部分にアクセスするものもあります (たとえば ID3D12Resource::ReadFromSubresource メソッド)。 通常、リソースの一部にアクセスするメソッドでは、ビューの説明 ( D3D12_TEX2D_ARRAY_SRV 構造など) を使用して、アクセスするサブリソースを指定します。 すべての一覧については、「サブリソースの API」セクションを参照してください。

サブリソースのインデックス

特定のサブリソースをインデックスで指定するために、各配列エントリにインデックスを付けるときに、最初に MIP レベルにインデックスが付けられます。

サブリソースのインデックス作成

MIP スライス

次の画像に示すように、1 つの MIP スライスには、配列内の同じ MIP マップ レベルのテクスチャがすべて含まれています。

サブリソースの MIP スライス

配列スライス

次の画像に示すように、あるテクスチャ配列で、各テクスチャに MIP マップがある場合に、1 つの配列スライスには 1 つのテクスチャとそのすべての MIP レベルが含まれています。

サブリソースの配列スライス

プレーン スライス

一般的に、平面形式が RGBA データの格納に使用されることはありませんが、使用される場合は (おそらく 24bpp RGB データ)、プレーンの 1 つが赤色の画像、1 つが緑色の画像、1 つが青色の画像を表します。 1 つのプレーンが 1 色である必要はなく、2 色以上を組み合わせて 1 つのプレーンにすることもできます。 平面データがより一般的に使用されるのは、サブサンプリングされた YCbCr と深度ステンシル データです。 深度ステンシルは、MIP マップ、配列、複数プレーンを完全にサポートする唯一の形式です (多くの場合はプレーン 0 が深度、プレーン 1 がステンシル)。

2 つの深度ステンシル画像の配列があり、それぞれに 3 つの MIP レベルがある場合に、この配列でのサブリソースのインデックスは次のようになります。

深度ステンシルのインデックス

サブサンプリングされた YCbCr では配列がサポートされ、プレーンがありますが、MIP マップはサポートされません。 YCbCr 画像には 2 つのプレーンがあります。1 つは輝度 (Y) つまり人間の目が最も敏感に認識する成分であり、もう 1 つはクロミナンス (Cb と Cr の両方がインターリーブ) つまり人間の目がそれほど敏感には認識しない成分です。 この形式では、輝度に影響を与えることなくクロミナンスを圧縮することによって画像を圧縮することができ、そのような理由からビデオ圧縮形式としてよく使われていますが、静止画像の圧縮にも使用されています。 次に示す画像は、NV12 形式を表しています。クロミナンスが圧縮されて輝度の解像度の 4 分の 1 になっていることに注目してください。つまり、各プレーンの幅は同一ですが、クロミナンスのプレーンの高さは輝度のプレーンの半分です。 これらのプレーンにサブリソースとしてインデックスを付ける方法は、上記の深度ステンシルの例と同じです。

NV12 形式

平面形式は Direct3D 11 にも存在しますが、コピーやマッピングなどの操作のために個々のプレーンを個別に指定することはできません。 これは Direct3D 12 で変更され、各プレーンに専用のサブリソース ID が付与されるようになりました。 サブリソース ID の計算について、次の 2 つの方法を比較します。

Direct3D 11

inline UINT D3D11CalcSubresource( UINT MipSlice, UINT ArraySlice, UINT MipLevels )
{
    return MipSlice + (ArraySlice * MipLevels); 
}

Direct3D 12

inline UINT D3D12CalcSubresource( UINT MipSlice, UINT ArraySlice, UINT PlaneSlice, UINT MipLevels, UINT ArraySize )
{ 
    return MipSlice + (ArraySlice * MipLevels) + (PlaneSlice * MipLevels * ArraySize); 
}

ほとんどのハードウェアは、プレーン N 用のメモリが常にプレーン N-1 の直後に確保されると想定しています。

アプリでのサブリソースの使用に代わる方法として、プレーンごとにまったく別のリソースを割り当てることもできます。 この場合は、そのデータが平面形式であることをアプリケーションが理解して、複数のリソースを使用してそのデータを表します。

複数のサブリソース

シェーダー リソース ビューでは、上で説明したスライスの 1 つを使用し、ビュー構造内のフィールドを慎重に使用してサブリソースの任意の四角形領域 ( D3D12_TEX2D_ARRAY_SRVなど) を選択できます (図に示すように)。

複数のサブリソースの選択

レンダー ターゲット ビューで使用できるのは、サブリソースまたは MIP スライス 1 つだけです。複数の MIP スライスからサブリソースを選択することはできません。 つまり、1 つのレンダー ターゲット ビュー内のテクスチャはすべて、同じサイズでなければなりません。 シェーダー リソース ビューでは、この画像に示すように、任意の四角形領域内のサブリソースを選択できます。

サブリソースの API

次の API でサブリソースを参照し、サブリソースを扱います。

列挙型:

以下の構造体の中に PlaneSlice インデックスがあり、ほとんどの中に MipSlice インデックスがあります。

以下の構造体の中に ArraySlice インデックスがあり、ほとんどの中に MipSlice インデックスがあります。

以下の構造体の中には MipSlice インデックスがありますが、ArraySlice インデックスと PlaneSlice インデックスはありません。

以下の構造体もサブリソースを参照します。

メソッド:

  • ID3D12Device::GetCopyableFootprints : コピーを行うために、リソースの情報を取得します。
  • ID3D12Device::GetResourceTiling : タイル リソースがどのようにタイルに分割されているかについての情報を取得します。
  • ID3D12GraphicsCommandList::ResolveSubresource : マルチ サンプリングされたサブリソースをマルチ サンプリングされていないサブリソースにコピーします。
  • ID3D12Resource::Map : リソース内の指定されたデータへのポインターを返します。そのサブリソースには GPU からアクセスできなくなります。
  • ID3D12Resource::ReadFromSubresource : 1 つのサブリソースから、または四角形領域内のサブリソースからデータをコピーします。
  • ID3D12Resource::Unmap : 指定されたメモリ範囲のマッピングを解除し、リソースへのポインターを無効にします。 GPU が再びそのリソースにアクセスできるようになります。
  • ID3D12Resource::WriteToSubresource : データを 1 つのサブリソースに、または四角形領域内のサブリソースにコピーします。

WriteToSubresourceReadFromSubresource を介した CPU アクセスを有効にするには、テクスチャがD3D12_RESOURCE_STATE_COMMON状態である必要があります。ただし、バッファーはしません。 リソースへの CPU アクセスは、通常、 マップ/のマップ解除を使用して行われます。

リソース バインディング