保守的なラスター化Direct3D 12
保守的なラスター化は、ピクセル レンダリングに確実性を追加します。これは、特に衝突検出アルゴリズムに役立ちます。
概要
保守的なラスター化とは、レンダリングしたプリミティブによって少なくとも一部が覆われているピクセルを、すべてラスター化することです。これは、ピクセル シェーダーが呼び出されることを意味します。 通常の動作はサンプリングですが、これは保守的なラスター化が有効な場合は使用されません。
保守的なラスター化は、衝突検出、オクルージョン カリング、タイル レンダリングの確実性など、さまざまな状況で役立ちます。
たとえば、次の図は、ラスタライザーに表示されるように (つまり、16.8 の固定小数点頂点座標を使用するように)、保守的なラスター化を使用してレンダリングされた緑色の三角形を示しています。 茶色の領域は "不確定領域" と呼ばれます。これは、ラスタライザーのプリミティブが元の浮動小数点の頂点座標に対して変わらないことを保証するために必要な、三角形の幅のある境界を表す概念的な領域です。 各頂点の赤い正方形は、不確定領域が (掃引される正方形として) どのように計算されるかを示しています。
大きな灰色の正方形は、レンダリングされるピクセルを示しています。 ピンク色の正方形は、三角形の辺がピクセルの辺と交差するときに有効になる "左上ルール" を使用してレンダリングされるピクセルを示しています。 偽陽性 (レンダリングされてはいけないピクセル セット) が発生する可能性があります。これは、通常、システムによってカリングされますが、常にそうであるとは限りません。
パイプラインの操作
ラスター化ルール操作
保守的なラスター化モードでは、ラスター化ルールは、前述の左上ルールとピクセル カバレッジを例外として、保守的なラスター化モードが有効でない場合と同じように適用されます。 16.8 固定小数点ラスタライザーの精度を使用する必要があります。
ハードウェアが完全浮動小数点頂点座標を使用している場合に覆われないピクセルは、それらが固定小数点ドメインの半ピクセルより大きくない不確定領域内にある場合にのみ覆われます。 将来のハードウェアは、階層 2 で指定された厳密な不確定領域に達すると予想されます。 この要件により、スライバー三角形には必要以上の幅は与えられなくなることに注意してください。
同様の有効な不確定領域は InnerCoverage
にも適用されますが、この場合にはより大きな不確定領域を必要とする実装がないため、より厳密になります。 詳細については、「InnerCoverage 操作」を参照してください。
内側および外側の不確定領域は、固定小数点ドメインのサブピクセル グリッドの半分、つまりピクセルの 1/512 のサイズ以上である必要があります。 これは、有効な最小の不確定領域です。 1/512 という数は、16.8 固定小数点ラスタライザー座標表現と、浮動小数点の頂点座標を 16.8 固定小数点座標に変換するときに適用される最も近い値への丸め規則に由来します。 1/512 は、ラスタライザーの精度が変わると変更される可能性があります。 実装でこの最小不確定領域を実装する場合、不確定領域の辺またはコーナーがピクセルの辺またはコーナーと一致するときは左上ルールに従う必要があります。 不確定領域の切り取られた辺は、最も近い頂点として扱う必要があります。つまり、これらは、関連付けられている頂点で結合される 2 つの辺としてカウントされます。 最小不確定領域を使用する場合は、左上ルールが必要です。使用しないと、保守的なラスター化の実装において、保守的なラスター化モードが無効な場合に覆われる可能性のあるピクセルのラスター化に失敗する可能性があります。
次の図は、固定小数点ドメインのプリミティブの辺の周囲に正方形を掃引することによって生成された有効な外側の不確定領域を示しています (つまり、頂点は 16.8 固定小数点表現で量子化されています)。 この正方形の寸法は、有効な外側の不確定領域のサイズに基づいています。ピクセルの 1/2 の場合、正方形の幅と高さは 1 ピクセルです。ピクセルの 1/512 の場合、正方形の幅と高さは 1/256 ピクセルです。 緑色の三角形は、指定されたプリミティブを表します。赤い点線は、過大評価された保守的なラスター化の境界を表します。黒い実線の正方形は、プリミティの辺に沿って掃引された正方形を表します。青い格子縞の領域が、外側の不確定領域です。
マルチサンプリング操作
RenderTarget/DepthStencil サーフェス内のサンプルの数 (または ForcedSampleCount が使用されているかどうか) に関係なく、すべてのサンプルは保守的なラスター化によってラスター化されたピクセルでカバーされます。 個々のサンプルの位置は、それらがプリミティブに含まれるかどうかについてはテストされません。
SampleMask 操作
SampleMask ラスタライザー状態は、InputCoverage
に対して保守的なラスター化が有効でない場合と同じように適用されますが、InnerCoverage
には影響しません (つまり、InnerCoverage
で宣言された入力に AND 操作されません)。 これは、MSAA サンプルがマスクアウトされているかどうかとは無関係であるため InnerCoverage
です。0 InnerCoverage
は、ピクセルが完全にカバーされる保証がないことを意味し、サンプルが更新されないことを意味するだけです。
深度テストまたはステンシル テスト操作
保守的にラスター化されたピクセルに対しては、深度テストまたはステンシル テストは、保守的なラスター化が有効でないときにすべてのサンプルが覆われる場合と同じように行われます。
覆われるすべてのサンプルが対象になると、深度補外が発生する可能性があります。これは有効であり、保守的なラスター化が有効でない場合に指定されているように、ビューポートにクランプする必要があります。 これは、サンプル数が 1 を超える RenderTarget にピクセル周波数補間モードを使用した場合と似ていますが、保守的なラスター化では、外挿可能なものは、固定関数深度テストの対象の深度値になります。
深度補外での早期深度カリング動作は未定義です。 これは、一部の早期深度カリング ハードウェアで、外挿された深度値を正しくサポートできないためです。 ただし、外挿された深度値をサポートできるハードウェアであっても、深度補外が存在する場合の早期深度カリング動作は問題になります。 この問題は、ピクセル シェーダーの入力深度をラスター化対象のプリミティブの最小深度と最大深度の値にクランプし、その値を oDepth
(ピクセル シェーダーの出力深度レジスタ) に書き込むことで回避できます。 この場合、oDepth
書き込みのため、実装で早期深度カリングを無効にする必要があります。
ヘルパー ピクセル操作
ヘルパー ピクセル ルールは、保守的なラスター化が有効でない場合と同じように適用されます。 その一環として、ヘルパー ピクセルを含むすべてのピクセルでは、「InputCoverage
操作」セクションで指定されているとおりに InputCoverage
を正確に報告する必要があります。 そのため、完全に覆われないピクセルでは 0 のカバレッジが報告されます。
出力カバレッジ操作
保守的にラスター化されるピクセルに対する出力カバレッジ (oMask
) の動作は、保守的なラスター化が有効でないときにすべてのサンプルが覆われる場合と同様です。
InputCoverage 操作
保守的なラスター化モードでは、この入力レジスタは、特定の保守的にラスター化されるピクセルに対し保守的なラスター化が有効でないときに、すべてのサンプルが覆われる場合と同じように入力されます。 つまり、既存のすべての相互作用が適用され ( SampleMask が適用されるなど)、LSB からの最初の n ビット InputCoverage
は、慎重にラスター化されたピクセルに対して 1 に設定されます。たとえば、ピクセルごとの n 個のサンプル RenderTarget バッファーまたは DepthStencil バッファーが Output Merger でバインドされているか、n 個のサンプル ForcedSampleCount が指定されています。 残りのビットは 0 になります。
この入力は、保守的なラスター化の使用に関係なくシェーダーで使用できます。ただし、保守的なラスター化では動作が変更され、覆われるすべてのサンプルのみが表示されるようになります (ヘルパー ピクセルの場合は何も表示されません)。
InnerCoverage 操作
この機能は階層 3 で必須であり、またこの階層でのみ使用可能です。 実装でサポートされる階層が階層 3 未満の場合、このモードを使用するシェーダーでは、ランタイムによるシェーダーの作成は失敗します。
ピクセル シェーダーには、InnerCoverage
という、32 ビットのスカラー整数のシステム生成値があります。 これは、特定の保守的にラスター化されるピクセルが完全に現在のプリミティブの内側にあることが保証されている場合に限り、そのピクセルについて、最下位ビットからビット 0 が 1 に設定されるビット フィールドです。 他のすべての入力レジスタ ビットは、ビット 0 が設定されていないときに 0 に設定する必要がありますが、ビット 0 が 1 に設定されているときは未定義です (つまり、このビット フィールドはブール値を表します。false は厳密に 0 である必要がありますが、true は 0 以外の任意の奇数値 (すなわち、ビット 0 が設定されている状態) でかまいません)。 この入力は、過小評価される保守的なラスター化情報に使用されます。 この情報から、現在のピクセルが完全にジオメトリの内側にあるかどうかがピクセル シェーダーに通知されます。
これには、現在の描画が動作している解像度以上の解像度でのスナップ エラーを考慮する必要があります。 偽陽性 (現在の描画が動作している解像度以上の解像度でのスナップ エラーに対して、ピクセルが完全に覆われないときに InnerCoverage
ビットを設定すること) が発生してはいけませんが、偽陰性は許可されます。 まとめると、実装では、ラスタライザーの完全浮動小数点頂点座標を持たない可能性のあるピクセルを、完全に覆われるものと誤って識別してはいけません。
ハードウェアが完全浮動小数点の頂点座標を使用している場合に完全に覆われるピクセルは、それらが、固定小数点ドメインのサブピクセル グリッドのサイズ、つまり 1/256 ピクセル以下のサイズでなければならない内側の不確定領域と交差する場合にのみ省略できます。 言い換えると、内側の不確定領域の内側の境界内に完全に含まれるピクセルは、完全に覆われるものとしてマークする必要があります。 不確定領域の内側の境界は、下図において太い黒の点線で示されています。 1/256 という数字は、16.8 固定小数点ラスタライザー座標表現に由来します。これは、ラスタライザーの精度が変わると変更される可能性があります。 この不確定領域は、ラスタライザーで浮動小数点頂点座標を固定小数点頂点座標に変換することによって発生するスナップ エラーを考慮するのに十分なサイズです。
「ラスター化ルール操作」に定義されているのと同じ 1/512 の最小不確定領域要件がここでも適用されます。
次の図は、固定小数点ドメインのプリミティブの辺の周囲に正方形を掃引することによって生成された有効な内側の不確定領域を示しています (つまり、頂点は 16.8 固定小数点表現で量子化されています)。 この正方形の寸法は、有効な内側の不確定領域のサイズに基づいています。ピクセルの 1/256 の場合、正方形の幅と高さは 1/128 ピクセルです。 緑色の三角形は、指定されたプリミティブを表します。太い黒の点線は、内側の不確定領域の境界を表します。黒い実線の正方形は、プリミティブの辺に沿って掃引された正方形を表します。オレンジ色の格子縞の領域が、内側の不確定領域です。
InnerCoverage
の使用は、ピクセルが保守的にラスター化されるかどうかには影響しません。つまり、保守的なラスター化モードが有効な場合は、これらの InputCoverage
モードのいずれを使用しても、どのピクセルがラスター化されるかには影響しません。 したがって、InnerCoverage
が使用され、ジオメトリで完全には覆われないピクセルをピクセル シェーダーにより処理しているとき、その値は 0 になりますが、ピクセル シェーダーの呼び出しによってサンプルが更新されます。 これは、サンプルが更新されない、InputCoverage
が 0 の場合とは異なります。
この入力は InputCoverage
と相互に排他的です。両方ともを使用することはできません。
InnerCoverage
にアクセスするには、いずれかのピクセル シェーダー入力レジスタから単一のコンポーネントとして宣言する必要があります。 宣言の補間モードは一定である必要があります (補間は適用されません)。
InnerCoverage
ビット フィールドは、深度テストとステンシル テストの影響を受けず、SampleMask ラスタライザー状態と AND 操作されることもありません。
この入力は、保守的なラスター化モードでのみ有効です。 保守的なラスター化が有効でない場合、InnerCoverage
は未定義の値を生成します。
ヘルパー ピクセルの必要性から発生する一方で、それ以外の場合はプリミティブで覆われないピクセル シェーダーの呼び出しでは、InnerCoverage
レジスタを 0 に設定する必要があります。
属性補間操作
属性補間モードは変更されず、保守的なラスター化が有効でない場合と同じように作用します。この場合、ビューポートでスケーリングされ固定小数点変換された頂点が使用されます。 保守的にラスター化されるピクセル内のすべてのサンプルは覆われると見なされるため、サンプル数が 1 より大きいときにピクセル周波数補間モードが RenderTarget で使用される場合と同様に、値を外挿することは有効です。 重心補間モードでは、対応する非重心補間モードと同じ結果が得られます。重心の概念は、サンプル カバレッジが完全または 0 のいずれかであるこのシナリオでは意味がありません。
保守的なラスター化では、縮退三角形がピクセル シェーダー呼び出しを生成できます。したがって、縮退三角形では、頂点 0 に割り当てられた値をすべての補間値に使用する必要があります。
クリッピング操作
保守的ラスター化モードが有効で深度クリップが無効になっている場合 ( DepthClipEnable Rasterizer State が FALSE に設定されている場合)、実装に応じて、プリミティブのセグメントの属性補間が 0 <= z <= w の範囲外になる場合があります。定数値は、プリミティブが関連する平面と交差するポイント (近くまたは遠い) から使用されます。 または 属性補間は、保守的ラスター化モードが無効になっている場合と同様に動作します。 ただし、深度値の動作は、保守的なラスター化モードにかかわらず同じです。すなわち、深度範囲の外側にあるプリミティブには、依然としてビューポート深度範囲の最も近い限度値を与える必要があります。 0 <= z <= w 範囲内の属性補間の動作は変更しない必要があります。
クリップ距離操作
クリップ距離は、保守的なラスター化モードが有効な場合に有効で、保守的なラスター化が有効でないときにすべてのサンプルが覆われる場合と同様に、保守的にラスター化されるピクセルに対して動作します。
保守的なラスター化によって W 頂点座標が外挿される可能性があり、W <= 0 が発生する可能性があることに注意してください。 これにより、ピクセルごとのクリップ距離の実装が、無効な W の値でパースペクティブ分割されたクリップ距離に作用する可能性があります。 クリップ距離の実装では、頂点座標 W <= 0 のピクセルに対するラスター化の呼び出しを防ぐ必要があります (たとえば、保守的なラスター化モードの場合の外挿による)。
ターゲットに依存しないラスター化操作
保守的なラスター化モードは、ターゲットに依存しないラスター化 (TIR) と互換性があります。 TIR のルールと制限が適用され、保守的にラスター化されるピクセルに対する動作は、すべてのサンプルが覆われる場合と同様です。
IA プリミティブ トポロジ操作
保守的なラスター化は、線または点のプリミティブには定義されません。 したがって、保守的なラスター化が有効な場合に点または線をラスタライザー ユニットに入力すると、点または線を指定するプリミティブ トポロジで未定義の動作が発生します。
デバッグ レイヤーの検証により、アプリケーションがこれらのプリミティブ トポロジを使用していないことが確認されます。
クエリ操作
保守的にラスター化されるピクセルに対して、クエリは、保守的なラスター化が有効でないときにすべてのサンプルが覆われる場合と同様に動作します。 たとえば、控えめにラスター化されたピクセルの場合、(D3D12_QUERY_TYPEから) D3D12_QUERY_TYPE_OCCLUSIONと D3D12_QUERY_TYPE_PIPELINE_STATISTICSは、すべてのサンプルをカバーするときに保守的なラスター化が有効になっていない場合と同じように動作する必要があります。
保守的なラスター化モードでは、保守的にラスター化されるピクセルごとにピクセル シェーダーの呼び出しをインクリメントする必要があります。
カリング状態操作
保守的なラスター化モードではすべてのカリング状態が有効であり、保守的なラスター化が有効でない場合と同じルールに従います。
保守的なラスター化を複数の解像度にわたってそれ自体と比較した場合、または保守的なラスター化が有効でない場合は、一部のプリミティブの向きが不一致になる可能性があります (一方が裏向き、もう一方が表向き)。 アプリケーションでは、システム生成値を使用せず、(D3D12_CULL_MODEから) D3D12_CULL_MODE_NONEを使用することで、この不確実性を IsFrontFace
回避できます。
IsFrontFace 操作
IsFrontFace
システム生成値は、保守的なラスター化モードでの使用に有効であり、保守的なラスター化が有効でないときに定義された動作に従います。
塗りつぶしモード操作
保守的なラスター化の唯一の有効な D3D12_FILL_MODE はD3D12_FILL_SOLIDです。その他の塗りつぶしモードは、ラスタライザーの状態の無効なパラメーターです。
これは、D3D12 機能仕様では、ワイヤフレームの塗りつぶしモードで三角形の辺を線に変換し、線のラスター化ルールに従う必要があることが指定されている一方、線の保守的なラスター化動作が定義されていないためです。
実装の詳細
Direct3D 12 でサポートされているラスター化の種類は、"過大評価される保守的なラスター化" と呼ばれることがあります。 また、"過小評価される保守的なラスター化" という概念もあります。これは、レンダリングされたプリミティブによって完全に覆われるピクセルのみがラスター化されることを意味します。 過小評価される保守的なラスター化の情報は、入力カバレッジ データを使用しピクセル シェーダーを介して使用できます。ラスター化モードとして使用可能なのは、過大評価される保守的なラスター化のみです。
プリミティブの一部がピクセルと重なる場合、そのピクセルは覆われると見なされ、ラスター化されます。 プリミティブの辺またはコーナーがピクセルの辺またはコーナーに沿う場合の "左上ルール" の適用は、実装に左右されます。 ただし、縮退三角形をサポートする実装では、辺またはコーナーに沿った縮退三角形は、少なくとも 1 つのピクセルを覆う必要があります。
保守的なラスター化の実装はハードウェアによって異なり、偽陽性、つまりピクセルが覆われると見なす誤った判定につながる可能性があります。 これは、ラスター化で使用される固定小数点頂点座標に固有のプリミティブの拡張またはスナップ エラーなど、実装ごとの詳細が原因で発生する可能性があります。 (固定小数点頂点座標に関して) 偽陽性が有効である理由は、実装でポストスナップされた頂点 (すなわち、浮動小数点からラスタライザーで使用される 16.8 固定小数点へ変換された頂点座標) に対するカバレッジ評価を行うことができるようにする一方で、元の浮動小数点頂点座標によって生成されるカバレッジを尊重するために、ある程度の偽陽性が必要であるためです。
保守的なラスター化の実装では、非縮退ポストスナップ プリミティブの浮動小数点頂点座標に関する偽陰性は生じません。プリミティブのいずれかの部分がピクセルのいずれかの部分と重なる場合、そのピクセルはラスター化されます。
縮退している三角形 (インデックス バッファー内の重複するインデックスまたは 3D の共線)、または固定小数点変換後に縮退する三角形 (ラスタライザー内の共線の頂点) は、カリングしてもしなくてもかまいません。どちらも有効な動作です。 縮退している三角形は裏向きと見なす必要があるため、アプリケーションで特定の動作が必要な場合は、裏向きカリングを使用するか、表向きのテストを行うことができます。 縮退三角形では、頂点 0 に割り当てられた値をすべての補間値に使用します。
ハードウェアがこの機能をサポートしていない可能性に加えて、ハードウェア サポートには 3 つの階層があります。
- 階層 1 では、最大 1/2 ピクセルの不確定領域が強制され、ポストスナップ縮退がサポートされません。 これは、タイル レンダリング、テクスチャ アトラス、ライト マップの生成、およびサブピクセル シャドウ マップに適しています。
- 階層 2 では、最大不確定領域が 1/256 に縮小され、ポストスナップ縮退のカリングを行わないことが求められます。 この階層は、CPU ベースのアルゴリズムの高速化 (ボクセル化など) に役立ちます。
- 階層 3 では、最大 1/256 の不確定領域が保持され、内側の入力カバレッジのサポートが追加されます。 内側の入力カバレッジにより、新しい値
SV_InnerCoverage
が高レベル シェーディング言語 (HLSL) に追加されます。 これは、ピクセル シェーダーへの入力時に指定できる 32 ビットのスカラー整数であり、過小評価される保守的なラスター化情報 (つまり、ピクセルが完全に覆われることが保証されているかどうか) を表します。 この階層は、オクルージョン カリングに有用です。
API の概要
次のメソッド、構造体、列挙型、およびヘルパー クラスは、保守的なラスター化を参照します。
- D3D12_RASTERIZER_DESC : ラスタライザーの説明を保持する構造体。
- D3D12_CONSERVATIVE_RASTERIZATION_MODE : モードの列挙値 (オンまたはオフ)。
- D3D12_FEATURE_DATA_D3D12_OPTIONS : サポート層を保持する構造体。
- D3D12_CONSERVATIVE_RASTERIZATION_TIER : ハードウェアによるサポートの各層の列挙値。
- CheckFeatureSupport: サポートされている機能にアクセスするためのメソッド。
- CD3DX12_RASTERIZER_DESC : ラスタライザーの説明を作成するためのヘルパー クラス。
関連トピック