ストリームアウトプット
今回のパートではストリームアウトプットステージ(英訳:Stream-Output Stage)について見ていきます。
ストリームアウトプットステージはジオメトリシェーダの次に実行されるステージになり、グラフィックスパイプラインで処理したプリミティブをバッファに出力することができます。
ドキュメント:ストリームアウトプットステージ
(日本語)
(英語)
概要
それではストリームアウトプットステージの使い方、設定について見ていきましょう。
対応するプロジェクトはPart11_StreamOutputになります。
シェーダの生成
ストリームアウトプットを利用するときに必要な設定について見ていきます。
ID3D11DeviceContext::SOSetTargets
ID3D11DeviceContext::SOSetTargetsでストリームアウトプットの出力先バッファを設定します。
出力先となるバッファは複数設定できます。
生成したバッファを別のところで使う際はストリームアウトプットステージから外さないと使えないので注意してください。
ドキュメント:ID3D11DeviceContext::SOSetTargets
(日本語)
(英語)
出力先のバッファの作成
ストリームアウトプットの出力先のバッファを作る際はBindFlagsにD3D11_BIND_STREAM_OUTPUTを指定する必要があります。
また、生成するプリミティブの上限もバッファ生成時に決めないといけません。
シェーダの生成
さて、ストリームアウトプットステージは出力先を設定すると自動的に有効となり、ジオメトリシェーダの出力を設定したバッファに書き込んでくれます。
サンプルではピクセルシェーダを使用していませんが、もちろんストリームアウトプットステージを使用しながら画面描画を行うこともできます。
出力にジオメトリシェーダを使用しますのでそれを用意する必要があるのですが、その時ID3D11GeometryShaderを作成するには専用の関数を使用する必要があります。
その関数はID3D11Device::CreateGeometryShaderWithStreamOutput になります。
ドキュメント:ID3D11Device::CreateGeometryShaderWithStreamOutput
(日本語)
(英語)
ID3D11Device::CreateGeometryShaderWithStreamOutputの引数一部
- RasterizedStream
画面描画を行う際、出力した頂点の中で使用するものの添字になります。
画面描画を行わない場合はD3D11_SO_NO_RASTERIZED_STREAMを指定してください。
出力する頂点のレイアウトはD3D11_SO_DECLARATION_ENTRYで設定します。
その内容は頂点レイアウトに似たものとなります。
ドキュメント:D3D11_SO_DECLARATION_ENTRY
(日本語)
(英語)
D3D11_SO_DECLARATION_ENTRY
- Stream
0から始まるストリーム番号になります。
- SemanticName
要素のセマンティクスになります。
指定できるものは"POSITION"、"NORMAL"、または "TEXCOORD0"になります。
これにnullptrを設定した場合は、この要素はデータが書き込まれていない隙間とみなされComponentCountに5以上の値を設定できるようになります。
- SemanticIndex
セマンティクスの0から始まる番号になります。
- StartComponent, ComponentCount
使用する要素の範囲を指定します。
StartComponentが2でComponentCountが3なら、yzw成分を使用します。
- OutputSlot
出力するストリームアウトプットステージに設定したバッファへの添字になります。
以上でストリームアウトプットステージの設定およびシェーダの作成についての説明を終わります。
ID3D11DeviceContext::DrawAuto
ストリームアウトプットで生成した頂点データは頂点バッファとして描画に使用できます。
が、実際に生成された頂点数はそのままだとわかりません。
頂点数を調べる方法は存在しますが、この場合ID3D11DeviceContext::DrawAutoという特別なドローコールが用意されています。
ドキュメント:ID3D11DeviceContext::DrawAuto
(日本語)
(英語)
使い方については特に説明はありません。
ストリームアウトプットによって生成された頂点データを入力アセンブラステージに設定し、ID3D11DeviceContext::DrawAutoを呼び出すだけで描画ができます。
まとめ
以上でストリームアウトプットの説明は終わります。
このステージを利用することでGPUの力を借りたプリミティブ生成が可能となりますので、活用できるときは活用しましょう。