Mesa (shader-work): glsl: introduce ir_binop_all_equal and ir_binop_any_equal, allow vector cmps (v2 )

Luca Barbieri lb at kemper.freedesktop.org
Thu Sep 9 18:38:09 UTC 2010


Module: Mesa
Branch: shader-work
Commit: 2fab36b79b02930cf0b7223162ed57c50e64fde9
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=2fab36b79b02930cf0b7223162ed57c50e64fde9

Author: Luca Barbieri <luca at luca-barbieri.com>
Date:   Wed Sep  8 01:31:39 2010 +0200

glsl: introduce ir_binop_all_equal and ir_binop_any_equal, allow vector cmps (v2)

Changes in v2:
- Fix buggy ir_validate logic

Currently GLSL IR forbids any vector comparisons, and defines "ir_binop_equal"
and "ir_binop_nequal" to compare all elements and give a single bool.

This is highly unintuitive and prevents generation of optimal Mesa IR.

Hence, first rename "ir_binop_equal" to "ir_binop_all_equal" and
"ir_binop_nequal" to "ir_binop_any_nequal".

Second, readd "ir_binop_equal" and "ir_binop_nequal" with the same semantics
as less, lequal, etc.

Third, allow all comparisons to acts on vectors.

---

 src/glsl/ast_to_hir.cpp             |    4 +-
 src/glsl/ir.cpp                     |    2 +
 src/glsl/ir.h                       |    6 +++-
 src/glsl/ir_algebraic.cpp           |    2 +
 src/glsl/ir_constant_expression.cpp |   38 +++++++++++++++++++++++++++++++---
 src/glsl/ir_mat_op_to_vec.cpp       |    6 ++--
 src/glsl/ir_validate.cpp            |   35 +++++++++++++++++++++-----------
 src/mesa/program/ir_to_mesa.cpp     |    8 ++++++-
 8 files changed, 77 insertions(+), 24 deletions(-)

diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index 3de6caa..31bb40d 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -636,8 +636,8 @@ ast_expression::hir(exec_list *instructions,
       ir_binop_greater,
       ir_binop_lequal,
       ir_binop_gequal,
-      ir_binop_equal,
-      ir_binop_nequal,
+      ir_binop_all_equal,
+      ir_binop_any_nequal,
       ir_binop_bit_and,
       ir_binop_bit_xor,
       ir_binop_bit_or,
diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp
index 9ac2485..5d58e1b 100644
--- a/src/glsl/ir.cpp
+++ b/src/glsl/ir.cpp
@@ -208,6 +208,8 @@ ir_expression::get_num_operands(ir_expression_operation op)
       2, /* ir_binop_gequal */
       2, /* ir_binop_equal */
       2, /* ir_binop_nequal */
+      2, /* ir_binop_all_equal */
+      2, /* ir_binop_any_nequal */
 
       2, /* ir_binop_lshift */
       2, /* ir_binop_rshift */
diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index 0d93302..caa5c10 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -673,16 +673,18 @@ enum ir_expression_operation {
    ir_binop_greater,
    ir_binop_lequal,
    ir_binop_gequal,
+   ir_binop_equal,
+   ir_binop_nequal,
    /**
     * Returns single boolean for whether all components of operands[0]
     * equal the components of operands[1].
     */
-   ir_binop_equal,
+   ir_binop_all_equal,
    /**
     * Returns single boolean for whether any component of operands[0]
     * is not equal to the corresponding component of operands[1].
     */
-   ir_binop_nequal,
+   ir_binop_any_nequal,
    /*@}*/
 
    /**
diff --git a/src/glsl/ir_algebraic.cpp b/src/glsl/ir_algebraic.cpp
index ff81563..2ed66db 100644
--- a/src/glsl/ir_algebraic.cpp
+++ b/src/glsl/ir_algebraic.cpp
@@ -270,6 +270,8 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
       case ir_binop_gequal:  new_op = ir_binop_less;    break;
       case ir_binop_equal:   new_op = ir_binop_nequal;  break;
       case ir_binop_nequal:  new_op = ir_binop_equal;   break;
+      case ir_binop_all_equal:   new_op = ir_binop_any_nequal;  break;
+      case ir_binop_any_nequal:  new_op = ir_binop_all_equal;   break;
 
       default:
 	 /* The default case handler is here to silence a warning from GCC.
diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp
index ca12392..ec0e26d 100644
--- a/src/glsl/ir_constant_expression.cpp
+++ b/src/glsl/ir_constant_expression.cpp
@@ -89,9 +89,9 @@ ir_expression::constant_expression_value()
    if (op[0]->type->is_array()) {
       assert(op[1] != NULL && op[1]->type->is_array());
       switch (this->operation) {
-      case ir_binop_equal:
+      case ir_binop_all_equal:
 	 return new(ctx) ir_constant(op[0]->has_value(op[1]));
-      case ir_binop_nequal:
+      case ir_binop_any_nequal:
 	 return new(ctx) ir_constant(!op[0]->has_value(op[1]));
       default:
 	 break;
@@ -622,11 +622,41 @@ ir_expression::constant_expression_value()
 	 assert(0);
       }
       break;
-
    case ir_binop_equal:
-      data.b[0] = op[0]->has_value(op[1]);
+      switch (op[0]->type->base_type) {
+      case GLSL_TYPE_UINT:
+         data.b[0] = op[0]->value.u[0] == op[1]->value.u[0];
+         break;
+      case GLSL_TYPE_INT:
+         data.b[0] = op[0]->value.i[0] == op[1]->value.i[0];
+         break;
+      case GLSL_TYPE_FLOAT:
+         data.b[0] = op[0]->value.f[0] == op[1]->value.f[0];
+         break;
+      default:
+         assert(0);
+      }
       break;
    case ir_binop_nequal:
+      switch (op[0]->type->base_type) {
+      case GLSL_TYPE_UINT:
+         data.b[0] = op[0]->value.u[0] != op[1]->value.u[0];
+         break;
+      case GLSL_TYPE_INT:
+         data.b[0] = op[0]->value.i[0] != op[1]->value.i[0];
+         break;
+      case GLSL_TYPE_FLOAT:
+         data.b[0] = op[0]->value.f[0] != op[1]->value.f[0];
+         break;
+      default:
+         assert(0);
+      }
+      break;
+
+   case ir_binop_all_equal:
+      data.b[0] = op[0]->has_value(op[1]);
+      break;
+   case ir_binop_any_nequal:
       data.b[0] = !op[0]->has_value(op[1]);
       break;
 
diff --git a/src/glsl/ir_mat_op_to_vec.cpp b/src/glsl/ir_mat_op_to_vec.cpp
index da6de94..2b5402a 100644
--- a/src/glsl/ir_mat_op_to_vec.cpp
+++ b/src/glsl/ir_mat_op_to_vec.cpp
@@ -473,10 +473,10 @@ ir_mat_op_to_vec_visitor::visit_leave(ir_assignment *orig_assign)
       }
       break;
 
-   case ir_binop_equal:
-   case ir_binop_nequal:
+   case ir_binop_all_equal:
+   case ir_binop_any_nequal:
       do_equal_mat_mat(result_var, op_var[1], op_var[0],
-		       (orig_expr->operation == ir_binop_equal));
+		       (orig_expr->operation == ir_binop_all_equal));
       break;
 
    default:
diff --git a/src/glsl/ir_validate.cpp b/src/glsl/ir_validate.cpp
index 445169f..c4c50a7 100644
--- a/src/glsl/ir_validate.cpp
+++ b/src/glsl/ir_validate.cpp
@@ -284,36 +284,47 @@ ir_validate::visit_leave(ir_expression *ir)
    case ir_binop_max:
    case ir_binop_pow:
       if (ir->operands[0]->type->is_scalar())
-	 assert(ir->operands[1]->type == ir->type);
+        assert(ir->operands[1]->type == ir->type);
       else if (ir->operands[1]->type->is_scalar())
-	 assert(ir->operands[0]->type == ir->type);
+        assert(ir->operands[0]->type == ir->type);
       else if (ir->operands[0]->type->is_vector() &&
-	       ir->operands[1]->type->is_vector()) {
-	 assert(ir->operands[0]->type == ir->operands[1]->type);
-	 assert(ir->operands[0]->type == ir->type);
+              ir->operands[1]->type->is_vector()) {
+        assert(ir->operands[0]->type == ir->operands[1]->type);
+        assert(ir->operands[0]->type == ir->type);
       }
       break;
+
    case ir_binop_less:
    case ir_binop_greater:
    case ir_binop_lequal:
    case ir_binop_gequal:
+   case ir_binop_equal:
+   case ir_binop_nequal:
       /* GLSL < > <= >= operators take scalar floats/ints, but in the
-       * IR we may want to do them for vectors instead to support the
-       * lessEqual() and friends builtins.
+       * IR we want to do them for vectors instead to support the
+       * lessEqual() and friends builtins, and Mesa IR constructs
        */
-      assert(ir->type == glsl_type::bool_type);
-      assert(ir->operands[0]->type == ir->operands[1]->type);
+      if (ir->operands[0]->type->is_scalar())
+	 assert(ir->operands[1]->type == ir->type);
+      else if (ir->operands[1]->type->is_scalar())
+	 assert(ir->operands[0]->type == ir->type);
+      else if (ir->operands[0]->type->is_vector() &&
+	       ir->operands[1]->type->is_vector()) {
+	 assert(ir->operands[0]->type == ir->operands[1]->type);
+	 assert(ir->operands[0]->type == ir->type);
+      }
       break;
 
-   case ir_binop_equal:
-   case ir_binop_nequal:
+   case ir_binop_all_equal:
+   case ir_binop_any_nequal:
       /* GLSL == and != operate on vectors and return a bool, and the
        * IR matches that.  We may want to switch up the IR to work on
        * vectors and return a bvec and make the operators break down
        * to ANDing/ORing the results of the vector comparison.
        */
-      assert(ir->type == glsl_type::bool_type);
+      assert(ir->type->base_type == GLSL_TYPE_BOOL);
       assert(ir->operands[0]->type == ir->operands[1]->type);
+      assert(ir->type->components() == ir->operands[0]->type->components());
       break;
 
    case ir_binop_lshift:
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index 009301e..aeeb545 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -1183,6 +1183,12 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
       ir_to_mesa_emit_op2(ir, OPCODE_SGE, result_dst, op[0], op[1]);
       break;
    case ir_binop_equal:
+      ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst, op[0], op[1]);
+      break;
+   case ir_binop_nequal:
+      ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, op[0], op[1]);
+      break;
+   case ir_binop_all_equal:
       /* "==" operator producing a scalar boolean. */
       if (ir->operands[0]->type->is_vector() ||
 	  ir->operands[1]->type->is_vector()) {
@@ -1196,7 +1202,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
 	 ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst, op[0], op[1]);
       }
       break;
-   case ir_binop_nequal:
+   case ir_binop_any_nequal:
       /* "!=" operator producing a scalar boolean. */
       if (ir->operands[0]->type->is_vector() ||
 	  ir->operands[1]->type->is_vector()) {




More information about the mesa-commit mailing list