Mesa (7.9): glsl: Fix structure and array comparisions.

Ian Romanick idr at kemper.freedesktop.org
Fri Dec 17 02:21:28 UTC 2010


Module: Mesa
Branch: 7.9
Commit: 1e88b3461a80b96c2c1be6cb22edd5b67c76d205
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=1e88b3461a80b96c2c1be6cb22edd5b67c76d205

Author: Eric Anholt <eric at anholt.net>
Date:   Tue Nov 30 11:23:28 2010 -0800

glsl: Fix structure and array comparisions.

We were trying to emit a single ir_expression to compare the whole
thing.  The backends (ir_to_mesa.cpp and brw_fs.cpp so far) expected
ir_binop_any_nequal or ir_binop_all_equal to apply to at most a vector
(with matrices broken down by the lowering pass).  Break them down to
a bunch of ORed or ANDed any_nequals/all_equals.

Fixes:
glsl-array-compare
glsl-array-compare-02
glsl-fs-struct-equal
glsl-fs-struct-notequal
Bug #31909
(cherry picked from commit ff79633d9f930e396933a0ad9564824ec73ea4dc)

---

 src/glsl/ast_to_hir.cpp |   72 +++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 70 insertions(+), 2 deletions(-)

diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index 58d9696..42d5f18 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -615,6 +615,75 @@ ast_node::hir(exec_list *instructions,
    return NULL;
 }
 
+static ir_rvalue *
+do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1)
+{
+   int join_op;
+
+   if (operation == ir_binop_all_equal)
+      join_op = ir_binop_logic_and;
+   else
+      join_op = ir_binop_logic_or;
+
+   switch (op0->type->base_type) {
+   case GLSL_TYPE_FLOAT:
+   case GLSL_TYPE_UINT:
+   case GLSL_TYPE_INT:
+   case GLSL_TYPE_BOOL:
+      return new(mem_ctx) ir_expression(operation, op0, op1);
+
+   case GLSL_TYPE_ARRAY: {
+      ir_rvalue *last = NULL;
+
+      for (unsigned int i = 0; i < op0->type->length; i++) {
+	 ir_rvalue *e0, *e1, *result;
+
+	 e0 = new(mem_ctx) ir_dereference_array(op0->clone(mem_ctx, NULL),
+						new(mem_ctx) ir_constant(i));
+	 e1 = new(mem_ctx) ir_dereference_array(op1->clone(mem_ctx, NULL),
+						new(mem_ctx) ir_constant(i));
+	 result = do_comparison(mem_ctx, operation, e0, e1);
+
+	 if (last) {
+	    last = new(mem_ctx) ir_expression(join_op, last, result);
+	 } else {
+	    last = result;
+	 }
+      }
+      return last;
+   }
+
+   case GLSL_TYPE_STRUCT: {
+      ir_rvalue *last = NULL;
+
+      for (unsigned int i = 0; i < op0->type->length; i++) {
+	 ir_rvalue *e0, *e1, *result;
+	 const char *field_name = op0->type->fields.structure[i].name;
+
+	 e0 = new(mem_ctx) ir_dereference_record(op0->clone(mem_ctx, NULL),
+						 field_name);
+	 e1 = new(mem_ctx) ir_dereference_record(op1->clone(mem_ctx, NULL),
+						 field_name);
+	 result = do_comparison(mem_ctx, operation, e0, e1);
+
+	 if (last) {
+	    last = new(mem_ctx) ir_expression(join_op, last, result);
+	 } else {
+	    last = result;
+	 }
+      }
+      return last;
+   }
+
+   case GLSL_TYPE_ERROR:
+   case GLSL_TYPE_VOID:
+   case GLSL_TYPE_SAMPLER:
+      /* I assume a comparison of a struct containing a sampler just
+       * ignores the sampler present in the type.
+       */
+      return new(mem_ctx) ir_constant(true);
+   }
+}
 
 ir_rvalue *
 ast_expression::hir(exec_list *instructions,
@@ -800,8 +869,7 @@ ast_expression::hir(exec_list *instructions,
 	 error_emitted = true;
       }
 
-      result = new(ctx) ir_expression(operations[this->oper], glsl_type::bool_type,
-				      op[0], op[1]);
+      result = do_comparison(ctx, operations[this->oper], op[0], op[1]);
       type = glsl_type::bool_type;
 
       assert(result->type == glsl_type::bool_type);




More information about the mesa-commit mailing list