Currently the SPIR-V emitter generates FMin, FMax and FClamp instructions for min, max, clamp and saturate. The specification of the GLSL.std.450 instruction set states that "which operand is the result is undefined if one of the operands is a NaN". This is in contrast with the DXIL, DXBC and HLSL specification of those instructions, which, if one of the operands is NaN, give the other operand as the result (and clamp/saturate gives the lower bound, as if max was performed first).
While HLSL is normally optimized as if there were no special floating-point values at all, with the precise qualifier or the "force IEEE strictness" compiler option, the compiler must honor the defined behavior for specials. Clamping operations may also be used with the implication of sanitizing the input, making sure the resulting value is strictly in the bounds and not NaN.
The correct implementation, which maps 1:1 to the DXIL/DXBC behavior, is NMax/NMin/NClamp from the GLSL.std.450 instruction set. Are those safe to use in DXC (such as, can we assume that NClamp to 0 and 1, on existing drivers or in the near future, will surely map to the hardware saturation modifier in all the same cases as when FClamp to 0 and 1 is used; and whether they're compatible with wave reduction)?
Currently the SPIR-V emitter generates FMin, FMax and FClamp instructions for min, max, clamp and saturate. The specification of the GLSL.std.450 instruction set states that "which operand is the result is undefined if one of the operands is a NaN". This is in contrast with the DXIL, DXBC and HLSL specification of those instructions, which, if one of the operands is NaN, give the other operand as the result (and clamp/saturate gives the lower bound, as if max was performed first).
While HLSL is normally optimized as if there were no special floating-point values at all, with the
precisequalifier or the "force IEEE strictness" compiler option, the compiler must honor the defined behavior for specials. Clamping operations may also be used with the implication of sanitizing the input, making sure the resulting value is strictly in the bounds and not NaN.The correct implementation, which maps 1:1 to the DXIL/DXBC behavior, is NMax/NMin/NClamp from the GLSL.std.450 instruction set. Are those safe to use in DXC (such as, can we assume that NClamp to 0 and 1, on existing drivers or in the near future, will surely map to the hardware saturation modifier in all the same cases as when FClamp to 0 and 1 is used; and whether they're compatible with wave reduction)?