2012-02-25 19 views
13

今朝の不思議なバグのように見えて、私は非常に素早く解決策を見つけるのは大変ラッキーだと感じました。OpenGLシェーダでNaNを検出する最善の方法

私は、フラグメントシェーダの平均内部を生成するためにカウンタで割っていましたが、もちろんカウンタがゼロのとき、結果のカラー値はNaNになりました。

ブレンド中、NVidiaはNaNを正常に0値として扱いますが、IntelはNaNをカスケードしないように見せかけ、黒い破片を生成します。

Intelのマシンでコードをテストするまで、このバグは残っていました。

無効な値を「トラップ」するためにできることがあるのだろうかと思います。通常のプログラミングと同じように、唯一の確実な(そしてそれでも防弾ではない)方法は、数値を分割するときに考えられるすべてのケースを注意深く検討することです。

NaNを検出する標準的な方法は、数値がそれ自身と等しくないかどうかを確認することです。おそらく、それ自身と等しくないかどうかを確認するために各フラグメントをチェックするデバッグシェーダを構築し、その条件が満たされていれば、目立った色が点滅するように設定できますか? GLSLはこのようにNaNを検出できますか、値が無効なときはいつも未定義の動作に固執していますか?

+0

なぜ0で割りますか?カウンターを0にしたり、アルゴリズムを変更したりすることはできませんか? – djmj

+2

潜在的な分母がゼロかもしれないが、チェックによって性能コストが発生する可能性があるかどうかは、プログラマにとって常に合理的です。私の質問は、事実の後の悪い値の検出に関連しています。 –

答えて

16

私は、フラグメントシェーダの平均内部を生成するためにカウンタで除算していましたが、もちろんカウンタがゼロの場合、結果のカラー値はNaNになりました。

これは、浮動小数点の仕組みではありません。ゼロで割ると、INF、NaNではなくなります。分子がゼロでない場合は、NaNを取得します。

いずれにしても、GLSLは、彼らが言うことを行うisinfisnanの機能を提供しています。

+0

ああ。それは非常に便利です。分子が分母であれば分子は常にゼロになるので、それらはNaNでした。 –

3

WebGLおよびOpenGL ES 2.0ではisnanが不足しています。すべてのGPUで動作するPolyfill私は試してみる機会がありました:

bool isnan(float val) 
{ 
    return (val < 0.0 || 0.0 < val || val == 0.0) ? false : true; 
    // important: some nVidias failed to cope with version below. 
    // Probably wrong optimization. 
    /*return (val <= 0.0 || 0.0 <= val) ? false : true;*/ 
} 
+1

[OpenGL ES GLSL 3+にはisnanがあります。](https://www.khronos.org/opengles/sdk/docs/man31/)。 –

+1

素晴らしい情報、ありがとうございました –

+1

非常に積極的なオプティマイザのため、NVIDIAはこれに対処できません。 – Ruslan

関連する問題