WIP: nir: Add a new fmulz opcode
OpenGL ARB programs have different floating-point rules than GLSL.
While GLSL aims to be mostly compliant with IEEE-754 (up to a rough
equivalent of -ffast-math), ARB programs do not. They require that NaN
is never generated. While not generating NaN isn't too hard most of the
time, there is one particular place it's tricky:
0*inf. According to
the IEEE-754 rules (and most hardware),
0*inf = NaN but ARB programs
explicitly specify that
0*x=0 for any value of x, including NaN.
Currently, in Mesa, this is handled by each driver itself. On Intel, we handle it by enabling the ALT floating-point mode. On AMD, they have different multiply instructions. For most of the GLES-focused drivers, it's ignored even if they claim desktop GL because no one has bothered to care. For drivers like Zink and the d3d12 gallium driver, they need to handle it with shader code-gen if they want to be correct. (Neither layered implementation is correct today.)
The best way to do this (and this is good for AMD as well), is likely to have an opcode in NIR which has old alternative behavior. Then we make the ARB -> NIR pass generate that opcode along with whatever other fix-ups we need for things like flog to ensure we never get NaN. Alternatively, we could add an "old school float" lowering pass. Back-ends will then have to handle the new fmulz instruction by either emitting special instructions (if they have them), emitting extra code to fix up a regular MUL, or ignoring it if you're a GLES driver and just don't care.