1b8e80941Smrg/* 2b8e80941Smrg * Copyright © 2013 Intel Corporation 3b8e80941Smrg * 4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 6b8e80941Smrg * to deal in the Software without restriction, including without limitation 7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 9b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 10b8e80941Smrg * 11b8e80941Smrg * The above copyright notice and this permission notice (including the next 12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 13b8e80941Smrg * Software. 14b8e80941Smrg * 15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21b8e80941Smrg * DEALINGS IN THE SOFTWARE. 22b8e80941Smrg */ 23b8e80941Smrg 24b8e80941Smrg/** 25b8e80941Smrg * \file opt_flip_matrices.cpp 26b8e80941Smrg * 27b8e80941Smrg * Convert (matrix * vector) operations to (vector * matrixTranspose), 28b8e80941Smrg * which can be done using dot products rather than multiplies and adds. 29b8e80941Smrg * On some hardware, this is more efficient. 30b8e80941Smrg * 31b8e80941Smrg * This currently only does the conversion for built-in matrices which 32b8e80941Smrg * already have transposed equivalents. Namely, gl_ModelViewProjectionMatrix 33b8e80941Smrg * and gl_TextureMatrix. 34b8e80941Smrg */ 35b8e80941Smrg#include "ir.h" 36b8e80941Smrg#include "ir_optimization.h" 37b8e80941Smrg#include "main/macros.h" 38b8e80941Smrg 39b8e80941Smrgnamespace { 40b8e80941Smrgclass matrix_flipper : public ir_hierarchical_visitor { 41b8e80941Smrgpublic: 42b8e80941Smrg matrix_flipper(exec_list *instructions) 43b8e80941Smrg { 44b8e80941Smrg progress = false; 45b8e80941Smrg mvp_transpose = NULL; 46b8e80941Smrg texmat_transpose = NULL; 47b8e80941Smrg 48b8e80941Smrg foreach_in_list(ir_instruction, ir, instructions) { 49b8e80941Smrg ir_variable *var = ir->as_variable(); 50b8e80941Smrg if (!var) 51b8e80941Smrg continue; 52b8e80941Smrg if (strcmp(var->name, "gl_ModelViewProjectionMatrixTranspose") == 0) 53b8e80941Smrg mvp_transpose = var; 54b8e80941Smrg if (strcmp(var->name, "gl_TextureMatrixTranspose") == 0) 55b8e80941Smrg texmat_transpose = var; 56b8e80941Smrg } 57b8e80941Smrg } 58b8e80941Smrg 59b8e80941Smrg ir_visitor_status visit_enter(ir_expression *ir); 60b8e80941Smrg 61b8e80941Smrg bool progress; 62b8e80941Smrg 63b8e80941Smrgprivate: 64b8e80941Smrg ir_variable *mvp_transpose; 65b8e80941Smrg ir_variable *texmat_transpose; 66b8e80941Smrg}; 67b8e80941Smrg} 68b8e80941Smrg 69b8e80941Smrgir_visitor_status 70b8e80941Smrgmatrix_flipper::visit_enter(ir_expression *ir) 71b8e80941Smrg{ 72b8e80941Smrg if (ir->operation != ir_binop_mul || 73b8e80941Smrg !ir->operands[0]->type->is_matrix() || 74b8e80941Smrg !ir->operands[1]->type->is_vector()) 75b8e80941Smrg return visit_continue; 76b8e80941Smrg 77b8e80941Smrg ir_variable *mat_var = ir->operands[0]->variable_referenced(); 78b8e80941Smrg if (!mat_var) 79b8e80941Smrg return visit_continue; 80b8e80941Smrg 81b8e80941Smrg if (mvp_transpose && 82b8e80941Smrg strcmp(mat_var->name, "gl_ModelViewProjectionMatrix") == 0) { 83b8e80941Smrg#ifndef NDEBUG 84b8e80941Smrg ir_dereference_variable *deref = ir->operands[0]->as_dereference_variable(); 85b8e80941Smrg assert(deref && deref->var == mat_var); 86b8e80941Smrg#endif 87b8e80941Smrg 88b8e80941Smrg void *mem_ctx = ralloc_parent(ir); 89b8e80941Smrg 90b8e80941Smrg ir->operands[0] = ir->operands[1]; 91b8e80941Smrg ir->operands[1] = new(mem_ctx) ir_dereference_variable(mvp_transpose); 92b8e80941Smrg 93b8e80941Smrg progress = true; 94b8e80941Smrg } else if (texmat_transpose && 95b8e80941Smrg strcmp(mat_var->name, "gl_TextureMatrix") == 0) { 96b8e80941Smrg ir_dereference_array *array_ref = ir->operands[0]->as_dereference_array(); 97b8e80941Smrg assert(array_ref != NULL); 98b8e80941Smrg ir_dereference_variable *var_ref = array_ref->array->as_dereference_variable(); 99b8e80941Smrg assert(var_ref && var_ref->var == mat_var); 100b8e80941Smrg 101b8e80941Smrg ir->operands[0] = ir->operands[1]; 102b8e80941Smrg ir->operands[1] = array_ref; 103b8e80941Smrg 104b8e80941Smrg var_ref->var = texmat_transpose; 105b8e80941Smrg 106b8e80941Smrg texmat_transpose->data.max_array_access = 107b8e80941Smrg MAX2(texmat_transpose->data.max_array_access, mat_var->data.max_array_access); 108b8e80941Smrg 109b8e80941Smrg progress = true; 110b8e80941Smrg } 111b8e80941Smrg 112b8e80941Smrg return visit_continue; 113b8e80941Smrg} 114b8e80941Smrg 115b8e80941Smrgbool 116b8e80941Smrgopt_flip_matrices(struct exec_list *instructions) 117b8e80941Smrg{ 118b8e80941Smrg matrix_flipper v(instructions); 119b8e80941Smrg 120b8e80941Smrg visit_list_elements(&v, instructions); 121b8e80941Smrg 122b8e80941Smrg return v.progress; 123b8e80941Smrg} 124