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