summaryrefslogtreecommitdiff
path: root/tests/shaders/glsl-vs-continue-in-switch-in-do-while.shader_test
blob: 88fcfb9b397812f13b4b5d8aaefc6ee8c027d1b8 (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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# From the GLSL 4.40 spec, section 6.4 (Jumps):
#
#     The continue jump is used only in loops. It skips the remainder
#     of the body of the inner most loop of which it is inside. For
#     while and do-while loops, this jump is to the next evaluation of
#     the loop condition-expression from which the loop continues as
#     previously defined.
#
# One way that do-while loops might be implemented is to convert them
# to infinite loops that terminate in a conditional break (this is
# what Mesa does).  In such an implementation, an easy way to
# implement the proper behaviour of "continue" in a do-while loop is
# to replicate the conditional break at the site of the "continue".
# For example, this code:
#
#     do {
#       ...
#       if (...) {
#         ...
#         continue;
#       }
#       ...
#     } while (condition);
#
# would get translated to:
#
#     loop {
#       ...
#       if (...) {
#         ...
#         if (!condition)
#           break;
#         continue;
#       }
#       ...
#       if (!condition)
#         break;
#     }
#
# However, we must be careful in making this transformation if the
# "continue" occurs inside a switch statement, since "break" inside a
# switch statement normally exits the switch statement, not the
# surrounding loop.
#
# This test verifies that "continue" behaves properly when invoked
# inside a switch statement which is itself inside a do-while loop.

[require]
GLSL >= 1.30

[vertex shader]
#version 130
void main()
{
  gl_Position = gl_Vertex;
  int w = 0;
  int x = 0;
  int y = 0;
  int z = 0;
  do {             // 1st iteration   2nd iteration
    ++w;           // w <- 1          w <- 2
    switch (w) {   // Jump to case 1  Jump to case 2
      case 1:
        ++x;       // x <- 1
        break;     // Jump to ++z
      case 2:
        continue;  //                 Jump to (w < 2)
      case 3:
        ++y;       // (this case is never executed)
        break;
    }
    ++z;           // z <- 1          skipped
  } while (w < 2); // true            false

  // The loop should execute for two iterations, so w should be 2.  X
  // should be incremented on the first iteration only, so it should
  // be 1.  Y should never be incremented (since w never reaches 3),
  // so it should be 0.  The "continue" should skip ++z on the second
  // iteration, so z should be 1.
  if (w == 2 && x == 1 && y == 0 && z == 1)
    gl_FrontColor = vec4(0.0, 1.0, 0.0, 1.0);
  else
    gl_FrontColor = vec4(1.0, 0.0, 0.0, 1.0);
}

[fragment shader]
#version 130
void main()
{
  gl_FragColor = gl_Color;
}

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