diff options
Diffstat (limited to 'src/glsl/ast_to_hir.cpp')
-rw-r--r-- | 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 fd9ed556806..0978100acd9 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -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); |