mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-27 04:00:10 +01:00
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
This commit is contained in:
parent
6b937465d4
commit
ff79633d9f
1 changed files with 70 additions and 2 deletions
|
|
@ -745,6 +745,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,
|
||||
|
|
@ -941,8 +1010,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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue