• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
matrix_flipper(exec_list * instructions)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
visit_enter(ir_expression * ir)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
opt_flip_matrices(struct exec_list * instructions)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