http://bugs.winehq.org/show_bug.cgi?id=34266
--- Comment #3 from Henri Verbeet hverbeet@gmail.com 2013-08-15 08:28:58 CDT --- (In reply to comment #0)
I do note that HLSL defines the rcp instruction to return infinity for a zero operand (*1), while the GLSL spec says that division by zero "result[s] in an unspecified value" (*2).
...
(*2) http://www.opengl.org/registry/doc/GLSLangSpec.Full.1.20.8.pdf (section 5.9 "Expressions") -- bizarrely, the GLSL 4.4 spec keeps that language but adds section 4.7.1 "Range and Precision" which says that "dividing a non-zero by 0 results in the appropriately signed IEEE Inf", so the spec is internally inconsistent and who knows what you'll get.
Sort of. It's undefined in GLSL 1.20, but later versions are supposed to follow IEEE floating point rules.
(In reply to comment #1)
visible in the current FFXIV:ARR benchmark. The problematic instruction is line 66: R0.z = (1.0 / R2.w) where R2 is an RGBA value read from a texture.
The issue is actually likely to be in line 68. The problem isn't that division by 0 generates NaNs, it doesn't. Instead, division by zero generates infinities as expected, and when such an infinity is then multiplied by 0 you'll get a NaN. That's what's supposed to happen according to IEEE floating point rules, but d3d9 has a rule that 0 * anything == 0.
You don't mention what GPU you're using, but if you look at the AMD R600 ISA docs for example you'll notice the GPU has e.g. both "MUL" and "MUL_IEEE" instructions for this reason. I think the right way to fix this issue is to create a GL extension that allows us to specify D3D or IEEE rules.