diff options
author | Paul Berry <[email protected]> | 2014-01-31 09:55:35 -0800 |
---|---|---|
committer | Paul Berry <[email protected]> | 2014-02-04 09:06:09 -0800 |
commit | 7f5740899fe8ee2d7fecebf1b9622e06dbc78f43 (patch) | |
tree | fd75c45ca7298fe65db4c5da35d98ee29dd264b8 | |
parent | 56790856b303ad5ba86d7eb261ade91edaa3ee0b (diff) |
glsl: Fix continue statements in do-while loops.
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.
Previously, we incorrectly treated a "continue" statement as jumping
to the top of a do-while loop.
This patch fixes the problem by replicating the loop condition when
converting the "continue" statement to IR. (We already do a similar
thing in "for" loops, to ensure that "continue" causes the loop
expression to be executed).
Fixes piglit tests:
- glsl-fs-continue-inside-do-while.shader_test
- glsl-vs-continue-inside-do-while.shader_test
- glsl-fs-continue-in-switch-in-do-while.shader_test
- glsl-vs-continue-in-switch-in-do-while.shader_test
Cc: [email protected]
Acked-by: Carl Worth <[email protected]>
Reviewed-by: Kenneth Graunke <[email protected]>
Reviewed-by: Matt Turner <[email protected]>
-rw-r--r-- | src/glsl/ast_to_hir.cpp | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index 950f513c01b..8d096ad0428 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -4029,17 +4029,22 @@ ast_jump_statement::hir(exec_list *instructions, _mesa_glsl_error(& loc, state, "break may only appear in a loop or a switch"); } else { - /* For a loop, inline the for loop expression again, - * since we don't know where near the end of - * the loop body the normal copy of it - * is going to be placed. + /* For a loop, inline the for loop expression again, since we don't + * know where near the end of the loop body the normal copy of it is + * going to be placed. Same goes for the condition for a do-while + * loop. */ if (state->loop_nesting_ast != NULL && - mode == ast_continue && - state->loop_nesting_ast->rest_expression) { - state->loop_nesting_ast->rest_expression->hir(instructions, - state); - } + mode == ast_continue) { + if (state->loop_nesting_ast->rest_expression) { + state->loop_nesting_ast->rest_expression->hir(instructions, + state); + } + if (state->loop_nesting_ast->mode == + ast_iteration_statement::ast_do_while) { + state->loop_nesting_ast->condition_to_hir(instructions, state); + } + } if (state->switch_state.is_switch_innermost && mode == ast_break) { |