101e04c3fSmrg/* 201e04c3fSmrg * Copyright © 2013 Intel Corporation 301e04c3fSmrg * 401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 501e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 601e04c3fSmrg * to deal in the Software without restriction, including without limitation 701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 901e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1001e04c3fSmrg * 1101e04c3fSmrg * The above copyright notice and this permission notice (including the next 1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1301e04c3fSmrg * Software. 1401e04c3fSmrg * 1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2101e04c3fSmrg * DEALINGS IN THE SOFTWARE. 2201e04c3fSmrg */ 2301e04c3fSmrg 2401e04c3fSmrg/** 2501e04c3fSmrg * \file opt_flip_matrices.cpp 2601e04c3fSmrg * 2701e04c3fSmrg * Convert (matrix * vector) operations to (vector * matrixTranspose), 2801e04c3fSmrg * which can be done using dot products rather than multiplies and adds. 2901e04c3fSmrg * On some hardware, this is more efficient. 3001e04c3fSmrg * 3101e04c3fSmrg * This currently only does the conversion for built-in matrices which 3201e04c3fSmrg * already have transposed equivalents. Namely, gl_ModelViewProjectionMatrix 3301e04c3fSmrg * and gl_TextureMatrix. 3401e04c3fSmrg */ 3501e04c3fSmrg#include "ir.h" 3601e04c3fSmrg#include "ir_optimization.h" 3701e04c3fSmrg#include "main/macros.h" 3801e04c3fSmrg 3901e04c3fSmrgnamespace { 4001e04c3fSmrgclass matrix_flipper : public ir_hierarchical_visitor { 4101e04c3fSmrgpublic: 4201e04c3fSmrg matrix_flipper(exec_list *instructions) 4301e04c3fSmrg { 4401e04c3fSmrg progress = false; 4501e04c3fSmrg mvp_transpose = NULL; 4601e04c3fSmrg texmat_transpose = NULL; 4701e04c3fSmrg 4801e04c3fSmrg foreach_in_list(ir_instruction, ir, instructions) { 4901e04c3fSmrg ir_variable *var = ir->as_variable(); 5001e04c3fSmrg if (!var) 5101e04c3fSmrg continue; 5201e04c3fSmrg if (strcmp(var->name, "gl_ModelViewProjectionMatrixTranspose") == 0) 5301e04c3fSmrg mvp_transpose = var; 5401e04c3fSmrg if (strcmp(var->name, "gl_TextureMatrixTranspose") == 0) 5501e04c3fSmrg texmat_transpose = var; 5601e04c3fSmrg } 5701e04c3fSmrg } 5801e04c3fSmrg 5901e04c3fSmrg ir_visitor_status visit_enter(ir_expression *ir); 6001e04c3fSmrg 6101e04c3fSmrg bool progress; 6201e04c3fSmrg 6301e04c3fSmrgprivate: 6401e04c3fSmrg ir_variable *mvp_transpose; 6501e04c3fSmrg ir_variable *texmat_transpose; 6601e04c3fSmrg}; 6701e04c3fSmrg} 6801e04c3fSmrg 6901e04c3fSmrgir_visitor_status 7001e04c3fSmrgmatrix_flipper::visit_enter(ir_expression *ir) 7101e04c3fSmrg{ 7201e04c3fSmrg if (ir->operation != ir_binop_mul || 7301e04c3fSmrg !ir->operands[0]->type->is_matrix() || 7401e04c3fSmrg !ir->operands[1]->type->is_vector()) 7501e04c3fSmrg return visit_continue; 7601e04c3fSmrg 7701e04c3fSmrg ir_variable *mat_var = ir->operands[0]->variable_referenced(); 7801e04c3fSmrg if (!mat_var) 7901e04c3fSmrg return visit_continue; 8001e04c3fSmrg 8101e04c3fSmrg if (mvp_transpose && 8201e04c3fSmrg strcmp(mat_var->name, "gl_ModelViewProjectionMatrix") == 0) { 8301e04c3fSmrg#ifndef NDEBUG 8401e04c3fSmrg ir_dereference_variable *deref = ir->operands[0]->as_dereference_variable(); 8501e04c3fSmrg assert(deref && deref->var == mat_var); 8601e04c3fSmrg#endif 8701e04c3fSmrg 8801e04c3fSmrg void *mem_ctx = ralloc_parent(ir); 8901e04c3fSmrg 9001e04c3fSmrg ir->operands[0] = ir->operands[1]; 9101e04c3fSmrg ir->operands[1] = new(mem_ctx) ir_dereference_variable(mvp_transpose); 9201e04c3fSmrg 9301e04c3fSmrg progress = true; 9401e04c3fSmrg } else if (texmat_transpose && 9501e04c3fSmrg strcmp(mat_var->name, "gl_TextureMatrix") == 0) { 9601e04c3fSmrg ir_dereference_array *array_ref = ir->operands[0]->as_dereference_array(); 9701e04c3fSmrg assert(array_ref != NULL); 9801e04c3fSmrg ir_dereference_variable *var_ref = array_ref->array->as_dereference_variable(); 9901e04c3fSmrg assert(var_ref && var_ref->var == mat_var); 10001e04c3fSmrg 10101e04c3fSmrg ir->operands[0] = ir->operands[1]; 10201e04c3fSmrg ir->operands[1] = array_ref; 10301e04c3fSmrg 10401e04c3fSmrg var_ref->var = texmat_transpose; 10501e04c3fSmrg 10601e04c3fSmrg texmat_transpose->data.max_array_access = 10701e04c3fSmrg MAX2(texmat_transpose->data.max_array_access, mat_var->data.max_array_access); 10801e04c3fSmrg 10901e04c3fSmrg progress = true; 11001e04c3fSmrg } 11101e04c3fSmrg 11201e04c3fSmrg return visit_continue; 11301e04c3fSmrg} 11401e04c3fSmrg 11501e04c3fSmrgbool 11601e04c3fSmrgopt_flip_matrices(struct exec_list *instructions) 11701e04c3fSmrg{ 11801e04c3fSmrg matrix_flipper v(instructions); 11901e04c3fSmrg 12001e04c3fSmrg visit_list_elements(&v, instructions); 12101e04c3fSmrg 12201e04c3fSmrg return v.progress; 12301e04c3fSmrg} 124