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 <ian.d.romanick@intel.com>
This commit is contained in:

committed by
Ian Romanick

parent
2cdbced10d
commit
4dfb89904c
@@ -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,
|
||||
|
@@ -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];
|
||||
}
|
||||
|
||||
|
@@ -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,
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
|
@@ -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.
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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:
|
||||
|
@@ -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.
|
||||
*/
|
||||
assert(ir->type == glsl_type::bool_type);
|
||||
assert(ir->operands[0]->type == ir->operands[1]->type);
|
||||
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.
|
||||
/* 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->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_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);
|
||||
|
@@ -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()) {
|
||||
|
Reference in New Issue
Block a user