From 4dfb89904c0a3d2166e9a3fc0253a254680e91bc Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Wed, 8 Sep 2010 01:31:39 +0200 Subject: [PATCH] glsl: introduce ir_binop_all_equal and ir_binop_any_equal, allow vector cmps 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. Signed-off-by: Ian Romanick --- src/glsl/ast_to_hir.cpp | 4 +-- src/glsl/ir.cpp | 5 ++++ 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 | 8 +++--- src/glsl/ir_validate.cpp | 26 ++++++++++++-------- src/mesa/program/ir_to_mesa.cpp | 8 +++++- 8 files changed, 74 insertions(+), 23 deletions(-) diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index 3de6caac701..31bb40dd138 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 b0945431ada..86dc4901543 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -210,6 +210,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 */ @@ -275,6 +277,8 @@ static const char *const operator_strs[] = { ">=", "==", "!=", + "all_equal", + "any_nequal", "<<", ">>", "&", @@ -293,6 +297,7 @@ static const char *const operator_strs[] = { const char *ir_expression::operator_string(ir_expression_operation op) { assert((unsigned int) op < Elements(operator_strs)); + assert(Elements(operator_strs) == (ir_binop_pow + 1)); return operator_strs[op]; } diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 80a647e0dc2..70c6faaf156 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -675,16 +675,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 ff81563f196..2ed66db4765 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 ca12392a74f..ec0e26de185 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 da6de9492b0..c32ca88b0fe 100644 --- a/src/glsl/ir_mat_op_to_vec.cpp +++ b/src/glsl/ir_mat_op_to_vec.cpp @@ -307,7 +307,7 @@ ir_mat_op_to_vec_visitor::do_equal_mat_mat(ir_variable *result_var, ir_dereference *const op1 = get_column(b_var, i); ir_expression *const cmp = - new(this->mem_ctx) ir_expression(ir_binop_nequal, + new(this->mem_ctx) ir_expression(ir_binop_any_nequal, glsl_type::bool_type, op0, op1); ir_rvalue *const swiz = @@ -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 445169f5202..1c50957d13b 100644 --- a/src/glsl/ir_validate.cpp +++ b/src/glsl/ir_validate.cpp @@ -293,24 +293,30 @@ ir_validate::visit_leave(ir_expression *ir) assert(ir->operands[0]->type == ir->type); } break; + case ir_binop_less: case ir_binop_greater: case ir_binop_lequal: case ir_binop_gequal: - /* 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. + case ir_binop_equal: + case ir_binop_nequal: + /* The semantics of the IR operators differ from the GLSL <, >, <=, >=, + * ==, and != operators. The IR operators perform a component-wise + * comparison on scalar or vector types and return a boolean scalar or + * vector type of the same size. */ - 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->operands[0]->type->is_vector() + || ir->operands[0]->type->is_scalar()); + assert(ir->operands[0]->type->vector_elements + == ir->type->vector_elements); break; - case ir_binop_equal: - case ir_binop_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. + case ir_binop_all_equal: + case ir_binop_any_nequal: + /* GLSL == and != operate on scalars, vectors, matrices and arrays, and + * return a scalar boolean. The IR matches that. */ assert(ir->type == glsl_type::bool_type); assert(ir->operands[0]->type == ir->operands[1]->type); diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 6d67da495d2..2edf01bb8f7 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -1193,6 +1193,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()) { @@ -1206,7 +1212,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()) { -- 2.30.2