-
Notifications
You must be signed in to change notification settings - Fork 664
spirv-opt moves RelaxedPrecision decoration from OpIAdd to FindSMsb #2764
Description
The attached zip contains this little fragment shader:
#version 310 es
precision highp float;
layout(location = 0) out vec4 _GLF_color;
void main() {
highp int a = 16777216;
_GLF_color = vec4(24 == (0 + findMSB(a)) ? 1.0 : 0.0, 0.0, 0.0, 1.0);
}
glslang treats the result of "0 + findMSB(a)" as having relaxed precision, decorating %18 in example.asm with RelaxedPrecision.
OpDecorate %18 RelaxedPrecision
...
%18 = OpIAdd %6 %15 %17
This is OK, because findMSB has lowp on its return type (which makes sense because the most significant bit of an integer cannot be a large number), and 0 does not have a precision, so lowp is the lowest common denominator.
Running spirv-opt -O on the generated SPIR-V gives example.opt.asm, in which the "0 +" has been removed.
The problem is that the RelaxedPrecision decoration has now been changed to refer to %17, which is the call to findMSB:
OpDecorate %17 RelaxedPrecision
...
%17 = OpExtInst %6 %1 FindSMsb %9
According to the SPIR-V specification, this leads not just to the result of FindSMsb, but also its argument, %9, being treated as having relaxed precision.
On some implementations this leads to %9 being truncated to a smaller number of bits, changing what is rendered. (In this test, %9 contains 16777216, which has 24 as its MSB, but if it is truncated to e.g. 16 bits it has 0 as its MSB.)
Issue found using GraphicsFuzz