diff options
author | Kenneth Graunke <[email protected]> | 2010-07-08 18:15:32 -0700 |
---|---|---|
committer | Ian Romanick <[email protected]> | 2010-07-09 09:46:29 -0700 |
commit | 284d821206d74fddb346cd0d892d2dcec463e2a5 (patch) | |
tree | 25710ffdc3dd47da4522f7c927e1f62fdb7d0d85 /src/glsl | |
parent | f58bbd134e921b14f50ecd1e76b2943753ba194c (diff) |
ast_function: Fix non-float constructors with matrix arguments.
Previously, code like ivec4(mat2(...)) would fail because the compiler
would naively try to convert a mat2 to an imat2...which doesn't exist.
Now, a separate pass breaks such matrices down to their columns, which
can be converted from vec2 to ivec2.
Fixes piglit tests constructor-11.vert, constructor-14.vert,
constructor-15.vert, and CorrectConstFolding2.frag.
Diffstat (limited to 'src/glsl')
-rw-r--r-- | src/glsl/ast_function.cpp | 77 |
1 files changed, 55 insertions, 22 deletions
diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp index 566eac4d332..9315a92ecbc 100644 --- a/src/glsl/ast_function.cpp +++ b/src/glsl/ast_function.cpp @@ -922,8 +922,6 @@ ast_function_expression::hir(exec_list *instructions, unsigned nonmatrix_parameters = 0; exec_list actual_parameters; - bool all_parameters_are_constant = true; - foreach_list (n, &this->expressions) { ast_node *ast = exec_node_data(ast_node, n, link); ir_rvalue *result = ast->hir(instructions, state)->as_rvalue(); @@ -955,26 +953,6 @@ ast_function_expression::hir(exec_list *instructions, else nonmatrix_parameters++; - /* Type cast the parameter and add it to the parameter list for - * the constructor. - */ - const glsl_type *desired_type = - glsl_type::get_instance(constructor_type->base_type, - result->type->vector_elements, - result->type->matrix_columns); - result = convert_component(result, desired_type); - - /* Attempt to convert the parameter to a constant valued expression. - * After doing so, track whether or not all the parameters to the - * constructor are trivially constant valued expressions. - */ - ir_rvalue *const constant = result->constant_expression_value(); - - if (constant != NULL) - result = constant; - else - all_parameters_are_constant = false; - actual_parameters.push_tail(result); components_used += result->type->components(); } @@ -1019,6 +997,61 @@ ast_function_expression::hir(exec_list *instructions, return ir_call::get_error_instruction(ctx); } + /* Later, we cast each parameter to the same base type as the + * constructor. Since there are no non-floating point matrices, we + * need to break them up into a series of column vectors. + */ + if (constructor_type->base_type != GLSL_TYPE_FLOAT) { + foreach_list_safe(n, &actual_parameters) { + ir_rvalue *matrix = (ir_rvalue *) n; + + if (!matrix->type->is_matrix()) + continue; + + /* Create a temporary containing the matrix. */ + ir_variable *var = new(ctx) ir_variable(matrix->type, "matrix_tmp"); + instructions->push_tail(var); + instructions->push_tail(new(ctx) ir_assignment(new(ctx) + ir_dereference_variable(var), matrix, NULL)); + var->constant_value = matrix->constant_expression_value(); + + /* Replace the matrix with dereferences of its columns. */ + for (int i = 0; i < matrix->type->matrix_columns; i++) { + matrix->insert_before(new (ctx) ir_dereference_array(var, + new(ctx) ir_constant(i))); + } + matrix->remove(); + } + } + + bool all_parameters_are_constant = true; + + /* Type cast each parameter and, if possible, fold constants.*/ + foreach_list_safe(n, &actual_parameters) { + ir_rvalue *ir = (ir_rvalue *) n; + + const glsl_type *desired_type = + glsl_type::get_instance(constructor_type->base_type, + ir->type->vector_elements, + ir->type->matrix_columns); + ir_rvalue *result = convert_component(ir, desired_type); + + /* Attempt to convert the parameter to a constant valued expression. + * After doing so, track whether or not all the parameters to the + * constructor are trivially constant valued expressions. + */ + ir_rvalue *const constant = result->constant_expression_value(); + + if (constant != NULL) + result = constant; + else + all_parameters_are_constant = false; + + if (result != ir) { + ir->insert_before(result); + ir->remove(); + } + } /* If all of the parameters are trivially constant, create a * constant representing the complete collection of parameters. |