入力アセンブラー ステージの概要
入力アセンブラー (IA) ステージを初期化するために必要な手順がいくつかあります。 たとえば、パイプラインに必要な頂点データを含むバッファー リソースを作成し、バッファーの場所と含まれるデータの型を IA ステージに指示し、そのデータからアセンブルするプリミティブの型を指定する必要があります。
このトピックでは、次の表内に示す IA ステージの設定に関連する基本的な手順について説明します。
Step | 説明 |
---|---|
入力バッファーを作成する | 入力頂点データを使用して入力バッファーを作成および初期化します。 |
入力レイアウト オブジェクトを作成する | 入力レイアウト オブジェクトを使用して、頂点バッファー データを IA ステージにストリームする方法を定義します。 |
オブジェクトを入力アセンブラー ステージにバインドする | 作成されたオブジェクト (入力バッファーと入力レイアウト オブジェクト) を IA ステージにバインドします。 |
プリミティブ型を指定する | 頂点をプリミティブにアセンブルする方法を特定します。 |
Draw メソッドを呼び出す | パイプラインを経由して、IA ステージにバインドされたデータを送信します。 |
これらの手順を理解したら、「システム生成値の使用」に進んでください。
入力バッファーを作成する
入力バッファーには、頂点バッファーとインデックス バッファーの 2 種類があります。 頂点バッファーは、IA ステージに頂点データを提供します。 インデックス バッファーは省略可能です。インデックス バッファーは、頂点バッファーから頂点にインデックスを提供します。 1 つ以上の頂点バッファーと、必要に応じて 1 つのインデックス バッファーを作成することができます。
そのバッファー リソースを作成したら、IA ステージにデータ レイアウトを記述するために、入力レイアウト オブジェクトを作成する必要があります。その後、バッファー リソースを IA ステージにバインドする必要があります。 ご利用のシェーダーがバッファーを使用しない場合は、バッファーの作成とバインドは必要ありません。 1 つの三角形を描画する単純な頂点とピクセル シェーダーの例については、「バッファーなしの入力アセンブラー ステージの使用」をご参照ください。
頂点バッファーの作成に関するヘルプについては、「方法: 頂点バッファーを作成する」をご参照ください。 インデックス バッファーの作成に関するヘルプについては、「方法: インデックス バッファーを作成する」をご参照ください。
入力レイアウト オブジェクトを作成する
入力レイアウト オブジェクトは、IA ステージの入力状態をカプセル化します。 これには、IA ステージにバインドされている入力データの記述が含まれます。 そのデータは、メモリから、1 つ以上の頂点バッファーから、IA ステージにストリームされます。 この記述では、1 つ以上の頂点バッファーからバインドされたその入力データを特定し、そのシェーダーの入力パラメーターの型に対して、その入力データの型をチェックする機能をランタイムに提供します。 この型チェックは、その型に互換性があることを確認するだけではなく、そのシェーダーに必要な各要素がバッファー リソース内で使用可能なことも確認します。
入力レイアウト オブジェクトは、入力要素の記述の配列と、コンパイル済みシェーダーへのポインターから作成されます (「ID3D11Device::CreateInputLayout」を参照)。 この配列には、1 つ以上の入力要素が含まれており、各入力要素は 1 つの頂点バッファーからの 1 つの頂点データ要素について記述します。 入力要素の説明セット全体で、IA ステージにバインドされているすべての頂点バッファーのすべての頂点データ要素について説明します。
次のレイアウトの記述では、3 つの頂点データ要素を含む 1 つの頂点バッファーについて記述します。
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ L"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,
D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ L"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12,
D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ L"NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 20,
D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
入力要素の記述では、サイズ、型、場所、目的など、頂点バッファー内の 1 つの頂点に含まれる各要素について記述します。 各行は、セマンティック、セマンティック インデックス、データ形式を使用して、データの型を特定します。 セマンティックは、データの使用方法を特定するテキスト文字列です。 この例では、最初の行は 3 コンポーネントの位置データ (xyz など) を特定し、2 行目は 2 コンポーネントのテクスチャ データ (UV など) を特定し、3 行目は通常のデータを特定します。
この入力要素の記述の例では、3 行すべてでセマンティック インデックス (2 番目のパラメーター) がゼロに設定されています。 セマンティック インデックスは、同じセマンティクスを使用する 2 つの行を区別するのに役立ちます。 この例では同様のセマンティクスがないため、セマンティック インデックスをその既定値のゼロに設定することができます。
3 番目のパラメーターは "形式" です。 形式 (「DXGI_FORMAT」を参照) では、要素ごとのコンポーネントの数と、各要素のデータのサイズを定義するデータ型を指定します。 この形式は、リソースの作成時に完全に型指定する、または要素内のコンポーネントの数を特定する DXGI_FORMAT を使用してリソースを作成することができます (ただし、データ型は未定義のままにします)。
入力スロット
次のイラスト内に示すように、データは "入力スロット" と呼ばれる入力を経由して IA ステージに入ります。 IA ステージには n 個の入力スロットがあり、入力データを提供する最大 n 個の頂点バッファーに対応するように設計されています。 各頂点バッファーは、別のスロットに割り当てる必要があります。この情報は、入力レイアウト オブジェクトが作成される際に、入力レイアウト宣言内に格納されます。 また、各バッファーの先頭から、読み取るバッファー内の最初の要素までのオフセットを指定することもできます。
次の 2 つのパラメーターは、"入力スロット" と "入力オフセット" です。 複数のバッファーを使用する際は、それらを 1 つ以上の入力スロットにバインドすることができます。 入力オフセットは、バッファーの先頭とデータの先頭の間のバイト数です。
入力レイアウト オブジェクトの再利用
各入力レイアウト オブジェクトは、シェーダー シグネチャに基づいて作成されます。これにより、API はシェーダー入力シグネチャに対して入力レイアウト オブジェクト要素を検証し、型とセマンティクスの完全一致を確認することができます。 すべてのシェーダー入力シグネチャが完全に一致する限り、多くのシェーダーに対して 1 つの入力レイアウト オブジェクトを作成することができます。
オブジェクトを入力アセンブラー ステージにバインドする
頂点バッファー リソースと入力レイアウト オブジェクトを作成したら、ID3D11DeviceContext::IASetVertexBuffers と ID3D11DeviceContext::IASetInputLayout を呼び出すことで、それらを IA ステージにバインドすることができます。 次の例では、1 つの頂点バッファーと 1 つの入力レイアウト オブジェクトの IA ステージへのバインドを示します。
UINT stride = sizeof( SimpleVertex );
UINT offset = 0;
g_pd3dDevice->IASetVertexBuffers(
0, // the first input slot for binding
1, // the number of buffers in the array
&g_pVertexBuffer, // the array of vertex buffers
&stride, // array of stride values, one for each buffer
&offset ); // array of offset values, one for each buffer
// Set the input layout
g_pd3dDevice->IASetInputLayout( g_pVertexLayout );
入力レイアウト オブジェクトのバインドには、そのオブジェクトへのポインターのみが必要です。
前の例では、1 つの頂点バッファーがバインドされています。ただし、ID3D11DeviceContext::IASetVertexBuffers への 1 回の呼び出しで、複数の頂点バッファーをバインドすることができます。次のコードでは、3 つの頂点バッファーをバインドする、そのような呼び出しを示します。
UINT strides[3];
strides[0] = sizeof(SimpleVertex1);
strides[1] = sizeof(SimpleVertex2);
strides[2] = sizeof(SimpleVertex3);
UINT offsets[3] = { 0, 0, 0 };
g_pd3dDevice->IASetVertexBuffers(
0, //first input slot for binding
3, //number of buffers in the array
&g_pVertexBuffers, //array of three vertex buffers
&strides, //array of stride values, one for each buffer
&offsets ); //array of offset values, one for each buffer
インデックス バッファーは、ID3D11DeviceContext::IASetIndexBuffer を呼び出すことで IA ステージにバインドされます。
プリミティブ型を指定する
入力バッファーがバインドされたら、頂点をプリミティブにアセンブルする方法を IA ステージに指示する必要があります。 これを行うには、ID3D11DeviceContext::IASetPrimitiveTopology を呼び出して、プリミティブ型を指定します。次のコードはこの関数を呼び出して、このデータを隣接しない三角形リストとして定義します。
g_pd3dDevice->IASetPrimitiveTopology( D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
残りのプリミティブ型は、D3D_PRIMITIVE_TOPOLOGY 内にリスト化されます。
Draw メソッドを呼び出す
入力リソースがパイプラインにバインドされたら、アプリケーションは Draw メソッドを呼び出してプリミティブをレンダリングします。 次の表内に示すように、いくつかの Draw メソッドがあります。インデックス バッファーを使用するもの、インスタンス データを使用するもの、ストリーミング出力ステージからのデータを入力アセンブラー ステージへの入力として再利用するものなどがあります。
Draw メソッド | 説明 |
---|---|
ID3D11DeviceContext::Draw | インデックスのない、インスタンス化されていないプリミティブを描画します。 |
ID3D11DeviceContext::DrawInstanced | インデックスのない、インスタンス化されたプリミティブを描画します。 |
ID3D11DeviceContext::DrawIndexed | インデックス付きの、インスタンス化されていないプリミティブを描画します。 |
ID3D11DeviceContext::DrawIndexedInstanced | インデックス付きの、インスタンス化されたプリミティブを描画します。 |
ID3D11DeviceContext::DrawAuto | ストリーミング出力ステージから取得された入力データから、インデックスのない、インスタンス化されていないプリミティブを描画します。 |
各 Draw メソッドは、1 つのトポロジの種類をレンダリングします。 レンダリング中、不完全なプリミティブ (十分な頂点がない、インデックスが不足している、部分的なプリミティブ、など) は、通知なしで破棄されます。
関連トピック