diff options
Diffstat (limited to 'src/glsl')
| -rw-r--r-- | src/glsl/ir_mat_op_to_vec.cpp | 197 | 
1 files changed, 188 insertions, 9 deletions
| diff --git a/src/glsl/ir_mat_op_to_vec.cpp b/src/glsl/ir_mat_op_to_vec.cpp index 828c63c17a..7bdb9057d8 100644 --- a/src/glsl/ir_mat_op_to_vec.cpp +++ b/src/glsl/ir_mat_op_to_vec.cpp @@ -44,7 +44,17 @@ public:     ir_visitor_status visit_leave(ir_assignment *); -   ir_rvalue *get_column(ir_variable *var, int i); +   ir_rvalue *get_column(ir_variable *var, int col); +   ir_rvalue *get_element(ir_variable *var, int col, int row); + +   void do_mul_mat_mat(ir_variable *result_var, +		       ir_variable *a_var, ir_variable *b_var); +   void do_mul_mat_vec(ir_variable *result_var, +		       ir_variable *a_var, ir_variable *b_var); +   void do_mul_vec_mat(ir_variable *result_var, +		       ir_variable *a_var, ir_variable *b_var); +   void do_mul_mat_scalar(ir_variable *result_var, +			  ir_variable *a_var, ir_variable *b_var);     bool made_progress;  }; @@ -83,7 +93,24 @@ do_mat_op_to_vec(exec_list *instructions)  }  ir_rvalue * -ir_mat_op_to_vec_visitor::get_column(ir_variable *var, int i) +ir_mat_op_to_vec_visitor::get_element(ir_variable *var, int col, int row) +{ +   ir_dereference *deref; + +   deref = new(base_ir) ir_dereference_variable(var); + +   if (var->type->is_matrix()) { +      deref = new(base_ir) ir_dereference_array(var, +						new(base_ir) ir_constant(col)); +   } else { +      assert(col == 0); +   } + +   return new(base_ir) ir_swizzle(deref, row, 0, 0, 0, 1); +} + +ir_rvalue * +ir_mat_op_to_vec_visitor::get_column(ir_variable *var, int row)  {     ir_dereference *deref; @@ -92,12 +119,152 @@ ir_mat_op_to_vec_visitor::get_column(ir_variable *var, int i)     } else {        deref = new(base_ir) ir_dereference_variable(var);        deref = new(base_ir) ir_dereference_array(deref, -						new(base_ir) ir_constant(i)); +						new(base_ir) ir_constant(row));     }     return deref;  } +void +ir_mat_op_to_vec_visitor::do_mul_mat_mat(ir_variable *result_var, +					 ir_variable *a_var, +					 ir_variable *b_var) +{ +   int b_col, i; +   ir_assignment *assign; +   ir_expression *expr; + +   for (b_col = 0; b_col < b_var->type->matrix_columns; b_col++) { +      ir_rvalue *a = get_column(a_var, 0); +      ir_rvalue *b = get_element(b_var, b_col, 0); + +      /* first column */ +      expr = new(base_ir) ir_expression(ir_binop_mul, +					a->type, +					a, +					b); + +      /* following columns */ +      for (i = 1; i < a_var->type->matrix_columns; i++) { +	 ir_expression *mul_expr; + +	 a = get_column(a_var, i); +	 b = get_element(b_var, b_col, i); + +	 mul_expr = new(base_ir) ir_expression(ir_binop_mul, +					       a->type, +					       a, +					       b); +	 expr = new(base_ir) ir_expression(ir_binop_add, +					   a->type, +					   expr, +					   mul_expr); +      } + +      ir_rvalue *result = get_column(result_var, b_col); +      assign = new(base_ir) ir_assignment(result, +					  expr, +					  NULL); +      base_ir->insert_before(assign); +   } +} + +void +ir_mat_op_to_vec_visitor::do_mul_mat_vec(ir_variable *result_var, +					 ir_variable *a_var, +					 ir_variable *b_var) +{ +   int i; +   ir_rvalue *a = get_column(a_var, 0); +   ir_rvalue *b = get_element(b_var, 0, 0); +   ir_assignment *assign; +   ir_expression *expr; + +   /* first column */ +   expr = new(base_ir) ir_expression(ir_binop_mul, +				     result_var->type, +				     a, +				     b); + +   /* following columns */ +   for (i = 1; i < a_var->type->matrix_columns; i++) { +      ir_expression *mul_expr; + +      a = get_column(a_var, i); +      b = get_element(b_var, 0, i); + +      mul_expr = new(base_ir) ir_expression(ir_binop_mul, +					    result_var->type, +					    a, +					    b); +      expr = new(base_ir) ir_expression(ir_binop_add, +					result_var->type, +					expr, +					mul_expr); +   } + +   ir_rvalue *result = new(base_ir) ir_dereference_variable(result_var); +   assign = new(base_ir) ir_assignment(result, +				       expr, +				       NULL); +   base_ir->insert_before(assign); +} + +void +ir_mat_op_to_vec_visitor::do_mul_vec_mat(ir_variable *result_var, +					 ir_variable *a_var, +					 ir_variable *b_var) +{ +   int i; + +   for (i = 0; i < b_var->type->matrix_columns; i++) { +      ir_rvalue *a = new(base_ir) ir_dereference_variable(a_var); +      ir_rvalue *b = get_column(b_var, i); +      ir_rvalue *result; +      ir_expression *column_expr; +      ir_assignment *column_assign; + +      result = new(base_ir) ir_dereference_variable(result_var); +      result = new(base_ir) ir_swizzle(result, i, 0, 0, 0, 1); + +      column_expr = new(base_ir) ir_expression(ir_binop_dot, +					       result->type, +					       a, +					       b); + +      column_assign = new(base_ir) ir_assignment(result, +						 column_expr, +						 NULL); +      base_ir->insert_before(column_assign); +   } +} + +void +ir_mat_op_to_vec_visitor::do_mul_mat_scalar(ir_variable *result_var, +					    ir_variable *a_var, +					    ir_variable *b_var) +{ +   int i; + +   for (i = 0; i < a_var->type->matrix_columns; i++) { +      ir_rvalue *a = get_column(a_var, i); +      ir_rvalue *b = new(base_ir) ir_dereference_variable(b_var); +      ir_rvalue *result = get_column(result_var, i); +      ir_expression *column_expr; +      ir_assignment *column_assign; + +      column_expr = new(base_ir) ir_expression(ir_binop_mul, +					       result->type, +					       a, +					       b); + +      column_assign = new(base_ir) ir_assignment(result, +						 column_expr, +						 NULL); +      base_ir->insert_before(column_assign); +   } +} +  ir_visitor_status  ir_mat_op_to_vec_visitor::visit_leave(ir_assignment *assign)  { @@ -119,10 +286,6 @@ ir_mat_op_to_vec_visitor::visit_leave(ir_assignment *assign)     if (!found_matrix)        return visit_continue; -   /* FINISHME: see below */ -   if (expr->operation == ir_binop_mul) -      return visit_continue; -     ir_dereference_variable *lhs_deref = assign->lhs->as_dereference_variable();     assert(lhs_deref); @@ -174,8 +337,24 @@ ir_mat_op_to_vec_visitor::visit_leave(ir_assignment *assign)        }        break;     case ir_binop_mul: -      /* FINISHME */ -      return visit_continue; +      if (op_var[0]->type->is_matrix()) { +	 if (op_var[1]->type->is_matrix()) { +	    do_mul_mat_mat(result_var, op_var[0], op_var[1]); +	 } else if (op_var[1]->type->is_vector()) { +	    do_mul_mat_vec(result_var, op_var[0], op_var[1]); +	 } else { +	    assert(op_var[1]->type->is_scalar()); +	    do_mul_mat_scalar(result_var, op_var[0], op_var[1]); +	 } +      } else { +	 assert(op_var[1]->type->is_matrix()); +	 if (op_var[0]->type->is_vector()) { +	    do_mul_vec_mat(result_var, op_var[0], op_var[1]); +	 } else { +	    assert(op_var[0]->type->is_scalar()); +	    do_mul_mat_scalar(result_var, op_var[1], op_var[0]); +	 } +      }        break;     default:        printf("FINISHME: Handle matrix operation for %s\n", expr->operator_string()); | 
