Fixes new piglit test: tests/spec/glsl-1.20/execution/qualifiers/vs-out-conversion-int-to-float-vec4-index.shader_test --- src/compiler/glsl/ast_function.cpp | 94 ++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+)
diff --git a/src/compiler/glsl/ast_function.cpp b/src/compiler/glsl/ast_function.cpp index 94e0a16a9c0..eab18446ef8 100644 --- a/src/compiler/glsl/ast_function.cpp +++ b/src/compiler/glsl/ast_function.cpp @@ -348,6 +348,93 @@ verify_parameter_modes(_mesa_glsl_parse_state *state, return true; } +static void +copy_index_derefs_to_temps(void *mem_ctx, ir_rvalue *param, + exec_list *before_instructions) +{ + /* Loop through the IR copying array indices until we find a swizzle, + * costant or variable ref. + */ + ir_rvalue *ir = param; + while (ir != NULL) { + switch (ir->ir_type) { + case ir_type_dereference_record: { + ir_dereference_record *r = (ir_dereference_record *) ir; + ir = r->record->as_dereference(); + break; + } + + case ir_type_swizzle: { + ir_swizzle *s = (ir_swizzle *) ir; + ir = s->val->as_dereference(); + break; + } + + case ir_type_expression: { + ir_expression *expr = (ir_expression* ) ir; + for (unsigned int i = 0; i < expr->num_operands; i++) { + copy_index_derefs_to_temps(mem_ctx, expr->operands[i], + before_instructions); + } + + ir = NULL; + break; + } + + case ir_type_dereference_array: { + ir_dereference_array *a = (ir_dereference_array *) ir; + ir = a->array->as_dereference(); + + ir_rvalue *idx = a->array_index; + copy_index_derefs_to_temps(mem_ctx, idx, before_instructions); + + if (idx->as_dereference_variable()) { + ir_variable *var = idx->variable_referenced(); + + /* If the index is read only it cannot change so there is no need + * to copy it. + */ + if (var->data.read_only || var->data.memory_read_only) + break; + } + + ir_variable *tmp = new(mem_ctx) ir_variable(idx->type, "idx_tmp", + ir_var_temporary); + before_instructions->push_tail(tmp); + + ir_dereference_variable *const deref_tmp_1 = + new(mem_ctx) ir_dereference_variable(tmp); + ir_assignment *const assignment = + new(mem_ctx) ir_assignment(deref_tmp_1, + idx->clone(mem_ctx, NULL)); + before_instructions->push_tail(assignment); + + /* Replace the array index with a dereference of the new temporary. + */ + ir_dereference_variable *const deref_tmp_2 = + new(mem_ctx) ir_dereference_variable(tmp); + a->array_index = deref_tmp_2; + break; + } + + case ir_type_dereference_variable: { + ir = NULL; + break; + } + + case ir_type_constant: { + /* Nothing to do for constants */ + ir = NULL; + break; + } + + default: + unreachable("Unexpected deref type"); + break; + } + } +} + static void fix_parameter(void *mem_ctx, ir_rvalue *actual, const glsl_type *formal_type, exec_list *before_instructions, exec_list *after_instructions, @@ -362,6 +449,13 @@ fix_parameter(void *mem_ctx, ir_rvalue *actual, const glsl_type *formal_type, && (expr == NULL || expr->operation != ir_binop_vector_extract)) return; + /* An array index could also be an out variable so we need to make a copy + * of them before the function is called. + */ + if (!actual->as_dereference_variable()) { + copy_index_derefs_to_temps(mem_ctx, actual, before_instructions); + } + /* To convert an out parameter, we need to create a temporary variable to * hold the value before conversion, and then perform the conversion after * the function call returns. -- 2.17.0 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev