为什么GLSL的算术函数会在iPad上产生与模拟器上不同的结果?
我正在追逐在iOS设备上运行的OpenGL ES 2.0片段着色器代码中的一些错误。 代码在模拟器中运行良好,但在iPad上它有很大的问题,一些计算产生了截然不同的结果,我在iPad上有0.0
和在模拟器上有4013.17
,所以我不是在谈论小差异可能是一些舍入错误的结果。
我注意到的一件事是,在iPad上,
float1 = pow(float2, 2.0);
可以产生与结果非常不同的结果
float1 = float2 * float2;
具体来说,当对包含较大负数的变量(如-8
pow(x, 2.0)
使用pow(x, 2.0)
时,它似乎返回一个满足条件的值if (powResult <= 0.0)
。
此外,两个操作( pow(x, 2.0)
以及x*x
)的结果在模拟器中产生的结果与在iPad上产生的结果不同。
用过的浮子是mediump
,但是我得到了与highp
相同的东西。
对这些差异有一个简单的解释吗?
我正在缩小问题范围,但需要花费很多时间,所以也许有人可以通过一个简单的解释来帮助我。
GLSL ES文档说如果x <0或x = 0且y≤0,则pow未定义。
模拟器使用x86浮点单元和Mac OS X数值库。 iPad使用ARM FPU。
pow()也是一个使用近似算法的库例程。
在GLSL中, pow
作为exp2
和log2
的函数实现。 由于对数函数没有定义为负实数,因此pow()
也不是。
请参阅GLSL ES 3.0规范第47页或GLSL 4.4规范第88页。
pow (x,y)从exp2inheritance(x * log2 (y))
同样来自规范:
genType pow (genType x,genType y)
- 返回x上升到y次幂,即x ^ y
- 如果x <0,则结果未定义。
- 如果x = 0且y <= 0,则结果未定义。