フロー制御の制限事項
ピクセル シェーダー フロー制御命令には、命令に含めることができる入れ子のレベルの数に影響する制限があります。 さらに、グラデーション命令を使用してピクセル単位のフロー制御を実装するには、いくつかの制限があります。
手記
*_4_0_level_9_x HLSL シェーダー プロファイルを使用する場合は、Direct3D 9 対応ハードウェアをサポートするために、シェーダー モデル 2.x プロファイルを暗黙的に使用します。 シェーダー モデル 2.x プロファイルでは、シェーダー モデル 4.x 以降のプロファイルよりも制限されたフロー制御動作がサポートされます。
ピクセル シェーダー命令の深度数
ps_2_0はフロー制御をサポートしていません。 他のピクセル シェーダー バージョンの制限事項を次に示します。
ps_2_xの命令深度数
各命令は、1 つ以上の入れ子の深さの制限に対してカウントされます。 次の表に、各命令が既存の深度を加算または減算する深度数を示します。
命令 | 静的な入れ子 | 動的な入れ子 | loop/rep nesting | 呼び出しの入れ子 |
---|---|---|---|---|
bool - ps の場合の | 1 | 0 | 0 | 0 |
if_comp - ps | 0 | 1 | 0 | 0 |
pred の場合の - ps | 0 | 1 | 0 | 0 |
それ以外の - ps | 0 | 0 | 0 | 0 |
endif の - ps | -1(if bool - ps) | -1( pred - psまたは if_comp - ps) の場合) | 0 | 0 |
rep - ps | 0 | 0 | 1 | 0 |
endrep - ps | 0 | 0 | -1 | 0 |
中断 - ps | 0 | 0 | 0 | 0 |
break_comp - ps | 0 | 1、-1 | 0 | 0 |
breakp - ps | 0 | 0 | 0 | 0 |
呼び出し - ps | 0 | 0 | 0 | 1 |
callnz bool - ps | 0 | 0 | 0 | 1 |
callnz pred - ps | 0 | 1 | 0 | 1 |
ret - ps | 0 | -1(callnz pred - ps) | 0 | -1 |
setp_comp - ps | 0 | 0 | 0 | 0 |
入れ子の深さ
入れ子の深さは、互いの内部から呼び出すことができる命令の数を定義します。 各種類の命令には、次の表に示すように、1 つ以上の入れ子の制限があります。
命令の種類 | 最大 |
---|---|
静的な入れ子 | (D3DCAPS9の場合は 24。D3DPSHADERCAPS2_0.StaticFlowControlDepth > 0);それ以外の場合は 0 |
動的な入れ子 | 0 から 24、D3DCAPS9を参照してください。D3DPSHADERCAPS2_0.DynamicFlowControlDepth |
rep nesting | 0 から 4、D3DCAPS9を参照してください。D3DPSHADERCAPS2_0.StaticFlowControlDepth |
呼び出しの入れ子 | 0 から 4、D3DCAPS9を参照してください。D3DPSHADERCAPS2_0.StaticFlowControlDepth (rep 制限とは無関係) |
ps_2_swの命令深度数
各命令は、1 つ以上の入れ子の深さの制限に対してカウントされます。 次の表は、各命令が既存の深度を加算または減算する深度数を示しています。
命令 | 静的な入れ子 | 動的な入れ子 | loop/rep nesting | 呼び出しの入れ子 |
---|---|---|---|---|
bool - ps の場合の | 1 | 0 | 0 | 0 |
pred の場合の - ps | 0 | 1 | 0 | 0 |
if_comp - ps | 0 | 1 | 0 | 0 |
それ以外の - ps | 0 | 0 | 0 | 0 |
endif の - ps | -1(if bool - ps) | -1( pred - psまたは if_comp - ps) の場合) | 0 | 0 |
rep - ps | 0 | 0 | 1 | 0 |
endrep - ps | 0 | 0 | -1 | 0 |
ループ - ps | n/a | n/a | n/a | n/a |
endloop - ps | n/a | n/a | n/a | n/a |
中断 - ps | 0 | 0 | 0 | 0 |
break_comp - ps | 0 | 1、-1 | 0 | 0 |
breakp - ps | 0 | 0 | 0 | 0 |
呼び出し - ps | 0 | 0 | 0 | 1 |
callnz bool - ps | 0 | 0 | 0 | 1 |
callnz pred - ps | 0 | 1 | 0 | 1 |
ret - ps | 0 | -1(callnz pred - ps) | 0 | -1 |
setp_comp - ps | 0 | 0 | 0 | 0 |
入れ子の深さ
入れ子の深さは、互いの内部から呼び出すことができる命令の数を定義します。 各種類の命令には、次の表に示すように、1 つ以上の入れ子の制限があります。
命令の種類 | 最大 |
---|---|
静的な入れ子 | 24 |
動的な入れ子 | 24 |
rep nesting | 4 |
呼び出しの入れ子 | 4 |
ps_3_0の命令深度数
各命令は、1 つ以上の入れ子の深さの制限に対してカウントされます。 次の表は、各命令が既存の深度を加算または減算する深度数を示しています。
命令 | 静的な入れ子 | 動的な入れ子 | loop/rep nesting | 呼び出しの入れ子 |
---|---|---|---|---|
bool - ps の場合の | 1 | 0 | 0 | 0 |
pred の場合の - ps | 0 | 1 | 0 | 0 |
if_comp - ps | 0 | 1 | 0 | 0 |
それ以外の - ps | 0 | 0 | 0 | 0 |
endif の - ps | -1(if bool - ps) | -1( pred - psまたは if_comp - ps) の場合) | 0 | 0 |
rep - ps | 0 | 0 | 1 | 0 |
endrep - ps | 0 | 0 | -1 | 0 |
ループ - ps | 0 | 0 | 1 | 0 |
endloop - ps | 0 | 0 | -1 | 0 |
中断 - ps | 0 | 0 | 0 | 0 |
break_comp - ps | 0 | 1、-1 | 0 | 0 |
breakp - ps | 0 | 0 | 0 | 0 |
呼び出し - ps | 0 | 0 | 0 | 1 |
callnz bool - ps | 0 | 0 | 0 | 1 |
callnz pred - ps | 0 | 1 | 0 | 1 |
ret - ps | 0 | -1(callnz pred - ps) | 0 | -1 |
setp_comp - ps | 0 | 0 | 0 | 0 |
入れ子の深さ
入れ子の深さは、互いの内部から呼び出すことができる命令の数を定義します。 各種類の命令には、次の表に示すように、1 つ以上の入れ子の制限があります。
命令の種類 | 最大 |
---|---|
静的な入れ子 | 24 |
動的な入れ子 | 24 |
loop/rep nesting | 4 |
呼び出しの入れ子 | 4 |
ps_3_swの命令深度数
各命令は、1 つ以上の入れ子の深さの制限に対してカウントされます。 次の表は、各命令が既存の深度を加算または減算する深度数を示しています。
命令 | 静的な入れ子 | 動的な入れ子 | loop/rep nesting | 呼び出しの入れ子 |
---|---|---|---|---|
bool - ps の場合の | 1 | 0 | 0 | 0 |
pred の場合の - ps | 0 | 1 | 0 | 0 |
if_comp - ps | 0 | 1 | 0 | 0 |
それ以外の - ps | 0 | 0 | 0 | 0 |
endif の - ps | -1(if bool - ps) | -1( pred - psまたは if_comp - ps) の場合) | 0 | 0 |
rep - ps | 0 | 0 | 1 | 0 |
endrep - ps | 0 | 0 | -1 | 0 |
ループ - ps | 0 | 0 | 1 | 0 |
endloop - ps | 0 | 0 | -1 | 0 |
中断 - ps | 0 | 0 | 0 | 0 |
break_comp - ps | 0 | 1、-1 | 0 | 0 |
breakp - ps | 0 | 0 | 0 | 0 |
呼び出し - ps | 0 | 0 | 0 | 1 |
callnz bool - ps | 0 | 0 | 0 | 1 |
callnz pred - ps | 0 | 1 | 0 | 1 |
ret - ps | 0 | -1(callnz pred - ps) | 0 | -1 |
setp_comp - ps | 0 | 0 | 0 | 0 |
入れ子の深さ
入れ子の深さは、互いの内部から呼び出すことができる命令の数を定義します。 各種類の命令には、次の表に示すように、1 つ以上の入れ子の制限があります。
命令の種類 | 最大 |
---|---|
静的な入れ子 | 24 |
動的な入れ子 | 24 |
loop/rep nesting | 4 |
呼び出しの入れ子 | 4 |
Per-Pixel フロー制御と画面グラデーションの相互作用
ピクセル シェーダー命令セットには、画面空間 x と y に関して数量のグラデーションを生成または使用するいくつかの命令が含まれています。 グラデーションの最も一般的な用途は、テクスチャ サンプリングの詳細レベル計算を計算し、異方性フィルタリングの場合は、異方性の軸に沿ってサンプルを選択する方法です。 通常、ハードウェア実装では複数のピクセル (2x2 グリッドなど) でピクセル シェーダーが同時に実行されるため、シェーダーで計算される数量のグラデーションは、隣接するピクセルの同じ実行ポイントでの値の差分として合理的に近似できます。
フロー制御がシェーダーに存在する場合、隣接するピクセルが個別のフロー制御パスを実行する可能性がある場合、特定の分岐パス内で要求されたグラデーション計算の結果はあいまいになります。 したがって、ラスター化される特定のプリミティブのピクセル間で変化する可能性があるフロー制御コンストラクト内の場所でグラデーション計算を要求するピクセル シェーダー操作を使用することは無効と見なされます。
すべてのピクセル シェーダー命令は、許可されている操作とフロー制御の内部で許可されていない操作にパーティション分割されます。
シナリオ A: プリミティブ内のピクセル間で変化する可能性があるフロー制御内で許可されていない操作。 これには、次の表に示す操作が含まれます。
命令 フロー制御では、次の場合に許可されます。 texld - ps_2_0およびアップ、 texldb - ps および texldp - ps テクスチャ座標には一時レジスタが使用されます。 dsx - ps と dsy - ps オペランドには一時レジスタが使用されます。 シナリオ B: どこでも許可される操作。 これには、次の表に示す操作が含まれます。
命令 次の場合はどこでも許可されます。 texld - ps_2_0およびアップ、 texldb - ps および texldp - ps テクスチャ座標には読み取り専用の数量が使用されます (補間テクスチャ座標など、ピクセルごとに異なる場合があります)。 dsx - ps と dsy - ps 入力オペランドには読み取り専用の数量が使用されます (補間テクスチャ座標など、ピクセルごとに異なる場合があります)。 texldl - ps ユーザーは詳細レベルを引数として提供するため、グラデーションがないため、フロー制御に問題はありません。 texldd - ps ユーザーは入力引数としてグラデーションを提供するため、フロー制御に問題はありません。
これらの制限は、シェーダー検証で厳密に適用されます。 条件式のオペランドがピクセル シェーダーによって計算された量であっても、プリミティブ全体で分岐するかのように見える分岐条件を持つシナリオでは、それでもシナリオ A に分類され、許可されません。 同様に、一部のシェーダー計算数量 x に対して動的フロー 制御内からグラデーションが要求されるシナリオでも、x はいずれの分岐でも変更されていないように見えますが、それでもシナリオ A に分類され、許可されません。
これらのフロー制御の制限にはプレディケーションが含まれているため、実装は、分岐命令の実装を述語付き命令と簡単に交換できます。
ユーザーは、シナリオ A と B の指示を一緒に使用できます。 たとえば、シェーダー計算テクスチャ座標を指定した場合、ユーザーが異方性テクスチャ サンプルを必要とするとします。ただし、テクスチャの負荷は、ピクセル単位の条件を満たすピクセルにのみ必要です。 これらの要件を満たすために、ユーザーは、ピクセル単位のさまざまなフロー制御の外部にあるすべてのピクセルのテクスチャ座標を計算し、dsx - ps と dsy - ps 命令を使用してグラデーションをすぐに計算できます。 次に、bool - ps /endif - ps ブロックの場合、ピクセル単位の内で、ユーザーは texldd - ps (ユーザーが指定したグラデーションでのテクスチャ負荷) を使用して、事前計算されたグラデーションを渡すことができます。 この使用パターンを記述するもう 1 つの方法は、プリミティブ内のすべてのピクセルがテクスチャ座標を計算し、グラデーション計算に関係する必要があったが、テクスチャをサンプリングするために必要なピクセルだけが実際にそうしたことです。
これらのルールに関係なく、グラデーションを計算する (またはグラデーションを暗黙的に計算するテクスチャ サンプルを実行する) 前に、ソース データを含むレジスタがすべての実行パスに対して事前に初期化されている必要があることを確認する必要があります。 一時レジスタの初期化は、一般的に検証または適用されません。
関連トピック
-
ピクセル シェーダー命令 を する