リソースの種類 (Direct3D 10)
Direct3D パイプラインで使用されるリソースはすべて、2 つの基本的なリソースの種類であるバッファーとテクスチャから派生したものです。 バッファーは未加工データ (要素) のコレクションで、テクスチャはテクセル (テクスチャ要素) のコレクションです。
リソースのレイアウト (またはメモリ使用量) を完全に指定する方法は次の 2 つです。
アイテム | 説明 |
---|---|
型指定あり |
リソース作成時に型を完全に指定します。 |
型指定なし |
リソースをパイプラインにバインドするときに型を完全に指定します。 |
バッファー リソース
バッファー リソースは完全に型指定されたデータのコレクションであり、内部的にはバッファーに要素が格納されます。 要素は 1 ~ 4 つの成分で構成されます。 要素のデータ型の例としては、圧縮済みデータ (R8G8B8A8 など)、単一の 8 ビット整数、4 つの 32 ビット浮動小数点などがあります。 これらのデータ型は、位置ベクトル、法線ベクトル、頂点バッファーのテクスチャ座標、インデックス バッファーのインデックス、デバイスの状態などのデータを格納するために使用されます。
バッファーは構造化されていないリソースとして作成されます。 構造化されていないため、バッファーはミップマップ レベルを格納できず、読み取り時にフィルター処理を適用したり、マルチサンプリングを適用したりすることはできません。
バッファーの種類
頂点バッファー
バッファーは要素のコレクションであり、頂点バッファーには頂点単位のデータが格納されます。 頂点バッファーの最も単純な例は、位置データなど、1 種類のデータが格納されたものです。 これを視覚化すると次の図のようになります。
多くの場合、頂点バッファーには 3D の頂点を完全に指定するために必要なすべてのデータが含まれます。 頂点ごとの位置座標、法線座標、およびテクスチャ座標を格納した頂点バッファーが、その一例です。 このようなデータは、次の図に示すように、頂点ごとの要素のセットとしてまとめられます。
この頂点バッファーには 8 つの頂点に関する頂点ごとのデータが含まれており、各頂点には 3 つの要素 (位置座標、法線座標、およびテクスチャ座標) が格納されています。 通常、位置と法線はそれぞれ 3 つの 32 ビット浮動小数点 (DXGI_FORMAT_R32G32B32_FLOAT) を使用し、テクスチャ座標は 2 つの 32 ビット浮動小数点 (DXGI_FORMAT_R32G32_FLOAT) を使用して指定されます。
頂点バッファーのデータにアクセスするには、どの頂点にアクセスするのかという情報と、次のバッファー パラメーターの情報が必要になります。
- オフセット - バッファーの先頭から最初の頂点データまでのバイト数です。 オフセットは、 IASetVertexBuffers に渡されます。
- BaseVertexLocation - 適切な描画呼び出しで使用されるオフセットから最初の頂点までのバイト数 (「 Draw メソッド」を参照)。
頂点バッファーを作成する前に、 input-layout オブジェクトを作成してそのレイアウトを定義する必要があります。これは、 CreateInputLayout を呼び出すことによって行われます。 入力レイアウト オブジェクトが作成されたら、 IASetInputLayout を呼び出して、入力アセンブラー ステージにバインドします。
頂点バッファーを作成するには、 CreateBuffer を呼び出します。
インデックス バッファー
インデックス バッファーは 16 ビットまたは 32 ビットの連続するインデックスを格納します。各インデックスは頂点バッファーの頂点を識別するのに使用されます。 インデックス バッファーと 1 つ以上の頂点バッファーを併せて使用して、IA ステージにデータを渡すことをインデックス作成と呼びます。 インデックス バッファーを視覚化すると次の図のようになります。
インデックス バッファーに格納される一連のインデックスの位置は、次のパラメーターを使用して特定します。
- オフセット - バッファーの先頭から最初のインデックスまでのバイト数です。 オフセットは、 IASetIndexBuffer に渡されます。
- StartIndexLocation - 適切な描画呼び出しで使用されるオフセットから最初の頂点までのバイト数です ( Draw メソッドを参照)。
- IndexCount - レンダリングするインデックスの数です。
インデックス バッファーを作成するには、 CreateBuffer を呼び出します。
インデックス バッファーは、複数の 線または三角形のストリップを結合できます それぞれをストリップ カットインデックスで区切ります。 ストリップカット インデックスを使用すると、複数のライン ストリップまたはトライアングル ストリップを 1 つの描画呼び出しを使って描画することができます。 ストリップカット インデックスは、単にインデックスに使用できる最大値です (16 ビット インデックスの場合は0xffff、32 ビット インデックスの場合は0xffffffff)。 ストリップ カット インデックスはインデックス付きプリミティブのワインディング順序をリセットします。ストリップ カット インデックスを使用すれば、縮退三角形を使用しなくても、トライアングル ストリップの適切なワインディング順序を維持できます。 次の図は、ストリップカット インデックスの例を示しています。
定数バッファー
Direct3D 10 では、シェーダー定数バッファーまたは単に定数バッファーと呼ばれるシェーダー定数を提供するための新しいバッファーが導入されました。 概念的には、次の図に示すように、単一要素の頂点バッファーのようになります。
各要素には 1 ~ 4 成分の定数が格納されます。この値は格納されるデータの形式によって決まります。
定数バッファーを使用すると、複数のシェーダー定数をグループにまとめて同時にコミットできます。それぞれのシェーダー定数を個別の呼び出しで別々にコミットすることがないので、シェーダー定数の更新に必要な帯域を削減することができます。
シェーダー定数バッファーを作成するには、 CreateBuffer を呼び出し、定数バッファー バインド フラグD3D10_BIND_CONSTANT_BUFFERを指定します ( D3D10_BIND_FLAGを参照)。
シェーダー定数バッファーをパイプラインにバインドするには、 GSSetConstantBuffers、 PSSetConstantBuffers、または VSSetConstantBuffers のいずれかのメソッドを呼び出します。
ID3D10Effect インターフェイスを使用する場合定数バッファーの作成、バインド、および結合のプロセスは、ID3D10Effect Interface インスタンスによって処理されることに注意してください。 その場合は、 GetVariableByName などの GetVariable メソッドのいずれかを使用して効果から変数を取得し SetMatrix などの SetVariable メソッドのいずれかで変数を更新するだけで済みます。 定数バッファーを管理するために ID3D10Effect Interface を使用する例については、 tutorial 07 を参照してください。
シェーダーは、定数バッファーに含まれていない変数を読み取る場合と同様に、変数名を使って定数バッファー内の変数を継続的に直接読み取ります。
各シェーダー ステージでは最大 15 個の定数バッファーを使用でき、各バッファーには最大 4,096 の定数を保持できます。
定数バッファーを使用して、ストリーム出力ステージの結果を保存します。
シェーダーで定数バッファーを宣言する例については、「シェーダー定数 (DirectX HLSL)」をご覧ください。
テクスチャ リソース
テクスチャ リソースは、テクセルを格納するように設計された、データの構造化されたコレクションです。 バッファーと異なり、テクスチャは、シェーダー ユニットに読み取られる際にテクスチャ サンプラーでフィルターを適用することができます。 テクスチャへのフィルター処理の適用方法はテクスチャの種類に影響されます。 テクセルは、パイプラインで読み取ったり、書き込んだりすることができるテクスチャの最小単位を表します。 各テクセルは 1 つから 4 つの成分を含み、いずれかの DXGI 形式で配置されます (「DXGI_FORMAT」を参照してください)。
テクスチャは構造化されたリソースとして作成されるため、そのサイズがわかります。 ただし、テクスチャがパイプラインにバインドされているときに、型がビューを使用して完全に指定されている限り、リソース作成時に各テクスチャを型指定するか、型を減らすこともできます。
テクスチャの種類
テクスチャの種類には 1D、2D、および 3D があり、それぞれミップマップ付きまたはミップマップなしで作成できます。 Direct3D 10 では、テクスチャ配列とマルチサンプリング テクスチャもサポートされています。
1D テクスチャ
最も単純な形式の 1D テクスチャには、1 つのテクスチャ座標で処理できるテクスチャ データが格納されます。これをテクセルの配列として視覚化すると次の図のようになります。
各テクセルには、格納されているデータ形式に応じた色成分がいくつか含まれます。 より複雑なものになると、次の図に示すように、ミップマップ レベルを持つ 1D テクスチャを作成できます。
ミップマップ レベルは、上のレベルよりも 2 の累乗だけ小さいテクスチャです。 最上位レベルが最も詳細で (大きく)、レベルが下がるほど小さくなります。1D ミップマップの最小レベルはテクセルを 1 つだけ含みます。 各レベルの識別には詳細レベル (LOD) と呼ばれるインデックスを使用します。カメラにそれほど近くないジオメトリをレンダリングする場合は、LOD を使って小さいテクスチャにアクセスできます。
1D テクスチャ配列
Direct3D 10 には、テクスチャの配列用の新しいデータ構造も用意されています。 1D テクスチャの配列は概念的に次の図のようになります。
このテクスチャ配列には 3 つのテクスチャが含まれています。 3 つのテクスチャはそれぞれテクスチャ幅が 5 になっています (5 は最初のレイヤーの要素数)。 また、各テクスチャには 3 レイヤーのミップマップも格納されています。
Direct3D のすべてのテクスチャ配列は、テクスチャの同次配列です。つまり、1 つのテクスチャ配列内にあるテクスチャはすべて、データ形式とサイズが (テクスチャ幅とミップマップ レベル数も含めて) 同じである必要があります。 各配列に含まれるすべてのテクスチャのサイズが一致してさえいれば、さまざまなサイズのテクスチャ配列を作成できます。
2D テクスチャと 2D テクスチャ配列
Texture2D リソースにはテクセルの 2D グリッドが 1 つ含まれています。 各テクセルは u ベクトルと v ベクトルで指定できます。 これはテクスチャ リソースであるため、ミップマップ レベルとサブリソースが格納される場合もあります。 すべてのデータが設定された 2D テクスチャ リソースは次の図のようになります。
このテクスチャ リソースには 1 つの 3x5 テクスチャと 3 つのミップマップ レベルが格納されています。
Texture2DArray リソースは 2D テクスチャの同次配列であるため、各テクスチャのデータ形式とサイズは (ミップマップ レベルを含めて) 同じです。 このリソースは、テクスチャに 2D データが含まれていることを除けば 1D テクスチャ配列とレイアウトが似ています。したがって、次のような図になります。
このテクスチャ配列には 3 つのテクスチャが含まれています。各テクスチャは 3x5 で、2 つのミップマップ レベルを持ちます。
テクスチャ キューブとしての Texture2DArray の使用
テクスチャ キューブは、6 つのテクスチャ (キューブの各面に 1 つずつ) が含まれた 2D テクスチャ配列です。 すべてのデータが設定されたテクスチャ キューブは次の図のようになります。
6 つのテクスチャが含まれた 2D テクスチャ配列は、キューブ テクスチャ ビューを使ってパイプラインにバインドした後に、キューブ マップ組み込み関数を使ってシェーダー内から読み取ることができます。 テクスチャ キューブは、テクスチャ キューブの中心を起点とする 3D ベクトルによってシェーダーで処理されます。
3D テクスチャ
Texture3D リソース (ボリューム テクスチャとも呼ばれます) にはテクセルの 3D ボリュームが格納されます。 これはテクスチャ リソースであるため、ミップマップ レベルが含まれる場合もあります。 完全に設定された 3D テクスチャ は次の図のようになります。
3D テクスチャ ミップマップ スライスを (レンダー ターゲット ビューを使って) レンダー ターゲット出力としてバインドした場合、3D テクスチャは n 個のスライスの 2D テクスチャ配列と同じように動作します。 特定のレンダー スライスは、出力データのスカラー コンポーネントをSV_RenderTargetArrayIndexシステム値として宣言することによって、geometry-shader ステージから選択されます。
3D テクスチャ配列という概念は存在しません。そのため、3D テクスチャのサブリソースは単一のミップマップ レベルになります。
サブリソース
Direct3D 10 API は、リソース全体またはリソースのサブセットを参照します。 リソースの一部を指定するために、Direct3D はリソースのサブセットを意味するサブリソースという用語を作成しました。
バッファーは単一のサブリソースと定義されます。 テクスチャはもう少し複雑です。テクスチャの種類が複数存在していて (1D、2D など)、その一部ではミップマップ レベルやテクスチャ配列がサポートされているためです。 最も単純なケースから始めると、1D テクスチャは単一のサブリソースとして定義され、次の図のようになります。
つまり、1D テクスチャを構成するテクセルの配列は単一のサブリソースに含まれます。
1D テクスチャを 3 つのミップマップ レベルで拡張した場合、それを視覚化すると次のようになります。
これを 3 つのサブテクスチャで構成される単一のテクスチャと考えます。 各サブテクスチャは 1 つのサブリソースとしてカウントされます。そのため、この 1D テクスチャには 3 つのサブリソースが含まれます。 サブテクスチャ (またはサブリソース) は、単一テクスチャ用の詳細レベル (LOD) を使ってインデックスを作成できます。 テクスチャの配列を使用する場合、特定のサブテクスチャにアクセスするには LOD とその特定のテクスチャの両方が必要です。 または、API によって、この 2 つの情報を以下に示すような 0 から始まる単一のサブリソース インデックスにまとめます。
サブリソースの選択
リソース全体 ( CopyResource など) にアクセスする API もあれば、リソースの一部 (たとえば、 UpdateSubresource CopySubresourceRegion) にアクセスする API もあります。 リソースの一部にアクセスする API では、通常、ビューの説明 ( D3D10_TEX2D_ARRAY_DSV など) を使用して、アクセスするサブリソースを指定します。
以下の図は、テクスチャの配列にアクセスする際にビュー記述で使用される用語を表しています。
配列スライス
あるテクスチャの配列で、各テクスチャにミップマップが用意されている場合、次の図に示すように、(白い長方形で表されている) 配列スライスには 1 つのテクスチャとそのすべてのサブテクスチャが含まれます。
ミップ スライス
次の図に示すように、(白い長方形で表されている) ミップ スライスには配列内のすべてのテクスチャのミップマップ レベルが 1 つ含まれます。
単一サブリソースの選択
次の図に示すように、単一のリソースを選択するには、前述の 2 種類のスライスを使用します。
複数のサブリソースの選択
また、複数のサブリソースを選択するには、ミップマップ レベル数やテクスチャ数を指定して、前述の 2 種類のスライスを使用します。
ミップマップの有無にかかわらず、テクスチャ配列の有無にかかわらず、ヘルパー関数 D3D10CalcSubresource を使用して、特定のサブリソースのインデックスを計算できます。
強い型指定と弱い型指定
完全に型指定されたリソースを作成すると、そのリソースの形式はそのリソースを作成したときの形式に制限されます。 これにより、特にリソースがアプリケーションによって マップできないことを示すフラグを使用して作成された場合 、ランタイムはアクセスを最適化できます。 型を指定して作成したリソースは、ビュー機構を使って再解釈することができません。
リソースが少ない型では、リソースが最初に作成されるときにデータ型が不明になります。 アプリケーションは、使用可能な型の小さい形式から選択する必要があります ( DXGI_FORMATを参照)。 また、割り当てるメモリのサイズと、ランタイムでミップマップのサブテクスチャを生成する必要があるかどうかも指定しなければなりません。 ただし、正確なデータ形式 (整数、浮動小数点値、符号なし整数などとして、メモリが解釈されるかどうか) はビューを使ってリソースがパイプラインにバインドされるまで決定されません。 テクスチャ形式はテクスチャがパイプラインにバインドされるまで柔軟性が維持されるため、このリソースは弱く型指定されたストレージと呼ばれます。 弱く型指定されたストレージには、新しい形式の成分ビットが古い形式のビット数と一致している限り、(別の形式で) 再使用または再解釈できるという利点があります。
各パイプライン ステージに、それぞれの場所での形式を完全に修飾する一意のビューがある限り、1 つのリソースを複数のパイプライン ステージにバインドすることができます。 たとえば、DXGI_FORMAT_R32G32B32A32_TYPELESS形式で作成されたリソースは、パイプライン内の異なる場所にあるDXGI_FORMAT_R32G32B32A32_FLOATとDXGI_FORMAT_R32G32B32A32_UINTとして同時に使用できます。
関連トピック