Re: [Mesa-dev] [PATCH v2] glsl: Expand matrix flip optimization pass to cover more cases.

2014-06-18 Thread Iago Toral
On Wed, 2014-06-18 at 14:43 -0700, Ian Romanick wrote:
> On 06/18/2014 05:03 AM, Iago Toral Quiroga wrote:
> > 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.
> > ---
> >  src/glsl/opt_flip_matrices.cpp | 145 
> > ++---
> >  1 file changed, 108 insertions(+), 37 deletions(-)
> > 
> > diff --git a/src/glsl/opt_flip_matrices.cpp b/src/glsl/opt_flip_matrices.cpp
> > index 9044fd6..d0b8125 100644
> > --- a/src/glsl/opt_flip_matrices.cpp
> > +++ b/src/glsl/opt_flip_matrices.cpp
> > @@ -29,44 +29,132 @@
> >   * 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)
> > +
> > + /* Must be a matrix */
> > + if (!var || !var->type->is_matrix())
> >  continue;
> 
> gl_TextureMatrix is an array of matrices, so var->type->is_matrix()
> will fail.  I think you want:
> 
>  if (!var)
> continue;
> 
>  /* Must be a matrix or array of matrices. */
>  if (!var->type->is_matrix() && 
>  !(var->type->is_array() && var->type->fields.array->is_matrix()))
> continue;

Oh, right.

> > - if (strcmp(var->name, "gl_ModelViewProjectionMatrixTranspose") == 
> > 0)
> > -mvp_transpose = var;
> > - if (strcmp(var->name, "gl_TextureMatrixTranspose") == 0)
> > -texmat_transpose = var;
> > + /* Must be a built-in */
> > + if (strstr(var->name, "gl_") != var->name)
> > +continue;
> 
> The name has to start with gl_, not just contain it.  Use
> is_gl_identifier(var->name) instead.

Actually, this checks that it starts with it (see != var->name), but
I'll use is_gl_identifier.

> > +
> > + /* 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 {
> 
> It's probably worth adding an assertion in case a built-in is ever
> added with something after Transpose.  The probability is very, very
> low, but I'd rather be safe.

Sure, I will add that.

>assert(transpose_ptr[9] == 0);
> 
> > +entry->transpose_matrix = var;
> > + }
> > +
> > + if (new_entry) {
> > +char *entry_key;
> > +if (transpose_ptr == NULL) {
> > +   entry_key = strdup(var->name);
> > +} else {
> > +   entry_key = strndup(var->name, transpose_ptr - var->name);
> > +}
> 
> hash_table_dtor doesn't free the keys, so all of this memory leaks.
> Use ralloc_strndup, and only copy the name in the transpose_ptr != NULL
> case.

Ok.

> > +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_transpos

Re: [Mesa-dev] [PATCH v2] glsl: Expand matrix flip optimization pass to cover more cases.

2014-06-18 Thread Ian Romanick
On 06/18/2014 05:03 AM, Iago Toral Quiroga wrote:
> 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.
> ---
>  src/glsl/opt_flip_matrices.cpp | 145 
> ++---
>  1 file changed, 108 insertions(+), 37 deletions(-)
> 
> diff --git a/src/glsl/opt_flip_matrices.cpp b/src/glsl/opt_flip_matrices.cpp
> index 9044fd6..d0b8125 100644
> --- a/src/glsl/opt_flip_matrices.cpp
> +++ b/src/glsl/opt_flip_matrices.cpp
> @@ -29,44 +29,132 @@
>   * 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)
> +
> + /* Must be a matrix */
> + if (!var || !var->type->is_matrix())
>  continue;

gl_TextureMatrix is an array of matrices, so var->type->is_matrix()
will fail.  I think you want:

 if (!var)
continue;

 /* Must be a matrix or array of matrices. */
 if (!var->type->is_matrix() && 
 !(var->type->is_array() && var->type->fields.array->is_matrix()))
continue;

> - if (strcmp(var->name, "gl_ModelViewProjectionMatrixTranspose") == 0)
> -mvp_transpose = var;
> - if (strcmp(var->name, "gl_TextureMatrixTranspose") == 0)
> -texmat_transpose = var;
> + /* Must be a built-in */
> + if (strstr(var->name, "gl_") != var->name)
> +continue;

The name has to start with gl_, not just contain it.  Use
is_gl_identifier(var->name) instead.

> +
> + /* 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 {

It's probably worth adding an assertion in case a built-in is ever
added with something after Transpose.  The probability is very, very
low, but I'd rather be safe.

   assert(transpose_ptr[9] == 0);

> +entry->transpose_matrix = var;
> + }
> +
> + if (new_entry) {
> +char *entry_key;
> +if (transpose_ptr == NULL) {
> +   entry_key = strdup(var->name);
> +} else {
> +   entry_key = strndup(var->name, transpose_ptr - var->name);
> +}

hash_table_dtor doesn't free the keys, so all of this memory leaks.
Use ralloc_strndup, and only copy the name in the transpose_ptr != NULL
case.

> +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

[Mesa-dev] [PATCH v2] glsl: Expand matrix flip optimization pass to cover more cases.

2014-06-18 Thread Iago Toral Quiroga
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.
---
 src/glsl/opt_flip_matrices.cpp | 145 ++---
 1 file changed, 108 insertions(+), 37 deletions(-)

diff --git a/src/glsl/opt_flip_matrices.cpp b/src/glsl/opt_flip_matrices.cpp
index 9044fd6..d0b8125 100644
--- a/src/glsl/opt_flip_matrices.cpp
+++ b/src/glsl/opt_flip_matrices.cpp
@@ -29,44 +29,132 @@
  * 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)
+
+ /* Must be a matrix */
+ if (!var || !var->type->is_matrix())
 continue;
- if (strcmp(var->name, "gl_ModelViewProjectionMatrixTranspose") == 0)
-mvp_transpose = var;
- if (strcmp(var->name, "gl_TextureMatrixTranspose") == 0)
-texmat_transpose = var;
+ /* Must be a built-in */
+ if (strstr(var->name, "gl_") != 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 {
+entry->transpose_matrix = var;
+ }
+
+ if (new_entry) {
+char *entry_key;
+if (transpose_ptr == NULL) {
+   entry_key = strdup(var->name);
+} else {
+   entry_key = strndup(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_transpo