[Mesa-dev] [PATCH v3] glsl: Expand matrix flip optimization pass to cover more cases.
Iago Toral Quiroga
itoral at igalia.com
Wed Jun 18 23:57:59 PDT 2014
Also, as suggested by Ian Romanick, make it so we don't need a bunch of
individual handles to flippable matrices, instead we register
matrix/transpose_matrix pairs in a hash table for all built-in matrices
using the non-transpose matrix name as key.
---
I was wondering, is it really safe to only dup the variable name in the case
that transpose_ptr != NULL? What if the variable gets killed in other
optimization passes? we would have garbage keys in the hash table... wouldn't
that cause problems?
src/glsl/opt_flip_matrices.cpp | 153 +++++++++++++++++++++++++++++++----------
1 file changed, 117 insertions(+), 36 deletions(-)
diff --git a/src/glsl/opt_flip_matrices.cpp b/src/glsl/opt_flip_matrices.cpp
index 9044fd6..80ecb0d 100644
--- a/src/glsl/opt_flip_matrices.cpp
+++ b/src/glsl/opt_flip_matrices.cpp
@@ -29,44 +29,142 @@
* On some hardware, this is more efficient.
*
* This currently only does the conversion for built-in matrices which
- * already have transposed equivalents. Namely, gl_ModelViewProjectionMatrix
- * and gl_TextureMatrix.
+ * already have transposed equivalents.
*/
#include "ir.h"
#include "ir_optimization.h"
#include "main/macros.h"
+#include "program/hash_table.h"
namespace {
+
class matrix_flipper : public ir_hierarchical_visitor {
public:
+ struct matrix_and_transpose {
+ ir_variable *matrix;
+ ir_variable *transpose_matrix;
+ };
+
matrix_flipper(exec_list *instructions)
{
progress = false;
- mvp_transpose = NULL;
- texmat_transpose = NULL;
+
+ /* Build a hash table of built-in matrices and their transposes.
+ *
+ * The key for the entries in the hash table is the non-transpose matrix
+ * name. This assumes that all built-in transpose matrices have the
+ * "Transpose" suffix.
+ */
+ ht = hash_table_ctor(0, hash_table_string_hash,
+ hash_table_string_compare);
foreach_list(n, instructions) {
ir_instruction *ir = (ir_instruction *) n;
ir_variable *var = ir->as_variable();
+
if (!var)
continue;
- if (strcmp(var->name, "gl_ModelViewProjectionMatrixTranspose") == 0)
- mvp_transpose = var;
- if (strcmp(var->name, "gl_TextureMatrixTranspose") == 0)
- texmat_transpose = var;
+
+ /* Must be a matrix or array of matrices. */
+ if (!var->type->is_matrix() &&
+ !(var->type->is_array() && var->type->fields.array->is_matrix()))
+ continue;
+
+ /* Must be a built-in */
+ if (is_gl_identifier(var->name))
+ continue;
+
+ /* Create a new entry for this matrix if we don't have one yet */
+ bool new_entry = false;
+ struct matrix_and_transpose *entry =
+ (struct matrix_and_transpose *) hash_table_find(ht, var->name);
+ if (!entry) {
+ new_entry = true;
+ entry = new struct matrix_and_transpose();
+ entry->matrix = NULL;
+ entry->transpose_matrix = NULL;
+ }
+
+ const char *transpose_ptr = strstr(var->name, "Transpose");
+ if (transpose_ptr == NULL) {
+ entry->matrix = var;
+ } else {
+ /* We should not be adding transpose built-in matrices that do
+ * not end in 'Transpose'.
+ */
+ assert(transpose_ptr[9] == 0);
+ entry->transpose_matrix = var;
+ }
+
+ if (new_entry) {
+ char *entry_key;
+ if (transpose_ptr == NULL) {
+ entry_key = (char *) var->name;
+ } else {
+ entry_key =
+ ralloc_strndup(this, var->name, transpose_ptr - var->name);
+ }
+ hash_table_insert(ht, entry, entry_key);
+ }
}
}
+ ~matrix_flipper()
+ {
+ hash_table_dtor(ht);
+ }
+
ir_visitor_status visit_enter(ir_expression *ir);
bool progress;
private:
- ir_variable *mvp_transpose;
- ir_variable *texmat_transpose;
+ void transform_operands(ir_expression *ir,
+ ir_variable *mat_var,
+ ir_variable *mat_transpose);
+ void transform_operands_array_of_matrix(ir_expression *ir,
+ ir_variable *mat_var,
+ ir_variable *mat_transpose);
+ struct hash_table *ht;
};
}
+void
+matrix_flipper::transform_operands(ir_expression *ir,
+ ir_variable *mat_var,
+ ir_variable *mat_transpose)
+{
+#ifndef NDEBUG
+ ir_dereference_variable *deref = ir->operands[0]->as_dereference_variable();
+ assert(deref && deref->var == mat_var);
+#endif
+
+ void *mem_ctx = ralloc_parent(ir);
+ ir->operands[0] = ir->operands[1];
+ ir->operands[1] = new(mem_ctx) ir_dereference_variable(mat_transpose);
+}
+
+void
+matrix_flipper::transform_operands_array_of_matrix(ir_expression *ir,
+ ir_variable *mat_var,
+ ir_variable *mat_transpose)
+{
+ ir_dereference_array *array_ref = ir->operands[0]->as_dereference_array();
+ assert(array_ref != NULL);
+ ir_dereference_variable *var_ref =
+ array_ref->array->as_dereference_variable();
+ assert(var_ref && var_ref->var == mat_var);
+
+ ir->operands[0] = ir->operands[1];
+ ir->operands[1] = array_ref;
+
+ var_ref->var = mat_transpose;
+
+ mat_transpose->data.max_array_access =
+ MAX2(mat_transpose->data.max_array_access,
+ mat_var->data.max_array_access);
+}
+
ir_visitor_status
matrix_flipper::visit_enter(ir_expression *ir)
{
@@ -79,34 +177,17 @@ matrix_flipper::visit_enter(ir_expression *ir)
if (!mat_var)
return visit_continue;
- if (mvp_transpose &&
- strcmp(mat_var->name, "gl_ModelViewProjectionMatrix") == 0) {
-#ifndef NDEBUG
- ir_dereference_variable *deref = ir->operands[0]->as_dereference_variable();
- assert(deref && deref->var == mat_var);
-#endif
-
- void *mem_ctx = ralloc_parent(ir);
-
- ir->operands[0] = ir->operands[1];
- ir->operands[1] = new(mem_ctx) ir_dereference_variable(mvp_transpose);
+ struct matrix_and_transpose *entry =
+ (struct matrix_and_transpose *) hash_table_find(ht, mat_var->name);
+ if (!entry || !entry->transpose_matrix)
+ return visit_continue;
+ if (strcmp(mat_var->name, "gl_TextureMatrix") == 0 ||
+ strcmp(mat_var->name, "gl_TextureMatrixInverse") == 0) {
+ transform_operands_array_of_matrix(ir, mat_var, entry->transpose_matrix);
progress = true;
- } else if (texmat_transpose &&
- strcmp(mat_var->name, "gl_TextureMatrix") == 0) {
- ir_dereference_array *array_ref = ir->operands[0]->as_dereference_array();
- assert(array_ref != NULL);
- ir_dereference_variable *var_ref = array_ref->array->as_dereference_variable();
- assert(var_ref && var_ref->var == mat_var);
-
- ir->operands[0] = ir->operands[1];
- ir->operands[1] = array_ref;
-
- var_ref->var = texmat_transpose;
-
- texmat_transpose->data.max_array_access =
- MAX2(texmat_transpose->data.max_array_access, mat_var->data.max_array_access);
-
+ } else {
+ transform_operands(ir, mat_var, entry->transpose_matrix);
progress = true;
}
--
1.9.1
More information about the mesa-dev
mailing list