[Piglit] [PATCH 2/2] Test that "continue" works in a switch statement within a do-while loop.

Matt Turner mattst88 at gmail.com
Fri Jan 31 15:28:13 PST 2014


On Fri, Jan 31, 2014 at 1:12 PM, Paul Berry <stereotype441 at gmail.com> wrote:
> ---
>  ...l-fs-continue-in-switch-in-do-while.shader_test | 94 +++++++++++++++++++++
>  ...l-vs-continue-in-switch-in-do-while.shader_test | 95 ++++++++++++++++++++++
>  2 files changed, 189 insertions(+)
>  create mode 100644 tests/shaders/glsl-fs-continue-in-switch-in-do-while.shader_test
>  create mode 100644 tests/shaders/glsl-vs-continue-in-switch-in-do-while.shader_test
>
> diff --git a/tests/shaders/glsl-fs-continue-in-switch-in-do-while.shader_test b/tests/shaders/glsl-fs-continue-in-switch-in-do-while.shader_test
> new file mode 100644
> index 0000000..58dc50d
> --- /dev/null
> +++ b/tests/shaders/glsl-fs-continue-in-switch-in-do-while.shader_test
> @@ -0,0 +1,94 @@
> +# 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;
> +}
> +
> +[fragment shader]
> +#version 130
> +void main()
> +{
> +  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_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
> +  else
> +    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
> +}
> +
> +[test]
> +draw rect -1 -1 2 2
> +probe all rgba 0.0 1.0 0.0 1.0
> diff --git a/tests/shaders/glsl-vs-continue-in-switch-in-do-while.shader_test b/tests/shaders/glsl-vs-continue-in-switch-in-do-while.shader_test
> new file mode 100644
> index 0000000..88fcfb9
> --- /dev/null
> +++ b/tests/shaders/glsl-vs-continue-in-switch-in-do-while.shader_test
> @@ -0,0 +1,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
> --
> 1.8.5.3
>

Nice tests. I'm really happy to see that they fail without causing GPU
hangs on unpatched Mesa.

Both are

Reviewed-by: Matt Turner <mattst88 at gmail.com>


More information about the Piglit mailing list