Skip to content

spirv-opt moves RelaxedPrecision decoration from OpIAdd to FindSMsb #2764

@afd

Description

@afd

spirvoptissue.zip

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions