歴史的に言えば、GPUは、任意の条件分岐をサポートしていたよりもはるかに長い間、MIN
やMAX
などのフラグメント単位の命令をサポートしています。デスクトップOpenGLにおけるこの例の1つは、GL_ARB_fragment_program
拡張(現在はGLSLに置き換えられている)です。これは、分岐をサポートしないことを明示していますが、MIN
およびMAX
の命令とその他の条件付き命令を提供します。
min()
、max()
、clamp()
がどのようにシェーダに含まれているかを考えれば、すべてのGPUにこれらの操作用の専用ハードウェアがまだあると確信しています。実装はコードを最適化することができますが、現実世界では独自のものを使うのではなく、GLSLの組み込み関数を使用する必要があるため、この仕様では保証されていません。
唯一の例外は、大量の追加フラグメント処理を避けるために条件を使用していた場合です。ある時点では、ブランチのコストはブランチ内のすべてのコードを実行するコストよりも低くなりますが、ここでのバランスはハードウェアに非常に依存するため、実際にアプリケーションで役立つかどうかをベンチマークする必要がありますターゲットハードウェアここで私が意味するもののようなものだ:
だけで0-1に
NDotL
をクランプ
void main() {
vec3 N = ...;
vec3 L = ...;
float NDotL = dot(N, L);
if (NDotL > 0.0)
{
// Lots of very intensive code for an awesome shadowing algorithm that we
// want to avoid wasting time on if the fragment is facing away from the light
}
}
とNDotL
ならば、常にのみNDotL
して、最終的な影の用語によって乗算するすべてのフラグメントに影コードを処理することは無駄な努力がたくさんありますもともとは< = 0でした。理論的には、このオーバーヘッドをブランチで回避できます。このようなことが常にパフォーマンス上の勝利をもたらすわけではない理由は、ハードウェアがどのようにシェーダの分岐を実装するかに大きく依存しているからです。
私はあなたの最後の文章はすでにそれに非常によく答えると思います。より合理化された見解とは別に、高速のハードウェア命令によって実装される可能性は、少なくとも「普通」よりも高くなります。しかし、この一般的な提案(これでも十分であるはずです)とは別に、実際には特殊なハードウェア命令や条件付き代入を使用し、 'if'をラップする関数ではありません。 –