2016-01-27 33 views
2

我已經看到了很多的GLSL代碼如下所示:爲什麼人們在GLSL中寫入0.00390625而不是1.0/256.0?

vec2 x = y * 0.00390625; 

通常情況下,爲了清楚起見,我會寫爲:

vec2 x = y * (1.0/256.0); 

或者爲:

vec2 x = y/256.0; 

是否有理由使用頂級版本?在我看來,如果編譯器不支持數字文字的常量摺疊或簡單的強度降低,那麼編譯器肯定會非常可悲。

所以我的問題可以改寫:您是否可能遇到GLSL編譯器而不支持常量摺疊或強度降低?我只想着OpenGL實現中的GLSL編譯器,而不是GLSL優化器。

回答

4

我不是編譯器專家,但如果GLSL編譯器不做簡單的常量摺疊,我會感到非常驚訝。因此,我認爲它應該是安全的假設,在下列情況下,不斷的劃分得到在編譯時評價:

vec2 x = y * (1.0/256.0); 

第二種情況實際上是更有趣:

vec2 x = y/256.0; 

如果這是C或C++代碼,我的理解是,一個編譯器將而不是默認情況下乘以一個乘法。原因是由於舍入不同,無法保證結果與最後一位相同。作爲參考,請參閱Optimizing a floating point division and conversion operation中的答案,其中一個答案確認例如gcc不會執行替換,除非使用-freciprocal-math編譯器選項。

但是,GLSL是另一種情況。了OpenGL ES GLSL規範特別允許此類型的轉換:

C++標準要求表達式必須在由操作的優先級指定的順序進行評估,並可以僅重新分組如果結果是相同的或結果未定義。沒有其他變換可能會影響操作的結果。 GLSL ES在以下方面放寬了這些要求:

...

浮點除法可以通過互惠和乘法來代替。

有趣的是,這是在充滿不部分(即非ES)GLSL規格。它確實有精確度要求,即分部的誤差最多可以是2.5 ULP(最後的單位)。我解釋這一點的方式是,如果用乘法替代一個分割符合精度要求,則替換將是合法的。但要確保您的代碼儘可能高效,在可能的情況下使用乘法而不是分割似乎更安全。

+0

我特別選擇256,因爲在任何一種情況下舍入都是相同的。 –

+0

這個答案寫得很好,但不幸的是,它並沒有真正回答這個問題,即是否有理由相信你的GLSL編譯器可能不支持強度降低或不斷摺疊。 –

+0

@DietrichEpp依賴於驅動程序,並且大多數開發者無論如何都會在謹慎的方面犯錯。 –

相關問題