summaryrefslogtreecommitdiff
path: root/tests/spec/glsl-1.30/execution/range_analysis_fsat_of_nan.shader_test
blob: 14de330ffb2ee72e11312b5842f421810f2045ab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
[require]
GLSL >= 1.30

[vertex shader passthrough]

[fragment shader]
#version 130
uniform float zero = 0.0;
uniform float also_zero = 0.0;

out vec4 piglit_fragcolor;

void main()
{
    /* Create a value that, if it were a number, would have to be > 0.  Due to
     * possible flush-to-zero semantics, pretty much anything involving
     * multiplication or division can be zero.  However, gt_zero + ge_zero is
     * gt_zero.
     */
    float not_a_number = 1.0 + abs(zero / also_zero);

    /* Result of the max() should be 0.0, but range analysis might incorrectly
     * think that it's some value > 0.
     *
     * A clever optimizer will convert this to
     *
     *    piglit_fragcolor = vec4(float(saturate(X) > 0),
     *                            float(!(saturate(X) > 0)),
     *                            0, 1);
     *
     * Since saturate(X) must be a number, it may further convert it to
     *
     *    piglit_fragcolor = vec4(float(saturate(X) > 0),
     *                            float(saturate(X) <= 0),
     *                            0, 1);
     *
     * At this point, all conversions are safe and exact.
     *
     * There are two possible incorrect reductions here.  First, range anaysis
     * may detect that X must be greater than zero, so saturate(X) must also
     * be greater than zero.  This first comparison a tautology and the second
     * comparison a contradiction.  If X is NaN (as we have cleverly
     * constructed here), saturate(X) should be zero instead.
     *
     * Second, since the calculations are not marked precise, an overzealous
     * optimizer may reduce this to
     *
     *    piglit_fragcolor = vec4(float(X > 0),
     *                            float(X <= 0),
     *                            0, 1);
     *
     * Dropping saturate() from the greater-than comparison is safe because
     * (0 > 0) is equivalent to (NaN > 0).  If X is NaN, the other condition
     * will also evaluate false.  The GLSL spec gives quite a bit of leeway
     * with respect to NaN, but that seems too far.  The shader author asked
     * for a result of red or green.  A result of black is still "undefined
     * behavior," but it's also a little mean.
     *
     * A result of red likely indicates the first problem, and a result of
     * black likely indicates the second problem.
     */
    if (min(max(not_a_number, 0.0), 1.0) > 0.0) {
        piglit_fragcolor = vec4(1.0, 0.0, 0.0, 1.0);
    } else {
        piglit_fragcolor = vec4(0.0, 1.0, 0.0, 1.0);
    }
}

[test]
draw rect -1 -1 2 2
probe all rgba 0.0 1.0 0.0 1.0