Ios 为什么GLSL';s的算术函数在iPad上产生的结果与在模拟器上产生的结果如此不同?
我目前正在追踪在iOS设备上运行的OpenGL ES 2.0片段着色器代码中的一些bug。代码在模拟器中运行良好,但在iPad上它有巨大的问题,并且一些计算产生了截然不同的结果,例如,我在iPad上使用了Ios 为什么GLSL';s的算术函数在iPad上产生的结果与在模拟器上产生的结果如此不同?,ios,opengl-es,floating-point,opengl-es-2.0,glsl,Ios,Opengl Es,Floating Point,Opengl Es 2.0,Glsl,我目前正在追踪在iOS设备上运行的OpenGL ES 2.0片段着色器代码中的一些bug。代码在模拟器中运行良好,但在iPad上它有巨大的问题,并且一些计算产生了截然不同的结果,例如,我在iPad上使用了0.0,在模拟器上使用了4013.17,所以我不是说可能是一些舍入错误导致的微小差异 我注意到的一件事是,在iPad上 float1 = pow(float2, 2.0); 可以产生与测试结果非常不同的结果 float1 = float2 * float2; 具体地说,当对包含较大负数的变量
0.0
,在模拟器上使用了4013.17
,所以我不是说可能是一些舍入错误导致的微小差异
我注意到的一件事是,在iPad上
float1 = pow(float2, 2.0);
可以产生与测试结果非常不同的结果
float1 = float2 * float2;
具体地说,当对包含较大负数的变量(如
-8
)使用pow(x,2.0)
时,如果模拟器使用x86浮点单元和Mac OS x数字库,它似乎会返回一个满足条件的值
pow()也是一个使用近似算法的库例程。如果x<0或x=0且y,则表示pow未定义≤ 0.在GLSL
pow
中作为exp2
和log2
的函数实现。由于未为负实数定义,因此pow()
也不是
参见第47页或第88页
pow(x,y)继承自exp2(x*log2(y))
本规范还包括:
genTypepow(genType x,genType y)
- 返回提升到y次方的x,即x^y
- 如果x<0,则结果未定义
- 如果x=0和y,结果是未定义的,所以你是说iPad和模拟器可以产生如此不同的数字,即使两者都符合OpenGL ES 2.0“标准”,因此(IIRC)符合IEEE浮点运算标准(IEEE 754)?我认为制定这些标准是为了防止类似的情况发生。请注意,他们询问的是GLSL着色器,因此这实际上是在GPU上执行的计算,而不是在CPU绑定的标准库上执行的计算。这里我们不是指ARM与x86,而是PowerVR与(主要是软件)的比较iOS模拟器中使用的仿真。@cheeesus OpenGL ES 2标准并不要求严格遵守IEEE 754标准,请参阅“精度和精度限定符”一章中的GLSL ES规范,这些要求是关于最小精度范围的。谢谢大家。
函数是造成这些巨大差异的原因,在iPad的GPU上实现pow()
确实存在一些问题,特别是负数。@JamesThiele,也许你可以编辑你的帖子来反映BradLarson的评论。在OpenGL中,pow的实现不完全;规范没有为x<0定义它。(见我的答案。)在主CPU上,pow应该很好,编译器可能会将pow(x,2)优化为x*x。我想你会发现,在不同的iOS设备GPU上,你甚至会得到略有不同的结果(iPad与iPad 2、iPhone 4等)。这是您几乎需要在所有希望支持的设备上进行测试的领域之一。谢谢!这将结束长时间的调试会话。但说真的:wtf?更具体地说:。pow()