フロー制御の制限事項
ピクセル シェーダー フロー制御命令には、命令に含めることができる入れ子のレベルの数に影響する制限があります。 さらに、グラデーション命令を使用してピクセル単位のフロー制御を実装する場合は、いくつかの制限があります。
Note
*_4_0_level_9_x HLSL シェーダー プロファイルを使用する場合は、 シェーダー モデル 2.x プロファイルを暗黙的に使用して Direct3D 9 対応ハードウェアをサポートします。 シェーダー モデル 2.x プロファイルでは、 シェーダー モデル 4.x 以降のプロファイルよりも制限されたフロー制御動作がサポートされています。
ピクセル シェーダー命令の深度数
ps_2_0はフロー制御をサポートしていません。 他のピクセル シェーダー バージョンの制限事項を次に示します。
ps_2_xの命令深度数
各命令は、1 つ以上の入れ子の深さの制限に対してカウントされます。 次の表に、各命令が既存の深さを加算または減算する深度数を示します。
命令 | 静的な入れ子 | 動的な入れ子 | loop/rep の入れ子 | 呼び出しの入れ子 |
---|---|---|---|---|
if bool - ps | 1 | 0 | 0 | 0 |
if_comp - ps | 0 | 1 | 0 | 0 |
pred の場合 - ps | 0 | 1 | 0 | 0 |
else - 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 |
break - ps | 0 | 0 | 0 | 0 |
break_comp - ps | 0 | 1, -1 | 0 | 0 |
breakp - ps | 0 | 0 | 0 | 0 |
call - 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 if (D3DCAPS9.D3DPSHADERCAPS2_0.StaticFlowControlDepth > 0);それ以外の場合は 0 |
動的な入れ子 | 0 ~ 24 については、「D3DCAPS9」を参照してください。D3DPSHADERCAPS2_0.DynamicFlowControlDepth |
rep の入れ子 | 0 ~ 4 については、「D3DCAPS9」を参照してください。D3DPSHADERCAPS2_0.StaticFlowControlDepth |
呼び出しの入れ子 | 0 ~ 4 については、「D3DCAPS9」を参照してください。D3DPSHADERCAPS2_0.StaticFlowControlDepth (担当者の制限に関係なく) |
ps_2_swの命令深度数
各命令は、1 つ以上の入れ子の深さの制限に対してカウントされます。 次の表は、各命令が既存の深さから加算または減算する深度数を示しています。
命令 | 静的な入れ子 | 動的な入れ子 | loop/rep の入れ子 | 呼び出しの入れ子 |
---|---|---|---|---|
if bool - ps | 1 | 0 | 0 | 0 |
pred の場合 - ps | 0 | 1 | 0 | 0 |
if_comp - ps | 0 | 1 | 0 | 0 |
else - 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 |
loop - ps | 該当なし | 該当なし | 該当なし | 該当なし |
endloop - ps | 該当なし | 該当なし | 該当なし | 該当なし |
break - ps | 0 | 0 | 0 | 0 |
break_comp - ps | 0 | 1, -1 | 0 | 0 |
breakp - ps | 0 | 0 | 0 | 0 |
call - 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 の入れ子 | 4 |
呼び出しの入れ子 | 4 |
ps_3_0の命令深度数
各命令は、1 つ以上の入れ子の深さの制限に対してカウントされます。 次の表は、各命令が既存の深さから加算または減算する深度数を示しています。
命令 | 静的な入れ子 | 動的な入れ子 | loop/rep の入れ子 | 呼び出しの入れ子 |
---|---|---|---|---|
if bool - ps | 1 | 0 | 0 | 0 |
pred の場合 - ps | 0 | 1 | 0 | 0 |
if_comp - ps | 0 | 1 | 0 | 0 |
else - 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 |
loop - ps | 0 | 0 | 1 | 0 |
endloop - ps | 0 | 0 | -1 | 0 |
break - ps | 0 | 0 | 0 | 0 |
break_comp - ps | 0 | 1, -1 | 0 | 0 |
breakp - ps | 0 | 0 | 0 | 0 |
call - 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 | 呼び出しの入れ子 |
---|---|---|---|---|
if bool - ps | 1 | 0 | 0 | 0 |
pred の場合 - ps | 0 | 1 | 0 | 0 |
if_comp - ps | 0 | 1 | 0 | 0 |
else - ps | 0 | 0 | 0 | 0 |
endif - ps | -1(bool - ps の場合) | -1(pred - ps または if_comp - ps) | 0 | 0 |
rep - ps | 0 | 0 | 1 | 0 |
endrep - ps | 0 | 0 | -1 | 0 |
loop - ps | 0 | 0 | 1 | 0 |
endloop - ps | 0 | 0 | -1 | 0 |
break - ps | 0 | 0 | 0 | 0 |
break_comp - ps | 0 | 1, -1 | 0 | 0 |
breakp - ps | 0 | 0 | 0 | 0 |
call - 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 の入れ子 | 4 |
呼び出しの入れ子 | 4 |
Per-Pixelフロー制御と画面勾配の相互作用
ピクセル シェーダー命令セットには、画面空間 x と y に関して数量のグラデーションを生成または使用するいくつかの命令が含まれています。 グラデーションの最も一般的な用途は、テクスチャ サンプリングの詳細レベル計算を計算し、異方性フィルタリングの場合は、異方性の軸に沿ってサンプルを選択することです。 通常、ハードウェア実装では、複数のピクセル (2 x 2 グリッドなど) でピクセル シェーダーが同時に実行されるため、シェーダーで計算される数量のグラデーションは、隣接するピクセルの同じ実行ポイントでの値の差分として合理的に近似できます。
シェーダーにフロー制御が存在する場合、隣接するピクセルが個別のフロー 制御パスを実行する場合に、特定の分岐パス内で要求されたグラデーション計算の結果があいまいになります。 したがって、ラスター化される特定のプリミティブのピクセル間で変化する可能性があるフロー制御コンストラクト内の場所でグラデーション計算の実行を要求するピクセル シェーダー操作を使用することは無効と見なされます。
すべてのピクセル シェーダー命令は、許可されている操作と、フロー制御の内部で許可されていない操作にパーティション分割されます。
シナリオ 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 つの方法は、プリミティブ内のすべてのピクセルがテクスチャ座標を計算し、グラデーションの計算に関与する必要がありましたが、テクスチャをサンプリングするために必要なピクセルのみが実際に行ったことです。
これらのルールに関係なく、グラデーションを計算する前 (またはグラデーションを暗黙的に計算するテクスチャ サンプルを実行する) 前に、ソース データを含むレジスタがすべての実行パスに対して事前に初期化されている必要があることを確認する負担はユーザーにあります。 一時レジスタの初期化は、一般に検証または適用されません。
関連トピック