Direct3Dのパイプライン - yoshimune/LearningDirectX11 GitHub Wiki
Direct3D 11 のプログラマブルパイプラインは、リアルタイムゲームのグラフィックを生成するためにデザインされています。このセクションはDirect3D 11 のプログラマブルパイプラインの解説をします。
↓のダイアグラムは、入力から出力までの、それぞれのプログラマブルステージでのデータフローを表しています。
https://docs.microsoft.com/en-us/windows/desktop/direct3d11/overviews-direct3d-11-graphics-pipeline
Direct3D 11 のグラフィックスパイプラインは、Direct3D 10と同じステージサポートしています。また、追加されたステージもあります。
Direct3D 11 APIを使って全てのステージの設定を行うことができます。シェーダーコア機能のブロック(ダイアグラム中で角丸長方形部分)はHLSLを使ってプログラミングすることができます。ご覧のように、これにより、パイプラインは非常に柔軟で適応性があります。
InputAssemblerStage
Direct3D 10 以上のAPIは、パイプライン中の機能部分と入力部分を分離しました。パイプライン最初のステージは入力アセンブラ(input-assembler(IA))ステージです。
入力アセンブラステージの目的は、プリミティブデータ(ポイント、ライン、三角形など)をユーザーが用意したバッファから読み込み、そのデータを他のパイプラインステージが使用するプリミティブにアセンブルすることです。入力アセンブラステージは、頂点をいくつかの異なるプリミティブタイプ(line list, triangle strips、隣接プリミティブなど)にアセンブルすることができます。新しいプリミティブタイプはジオメトリシェーダーサポートに含まれました。
隣接情報はアプリケーション中のジオメトリシェーダー内のみで確認することができます。もしジオメトリシェーダーが三角形の隣接情報とともに呼び出された場合、インスタンスでは、入力データに三角形毎の3つの頂点と三角形ごとの隣接情報データが含まれます。
プリミティブをアセンブルしている最中、入力アセンブラの2つ目の目的は、シェーダーを効率よく作成するためのセマンティクス(system-genetrated values)をアタッチすることです。セマンティクスはテキスト文字列です。3つ全てのシェーダーステージはcommon shader core から構築されています。また、シェーダーコアはセマンティクス(例えば、プリミティブID・インスタンスID・頂点ID)を使用します。これによりシェーダーステージの加工されていないプリミティブ・インスタンス・頂点に限り処理不可を低減できます。
パイプラインダイアグラムで見たとおり、一つの入力アセンブラステージはメモリからデータを読み込みます。そのデータをプリミティブにアセンブルし、セマンティクスをアタッチして頂点シェーダステージへ渡します。
Vertex Shader Stage
バーテックスシェーダステージ(vertex-shader(VS)stage)は入力アセンブラから渡された頂点を処理します。頂点毎に移動・スキニング・モーフィング・頂点ライティングなどの処理を行います。バーテックスシェーダは常に単一の頂点入力を取り扱い、単一の結果を提供します。バーテックスシェーダステージはパイプライン上に常に存在しています。もし頂点の更新が必要ない場合でも、バーテックスシェーダを作成しパイプラインにセットする必要があります。
Vertex Shader
それぞれのバーテックスシェーダの頂点入力は、最大16個の32bitベクトル(最大4コンポーネント)で構成することができ、それぞれの出力頂点データは同じ量の最大16個32bit4コンポーネントベクトルで構成することができます。全てのバーテックスシェーダは最小でも一つの入力と一つの出力を持つ必要があります。
バーテックスシェーダステージは2つのセマンティクス(VertexIDとIndexID)を利用することができます。VertexIDとInstanceID両者とも頂点レベルで意味があるため、ハードウェアによって生成されたIDは最初のステージのみ渡されます。
バーテックスシェーダは常に全ての頂点に対して実行されます。隣接を含む入力プリミティブトポロジーの隣接頂点も含みます。バーテックスシェーダの実行回数はVSInvocationsパイプライン統計を使用してCPUから照会できます。
Tessellation Stages
Direct3D 11 ランタイムは3つのテッセレーションを実装する新しいステージをサポートしています。GPU上で粗いサブディビジョンサーフェスを高精細なプリミティブに変換します。テッセレーションは高次のサーフェイスをレンダリングに適した構造にタイリングします。
ハードウェアでテッセレーションを実装することにより、グラフィックスパイプラインはよりポリゴン数の低いモデルを評価することができ、より高精細なディティールをレンダリングすることができます。ソフトウェアテッセレーションを行うこともできますが、ハードウェアで実装されたテッセレーションは信じられない量のビジュアルディティール(ディスプレイスメントマッピングを含む)をモデルサイズやリフレッシュレートの遅延なしに生成することができます。
New Pipeline Stages
テッセレーションはGPUを四角パッチ・三角パッチ・等地ラインで構成されたサーフェイスをより詳細なサーフェイスに変換するための計算に使用します。それぞれのパッチは三角形・点・ラインに分割されます。Direct3D 11 パイプラインは3つのパイプラインステージを使用してテッセレーションを実装します。
Shader | Discription |
---|---|
Hull-Shader Stage | 各入力パッチ(四角形・三角形・またはライン)に対応するジオメトリパッチ(およびパッチ定数)を生成するプログラム可能なシェーダーステージ |
Tessellator Stage | 固定関数パイプラインステージ。ジオメトリパッチを表すドメインのサンプリングパターンを作成し、これらのサンプルを接続する一連の小さなオブジェクト(三角形、点、ライン)を生成する。 |
Domain-Shader Stage | プログラマブルシェーダーステージ。それぞれのドメインサンプルと対応する頂点位置を計算する。 |
Geometry Shader Stage
ジオメトリシェーダー(geometry-shader(GS))ステージは、入力された頂点をもってアプリケーション指定のシェーダコードを実行し、生成された頂点を出力する機能を有します。
The Geometry Shader
一つの頂点を取り扱うバーテックスシェーダと違い、ジオメトリシェーダーの入力は全てのプリミティブ(2つの頂点からなるライン、3つの頂点からなる三角形、一つの頂点からなる点)の頂点となります。ジオメトリシェーダーは辺に隣接する頂点データを入力(追加されたラインの2つの頂点、追加された三角形の3つの頂点)として運ぶことができます。
Stream-Output Stage
ストリームアウトプット(stream-output)ステージの目的は連続的にジオメトリシェーダステージ(またはジオメトリシェーダステージが使われていない場合はバーテックスシェーダステージ)頂点データを一つ以上のバッファに出力することです。
Rasterizer Stage
ラスタライザステージはベクトル情報(シェイプかプリミティブで構成された)をラスターイメージ(ピクセル)に変換することです。リアルタイムに3Dグラフィックスを表示するためです。
ラスタライズ中、各プリミティブはピクセルに変換されます。頂点データの値は線形補間されます。ラスタライザは頂点を視錐台でクリッピングし、パースペクティブで分離し、2Dビューポートにプリミティブをマッピングし、どのようにピクセルシェーダーを起動するかを決定します。ピクセルシェーダーを補助的に使用している間は、ラスタライザステージは常にクリッピング、パースペクティブを点が同質空間に変換するために分離し、頂点をビューポートにマッピングします。
ラスタライザステージに来たベクトル(x,y,z,w)は同質クリップ空間となることを想定されています。この座標系では、X軸は右、Y軸は上、Z軸は奥行きを表します。
パイプラインにピクセルシェーダーがない状態(ID3D11DeviceContext::PSSetShader
でピクセルシェーダーステージにNULlをセットする)にし、デプス・ステンシルテストを無効にする(D3D11_DEPTH_STENCIL_DESC
でDepthEnableとStencilEnableをFALSEにする)とラスタライズを無効にできます。無効のあいだ、ラスタライズに関連するパイプラインカウンターは更新されません。このことについての解説はrasterization rulesで解説されています。
階層型Zバッファの最適化を実装するハードウェアでは、ピクセルシェーダステージをNULLに設定してデプス・ステンシルテストを有効にしてZバッファをプリロードすることができます。
Pixel Shader Stage
ピクセルシェーダ(PS)ステージはピクセルごとのライティングやポストプロセッシングのような豪華なシェーディングテクニックを可能にします。ピクセルシェーダーは定数、テクスチャデータ、線形補間された頂点データ、その他のピクセルごとに出力に使用するデータが含まれるプログラムです。しかし、シェーダにNULLを指定して実行を回避することができます。
The Pixel Shader
テクスチャのマルチサンプリングのとき、ピクセルシェーダはピクセル一つ毎に起動され、マルチサンプリング毎にデプス・ステンシルテストが実行されます。デプス・ステンシルテストに渡されたサンプルはピクセルシェーダの出力カラーで更新されます。
ピクセルシェーダの組み込み関数は、スクリーン空間のxまたはyに関しての量の導関数を生成または使用します。もっともよく使用される導関数は、テクスチャサンプリングに利用されるLOD(level-of-detail)の算出で、異方性フィルタリング、異方性軸にそったサンプリングを行います。典型的には、ハードウェア実装で複数のピクセル(例えば2x2)上でピクセルシェーダを同時に実行するので、ピクセルシェーダーで計算する導関数は、隣接するピクセルにおける実行する同じ実行点の値の差分として合理的に近似できます。
Inputs
パイプラインがジオメトリシェーダなしに設定されたとき、ピクセルシェーダは16個 32bit 4コンポーネントの入力に制限されます。ジオメトリシェーダを使う場合は、32個、32bit、4コンポーネントの入力までとなります。
ピクセルシェーダ入力データは頂点属性(線形補間された)を含むか、プリミティブごとの定数を扱うことができます。ピクセルシェーダー入力はプリミティブの頂点属性からラスタライザで線形補間されます。線形補間モードはデフォルトで宣言されます。もしプリミティブがラスタライズ前にクリップされた場合、クリッピング処理中に補間モードが維持されます。
頂点属性は、ピクセルシェーダ中心位置で線形補間(または評価)されます。