2016-08-16 18 views
0

iOS向けにもう1つのGPUマンデルブローレンダラーを作成していますが、フラグメントシェーダで予期しない結果が発生しています。OpenGL ES 2.0で最適化されたコードiOSのフラグメントシェーダ

私は独立してその値をテストする場合、私は2つの制服を持っている、と。その後、

if (u_h0 == 0.00130208337) { 
     return 200.; // this line is executed 
    } 

上述のコメント、および:

if (u_h1 == -0.0000000000388051084) { 
     return 100.; // this line is executed 
    } 

を、私はこれらが有効なテストです願っています。今、私は関数を呼び出す:

vec2 e_ty = ds_mul(vec2(1., 0.), vec2(u_h0, u_h1)); 
    if (e_ty.y == -0.0000000000388051084) { 
     return 100.; // this is NOT executed 
    } 

は少しさらに探している相手:

vec2 e_ty = ds_mul(vec2(1., 0.), vec2(u_h0, u_h1)); 
    if (e_ty.y == 0.) {//-0.0000000000388051084) { 
     return 100.; // this IS executed 
    } 

ここに行くことができるか

vec2 e_ty = ds_mul(vec2(1., 0.), vec2(0.00130208337, -0.0000000000388051084)); 
    if (e_ty.y == -0.0000000000388051084) { 
     return 100.; // this line is executed (correct result) 
    } 

しかし、次は同じ結果が得られていないのですか? (速い数学をオフにするには?)私は、これは、いくつかのコンパイラの最適化タイプの魔法である疑いがあるが、私は任意のプラグマ型のオプションを見つけることができません(私は、OpenGL ES 3.0に切り替えた場合)を除いて:私が解決しない

#pragma optimize({on, off}) - enable or disable shader optimization (default on) 

問題。私はそこにあると信じて:

#pragma optionNV(fastmath off) 
#pragma optionNV(fastprecision off) 

は、NVIDIAのために、私はiOSデバイスのための同等のものを見つけることができません。

誰にもアイデアはありますか?これは私にナットを駆動します。..

+1

"誰にもアイデアはありますか?*"はい。浮動小数点数を等価比較しようとしないでください。ほとんど常に悪い考えです。 –

答えて

2

申し訳ありませんが私は誰もが任意の有用なアイデア

はい

を持っていない意味しました。浮動小数点数を等価比較しようとしないでください。ほとんど常に悪い考えです。

問題は、浮動小数点比較が正確であると期待しているという直接的な結果です。彼らは正確ではないでしょう。彼らは決して正確ではありません。そして、それらを機能させるために使用できる設定はありません。

特定の問題はこれです:これは、浮動小数点リテラルを有する均一な値の比較である

(u_h1 == -0.0000000000388051084) 

。一様な値はCPUによってユーザから提供されます。このリテラルは、GLSLコンパイラによって解釈されるように、CPU上でユーザからも提供されます。

GLSLコンパイラが均一な浮動小数点アルゴリズムを使用して、均一な値を提供するために使用した値floatを取得した場合、この比較がうまくいきます。これは、提供したデータと提供した他のデータとの浮動小数点比較を行うだけです。

重要な点は、GLSL 計算が使用されないことです。ds_mulpure functionで、これは定数式にダウン沸騰すると仮定すると

vec2 e_ty = ds_mul(vec2(1., 0.), vec2(0.00130208337, -0.0000000000388051084)); 

。使用する価値のあるコンパイラは、この関数呼び出しをCPUので実行し、単に結果を格納します。これを行う際には、CPUのネイティブの浮動小数点精度と表現を使用します。

実際に使用する価値のあるコンパイラは、e_tyが定数式であることを認識し、したがってCPU上で条件付き比較を実行することもあります。

いずれにしても、ポイントは以前と同じです:いいえGLSL 計算が実行されます。

vec2 e_ty = ds_mul(vec2(1., 0.), vec2(u_h0, u_h1)); 

これは2人の制服の値に基づいて表現です。このように、最適化することはできません。 GPUに書いたとして実行する必要があります。つまり、あなたはGPUの浮動小数点精度のmercyです。

この問題では、GPU は慈悲を示さないです。

GPUは32ビット浮動を許可していますか? highpを使用して、最高の状態を期待できます。 GPUが腐らされたIEEE-754 32ビット浮動小数点を適切に処理していますか?オッズはいいえ、あなたにそれを強制する方法はまったくありません。

その式の結果はどうなりますか?これは、GPUの計算精度の許容範囲内で、数学の結果になります。あなたはコントロールできません。 GPUの精度が低いため、0の値が計算されました。これは、指定した小さな浮動小数点の値と等しくありません。

使用しようとしているアルゴリズムは、正確な浮動小数点計算に依存します。そのようなものはGLSLのを制御することはできません。したがって、は、は、浮動小数点の不正確さに対してより耐性のあるアルゴリズムを考案する必要があります。

+0

大丈夫、ありがとう、私は定数式がCPU上で実行されていることを認識していませんでした。 浮動小数点範囲= {127,127、}、精度= 23.精度ビットが23の場合は、32ビット浮動小数点数を扱っていると思いますが、それは正しいですか? 機能ds_mulダブルフロート乗算を実装していますが、リターンのy成分は常に0 である私は、コンパイラは、例えばGPU上で次のコード、離れてコードを最適化だと思う:\t \t \t T1 = C11 + C2 ; \t \t e = t1-c11; は、 \t \tに、t1 = c11 + c2に、 \t \t e = c2; この音はあなたのようですか? 助けてくれてありがとう – jonsl

+0

"これは2ユニフォームの値に基づく式なので、最適化することはできず、GPUで書かれたとおりに実行する必要があります。"私が見たものに基づいて、いくつかのドライバがCPU上でそれを最適化すると確信しています... – solidpixel

+1

また価値があります異なるシェーダで同じ計算を行っている場合、コンパイラは同じ表現を別々に最適化することができます(つまり、演算の順序を入れ替えるなど)。そのため、GPUとGPUの比較でも同じソースコードのビット精度の結果は得られません。レベル表現。あなたはそれを止めるために場所の周りの "不変"指定子を自由に振りかけることができますが、(現在の答えによると)不変式はコンパイラが最適化できるものを制限する傾向があるので、ずっと良い解決策はビット精度に頼らないことですしたがって、パフォーマンスを低下させます... – solidpixel

0

元の質問にわずかに接していますが、一般的にシェーダー内の統一表現に基づいた制御フローを持つことは悪い習慣です。

制服は全体の描画シーケンスでは定数なので、GPUにすべての頂点やフラグメントの式を評価する時間を無駄にするのはなぜですか?幸運なことに、コンパイラはそれを最適化するかもしれませんが、アプリケーションが描画を発行する際に使用する統一されたアプリケーションを知っていることを考えると、フラグメント単位の制御コードは必要ありません。

条件付きのものを削除して、一定のコードパスごとに1つのシェーダを作成し、使用するシェーダの条件チェックをCPUに移動します。シェーダ言語はプリプロセッサをサポートしているので、ソースをアップロードする前に#defineを追加するだけで、同じシェーダの複数のバリエーションを構築できます。

関連する問題