mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-22 11:20:11 +01:00
glsl: Save and restore the whole switch state for nesting.
This stuffs them all in a struct for sanity. Fixes piglit glsl-1.30/execution/switch/fs-uniform-nested. NOTE: This is a candidate for the 8.0 branch. Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
This commit is contained in:
parent
b8c9252570
commit
22d81f154f
3 changed files with 225 additions and 230 deletions
|
|
@ -3405,7 +3405,7 @@ ast_jump_statement::hir(exec_list *instructions,
|
||||||
"continue may only appear in a loop");
|
"continue may only appear in a loop");
|
||||||
} else if (mode == ast_break &&
|
} else if (mode == ast_break &&
|
||||||
state->loop_nesting_ast == NULL &&
|
state->loop_nesting_ast == NULL &&
|
||||||
state->switch_nesting_ast == NULL) {
|
state->switch_state.switch_nesting_ast == NULL) {
|
||||||
YYLTYPE loc = this->get_location();
|
YYLTYPE loc = this->get_location();
|
||||||
|
|
||||||
_mesa_glsl_error(& loc, state,
|
_mesa_glsl_error(& loc, state,
|
||||||
|
|
@ -3423,11 +3423,11 @@ ast_jump_statement::hir(exec_list *instructions,
|
||||||
state);
|
state);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->is_switch_innermost &&
|
if (state->switch_state.is_switch_innermost &&
|
||||||
mode == ast_break) {
|
mode == ast_break) {
|
||||||
/* Force break out of switch by setting is_break switch state.
|
/* Force break out of switch by setting is_break switch state.
|
||||||
*/
|
*/
|
||||||
ir_variable *const is_break_var = state->is_break_var;
|
ir_variable *const is_break_var = state->switch_state.is_break_var;
|
||||||
ir_dereference_variable *const deref_is_break_var =
|
ir_dereference_variable *const deref_is_break_var =
|
||||||
new(ctx) ir_dereference_variable(is_break_var);
|
new(ctx) ir_dereference_variable(is_break_var);
|
||||||
ir_constant *const true_val = new(ctx) ir_constant(true);
|
ir_constant *const true_val = new(ctx) ir_constant(true);
|
||||||
|
|
@ -3530,25 +3530,22 @@ ast_switch_statement::hir(exec_list *instructions,
|
||||||
|
|
||||||
/* Track the switch-statement nesting in a stack-like manner.
|
/* Track the switch-statement nesting in a stack-like manner.
|
||||||
*/
|
*/
|
||||||
ir_variable *saved_test_var = state->test_var;
|
struct glsl_switch_state saved = state->switch_state;
|
||||||
ir_variable *saved_is_fallthru_var = state->is_fallthru_var;
|
|
||||||
|
|
||||||
bool save_is_switch_innermost = state->is_switch_innermost;
|
state->switch_state.is_switch_innermost = true;
|
||||||
ast_switch_statement *saved_nesting_ast = state->switch_nesting_ast;
|
state->switch_state.switch_nesting_ast = this;
|
||||||
|
|
||||||
state->is_switch_innermost = true;
|
|
||||||
state->switch_nesting_ast = this;
|
|
||||||
|
|
||||||
/* Initalize is_fallthru state to false.
|
/* Initalize is_fallthru state to false.
|
||||||
*/
|
*/
|
||||||
ir_rvalue *const is_fallthru_val = new (ctx) ir_constant(false);
|
ir_rvalue *const is_fallthru_val = new (ctx) ir_constant(false);
|
||||||
state->is_fallthru_var = new(ctx) ir_variable(glsl_type::bool_type,
|
state->switch_state.is_fallthru_var =
|
||||||
|
new(ctx) ir_variable(glsl_type::bool_type,
|
||||||
"switch_is_fallthru_tmp",
|
"switch_is_fallthru_tmp",
|
||||||
ir_var_temporary);
|
ir_var_temporary);
|
||||||
instructions->push_tail(state->is_fallthru_var);
|
instructions->push_tail(state->switch_state.is_fallthru_var);
|
||||||
|
|
||||||
ir_dereference_variable *deref_is_fallthru_var =
|
ir_dereference_variable *deref_is_fallthru_var =
|
||||||
new(ctx) ir_dereference_variable(state->is_fallthru_var);
|
new(ctx) ir_dereference_variable(state->switch_state.is_fallthru_var);
|
||||||
instructions->push_tail(new(ctx) ir_assignment(deref_is_fallthru_var,
|
instructions->push_tail(new(ctx) ir_assignment(deref_is_fallthru_var,
|
||||||
is_fallthru_val,
|
is_fallthru_val,
|
||||||
NULL));
|
NULL));
|
||||||
|
|
@ -3556,13 +3553,13 @@ ast_switch_statement::hir(exec_list *instructions,
|
||||||
/* Initalize is_break state to false.
|
/* Initalize is_break state to false.
|
||||||
*/
|
*/
|
||||||
ir_rvalue *const is_break_val = new (ctx) ir_constant(false);
|
ir_rvalue *const is_break_val = new (ctx) ir_constant(false);
|
||||||
state->is_break_var = new(ctx) ir_variable(glsl_type::bool_type,
|
state->switch_state.is_break_var = new(ctx) ir_variable(glsl_type::bool_type,
|
||||||
"switch_is_break_tmp",
|
"switch_is_break_tmp",
|
||||||
ir_var_temporary);
|
ir_var_temporary);
|
||||||
instructions->push_tail(state->is_break_var);
|
instructions->push_tail(state->switch_state.is_break_var);
|
||||||
|
|
||||||
ir_dereference_variable *deref_is_break_var =
|
ir_dereference_variable *deref_is_break_var =
|
||||||
new(ctx) ir_dereference_variable(state->is_break_var);
|
new(ctx) ir_dereference_variable(state->switch_state.is_break_var);
|
||||||
instructions->push_tail(new(ctx) ir_assignment(deref_is_break_var,
|
instructions->push_tail(new(ctx) ir_assignment(deref_is_break_var,
|
||||||
is_break_val,
|
is_break_val,
|
||||||
NULL));
|
NULL));
|
||||||
|
|
@ -3575,13 +3572,7 @@ ast_switch_statement::hir(exec_list *instructions,
|
||||||
*/
|
*/
|
||||||
body->hir(instructions, state);
|
body->hir(instructions, state);
|
||||||
|
|
||||||
/* Restore previous nesting before returning.
|
state->switch_state = saved;
|
||||||
*/
|
|
||||||
state->switch_nesting_ast = saved_nesting_ast;
|
|
||||||
state->is_switch_innermost = save_is_switch_innermost;
|
|
||||||
|
|
||||||
state->test_var = saved_test_var;
|
|
||||||
state->is_fallthru_var = saved_is_fallthru_var;
|
|
||||||
|
|
||||||
/* Switch statements do not have r-values.
|
/* Switch statements do not have r-values.
|
||||||
*/
|
*/
|
||||||
|
|
@ -3601,13 +3592,13 @@ ast_switch_statement::test_to_hir(exec_list *instructions,
|
||||||
test_expression->hir(instructions,
|
test_expression->hir(instructions,
|
||||||
state);
|
state);
|
||||||
|
|
||||||
state->test_var = new(ctx) ir_variable(glsl_type::int_type,
|
state->switch_state.test_var = new(ctx) ir_variable(glsl_type::int_type,
|
||||||
"switch_test_tmp",
|
"switch_test_tmp",
|
||||||
ir_var_temporary);
|
ir_var_temporary);
|
||||||
ir_dereference_variable *deref_test_var =
|
ir_dereference_variable *deref_test_var =
|
||||||
new(ctx) ir_dereference_variable(state->test_var);
|
new(ctx) ir_dereference_variable(state->switch_state.test_var);
|
||||||
|
|
||||||
instructions->push_tail(state->test_var);
|
instructions->push_tail(state->switch_state.test_var);
|
||||||
instructions->push_tail(new(ctx) ir_assignment(deref_test_var,
|
instructions->push_tail(new(ctx) ir_assignment(deref_test_var,
|
||||||
test_val,
|
test_val,
|
||||||
NULL));
|
NULL));
|
||||||
|
|
@ -3650,9 +3641,9 @@ ast_case_statement::hir(exec_list *instructions,
|
||||||
*/
|
*/
|
||||||
ir_constant *const false_val = new(state) ir_constant(false);
|
ir_constant *const false_val = new(state) ir_constant(false);
|
||||||
ir_dereference_variable *const deref_is_fallthru_var =
|
ir_dereference_variable *const deref_is_fallthru_var =
|
||||||
new(state) ir_dereference_variable(state->is_fallthru_var);
|
new(state) ir_dereference_variable(state->switch_state.is_fallthru_var);
|
||||||
ir_dereference_variable *const deref_is_break_var =
|
ir_dereference_variable *const deref_is_break_var =
|
||||||
new(state) ir_dereference_variable(state->is_break_var);
|
new(state) ir_dereference_variable(state->switch_state.is_break_var);
|
||||||
ir_assignment *const reset_fallthru_on_break =
|
ir_assignment *const reset_fallthru_on_break =
|
||||||
new(state) ir_assignment(deref_is_fallthru_var,
|
new(state) ir_assignment(deref_is_fallthru_var,
|
||||||
false_val,
|
false_val,
|
||||||
|
|
@ -3662,7 +3653,7 @@ ast_case_statement::hir(exec_list *instructions,
|
||||||
/* Guard case statements depending on fallthru state.
|
/* Guard case statements depending on fallthru state.
|
||||||
*/
|
*/
|
||||||
ir_dereference_variable *const deref_fallthru_guard =
|
ir_dereference_variable *const deref_fallthru_guard =
|
||||||
new(state) ir_dereference_variable(state->is_fallthru_var);
|
new(state) ir_dereference_variable(state->switch_state.is_fallthru_var);
|
||||||
ir_if *const test_fallthru = new(state) ir_if(deref_fallthru_guard);
|
ir_if *const test_fallthru = new(state) ir_if(deref_fallthru_guard);
|
||||||
|
|
||||||
foreach_list_typed (ast_node, stmt, link, & this->stmts)
|
foreach_list_typed (ast_node, stmt, link, & this->stmts)
|
||||||
|
|
@ -3696,7 +3687,7 @@ ast_case_label::hir(exec_list *instructions,
|
||||||
void *ctx = state;
|
void *ctx = state;
|
||||||
|
|
||||||
ir_dereference_variable *deref_fallthru_var =
|
ir_dereference_variable *deref_fallthru_var =
|
||||||
new(ctx) ir_dereference_variable(state->is_fallthru_var);
|
new(ctx) ir_dereference_variable(state->switch_state.is_fallthru_var);
|
||||||
|
|
||||||
ir_rvalue *const true_val = new(ctx) ir_constant(true);
|
ir_rvalue *const true_val = new(ctx) ir_constant(true);
|
||||||
|
|
||||||
|
|
@ -3709,7 +3700,7 @@ ast_case_label::hir(exec_list *instructions,
|
||||||
ir_rvalue *const test_val = this->test_value->hir(instructions, state);
|
ir_rvalue *const test_val = this->test_value->hir(instructions, state);
|
||||||
|
|
||||||
ir_dereference_variable *deref_test_var =
|
ir_dereference_variable *deref_test_var =
|
||||||
new(ctx) ir_dereference_variable(state->test_var);
|
new(ctx) ir_dereference_variable(state->switch_state.test_var);
|
||||||
|
|
||||||
ir_rvalue *const test_cond = new(ctx) ir_expression(ir_binop_all_equal,
|
ir_rvalue *const test_cond = new(ctx) ir_expression(ir_binop_all_equal,
|
||||||
glsl_type::bool_type,
|
glsl_type::bool_type,
|
||||||
|
|
@ -3801,8 +3792,8 @@ ast_iteration_statement::hir(exec_list *instructions,
|
||||||
/* Likewise, indicate that following code is closest to a loop,
|
/* Likewise, indicate that following code is closest to a loop,
|
||||||
* NOT closest to a switch.
|
* NOT closest to a switch.
|
||||||
*/
|
*/
|
||||||
bool saved_is_switch_innermost = state->is_switch_innermost;
|
bool saved_is_switch_innermost = state->switch_state.is_switch_innermost;
|
||||||
state->is_switch_innermost = false;
|
state->switch_state.is_switch_innermost = false;
|
||||||
|
|
||||||
if (mode != ast_do_while)
|
if (mode != ast_do_while)
|
||||||
condition_to_hir(stmt, state);
|
condition_to_hir(stmt, state);
|
||||||
|
|
@ -3822,7 +3813,7 @@ ast_iteration_statement::hir(exec_list *instructions,
|
||||||
/* Restore previous nesting before returning.
|
/* Restore previous nesting before returning.
|
||||||
*/
|
*/
|
||||||
state->loop_nesting_ast = nesting_ast;
|
state->loop_nesting_ast = nesting_ast;
|
||||||
state->is_switch_innermost = saved_is_switch_innermost;
|
state->switch_state.is_switch_innermost = saved_is_switch_innermost;
|
||||||
|
|
||||||
/* Loops do not have r-values.
|
/* Loops do not have r-values.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *ctx,
|
||||||
this->info_log = ralloc_strdup(mem_ctx, "");
|
this->info_log = ralloc_strdup(mem_ctx, "");
|
||||||
this->error = false;
|
this->error = false;
|
||||||
this->loop_nesting_ast = NULL;
|
this->loop_nesting_ast = NULL;
|
||||||
this->switch_nesting_ast = NULL;
|
this->switch_state.switch_nesting_ast = NULL;
|
||||||
|
|
||||||
this->num_builtins_to_link = 0;
|
this->num_builtins_to_link = 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,15 @@ enum _mesa_glsl_parser_targets {
|
||||||
|
|
||||||
struct gl_context;
|
struct gl_context;
|
||||||
|
|
||||||
|
struct glsl_switch_state {
|
||||||
|
/** Temporary variables needed for switch statement. */
|
||||||
|
ir_variable *test_var;
|
||||||
|
ir_variable *is_fallthru_var;
|
||||||
|
ir_variable *is_break_var;
|
||||||
|
class ast_switch_statement *switch_nesting_ast;
|
||||||
|
bool is_switch_innermost; // if switch stmt is closest to break, ...
|
||||||
|
};
|
||||||
|
|
||||||
struct _mesa_glsl_parse_state {
|
struct _mesa_glsl_parse_state {
|
||||||
_mesa_glsl_parse_state(struct gl_context *ctx, GLenum target,
|
_mesa_glsl_parse_state(struct gl_context *ctx, GLenum target,
|
||||||
void *mem_ctx);
|
void *mem_ctx);
|
||||||
|
|
@ -150,13 +159,8 @@ struct _mesa_glsl_parse_state {
|
||||||
|
|
||||||
/** Loop or switch statement containing the current instructions. */
|
/** Loop or switch statement containing the current instructions. */
|
||||||
class ast_iteration_statement *loop_nesting_ast;
|
class ast_iteration_statement *loop_nesting_ast;
|
||||||
class ast_switch_statement *switch_nesting_ast;
|
|
||||||
bool is_switch_innermost; // if switch stmt is closest to break, ...
|
|
||||||
|
|
||||||
/** Temporary variables needed for switch statement. */
|
struct glsl_switch_state switch_state;
|
||||||
ir_variable *test_var;
|
|
||||||
ir_variable *is_fallthru_var;
|
|
||||||
ir_variable *is_break_var;
|
|
||||||
|
|
||||||
/** List of structures defined in user code. */
|
/** List of structures defined in user code. */
|
||||||
const glsl_type **user_structures;
|
const glsl_type **user_structures;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue