Inout parameters which depended on other inout parameters where not assigned in the correct order.
Fixes the following piglit tests in shaders/out-parameter-indexing: vs-inout-index-inout-float-array vs-inout-index-inout-mat2-col vs-inout-index-inout-mat2-row vs-inout-index-inout-vec4 vs-inout-index-inout-vec4-array vs-inout-index-inout-vec4-array-element Signed-off-by: Lars Hamre <cheme...@gmail.com> --- NOTES: - Someone with access will need to commit this post review process. - Not sure if this is the "mesa" approach to this problem, feedback is appreciated. src/compiler/glsl/opt_function_inlining.cpp | 80 ++++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 7 deletions(-) diff --git a/src/compiler/glsl/opt_function_inlining.cpp b/src/compiler/glsl/opt_function_inlining.cpp index 19f5fae..a5e7ea6 100644 --- a/src/compiler/glsl/opt_function_inlining.cpp +++ b/src/compiler/glsl/opt_function_inlining.cpp @@ -95,6 +95,54 @@ replace_return_with_assignment(ir_instruction *ir, void *data) } } +static void +gather_inout_vars_from_params(void *ctx, + exec_list *actual_params, + exec_list *callee_params, + exec_list *inout_vars) +{ + foreach_two_lists(formal_node, callee_params, + actual_node, actual_params) { + ir_rvalue *const param = (ir_rvalue *)actual_node; + const ir_variable *const sig_param = (ir_variable *)formal_node; + + if (sig_param->data.mode == ir_var_function_inout && + param->ir_type == ir_type_dereference_variable) { + inout_vars->push_tail(sig_param->clone(ctx, NULL)); + } + } +} + +static bool +rvalue_depends_on_inout_var_helper(ir_rvalue *rv, exec_list *inout_vars) +{ + if (rv->ir_type == ir_type_dereference_array) { + ir_dereference_array *deref_arr = (ir_dereference_array *)rv; + return (rvalue_depends_on_inout_var_helper(deref_arr->array, inout_vars) || + rvalue_depends_on_inout_var_helper(deref_arr->array_index, inout_vars)); + } else if (rv->ir_type == ir_type_swizzle) { + return rvalue_depends_on_inout_var_helper(((ir_swizzle *)rv)->val, inout_vars); + } else if (rv->ir_type == ir_type_dereference_variable) { + const char *var_name = ((ir_dereference_variable *)rv)->var->name; + foreach_in_list(ir_variable, inout_var, inout_vars) { + if (!strcmp(var_name, inout_var->name)) { + return true; + } + } + } + return false; +} + +static bool +rvalue_depends_on_inout_var(ir_rvalue *rv, exec_list *inout_vars) +{ + if (rv->ir_type == ir_type_dereference_array || + rv->ir_type == ir_type_swizzle) { + return rvalue_depends_on_inout_var_helper(rv, inout_vars); + } + return false; +} + void ir_call::generate_inline(ir_instruction *next_ir) { @@ -185,7 +233,14 @@ ir_call::generate_inline(ir_instruction *next_ir) /* Copy back the value of any 'out' parameters from the function body * variables to our own. */ + + exec_list inout_vars; + gather_inout_vars_from_params(ctx, &this->actual_parameters, + &this->callee->parameters, + &inout_vars); + i = 0; + ir_instruction *last_non_dependent_inout_assigned = next_ir; foreach_two_lists(formal_node, &this->callee->parameters, actual_node, &this->actual_parameters) { ir_rvalue *const param = (ir_rvalue *) actual_node; @@ -194,12 +249,24 @@ ir_call::generate_inline(ir_instruction *next_ir) /* Move our param variable into the actual param if it's an 'out' type. */ if (parameters[i] && (sig_param->data.mode == ir_var_function_out || sig_param->data.mode == ir_var_function_inout)) { - ir_assignment *assign; - - assign = new(ctx) ir_assignment(param->clone(ctx, NULL)->as_rvalue(), - new(ctx) ir_dereference_variable(parameters[i]), - NULL); - next_ir->insert_before(assign); + ir_assignment *assign; + + assign = new(ctx) ir_assignment(param->clone(ctx, NULL)->as_rvalue(), + new(ctx) ir_dereference_variable(parameters[i]), + NULL); + + if (sig_param->data.mode == ir_var_function_inout && + rvalue_depends_on_inout_var(param, &inout_vars)) { + /* + * Insert assignment before the others if it depends on another + * inout parameter. + */ + last_non_dependent_inout_assigned->insert_before(assign); + } else { + /* Otherwise insert assignment before the next_ir */ + next_ir->insert_before(assign); + last_non_dependent_inout_assigned = assign; + } } ++i; @@ -210,7 +277,6 @@ ir_call::generate_inline(ir_instruction *next_ir) hash_table_dtor(ht); } - ir_visitor_status ir_function_inlining_visitor::visit_enter(ir_expression *ir) { -- 2.5.5 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev