diff options
Diffstat (limited to 'mesalib/src/glsl')
-rwxr-xr-x | mesalib/src/glsl/ir.cpp | 2 | ||||
-rw-r--r-- | mesalib/src/glsl/ir.h | 1 | ||||
-rw-r--r-- | mesalib/src/glsl/ir_builder.cpp | 6 | ||||
-rwxr-xr-x | mesalib/src/glsl/ir_constant_expression.cpp | 6 | ||||
-rw-r--r-- | mesalib/src/glsl/ir_optimization.h | 1 | ||||
-rw-r--r-- | mesalib/src/glsl/ir_validate.cpp | 1 | ||||
-rw-r--r-- | mesalib/src/glsl/linker.cpp | 4 | ||||
-rw-r--r-- | mesalib/src/glsl/lower_instructions.cpp | 29 | ||||
-rw-r--r-- | mesalib/src/glsl/opt_algebraic.cpp | 98 |
9 files changed, 142 insertions, 6 deletions
diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp index c2bfda938..4229a2bf4 100755 --- a/mesalib/src/glsl/ir.cpp +++ b/mesalib/src/glsl/ir.cpp @@ -255,6 +255,7 @@ ir_expression::ir_expression(int op, ir_rvalue *op0) case ir_unop_dFdy_fine: case ir_unop_bitfield_reverse: case ir_unop_interpolate_at_centroid: + case ir_unop_saturate: this->type = op0->type; break; @@ -534,6 +535,7 @@ static const char *const operator_strs[] = { "bit_count", "find_msb", "find_lsb", + "sat", "noise", "interpolate_at_centroid", "+", diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h index e9051732b..8003f88ce 100644 --- a/mesalib/src/glsl/ir.h +++ b/mesalib/src/glsl/ir.h @@ -1250,6 +1250,7 @@ enum ir_expression_operation { ir_unop_find_lsb, /*@}*/ + ir_unop_saturate, ir_unop_noise, /** diff --git a/mesalib/src/glsl/ir_builder.cpp b/mesalib/src/glsl/ir_builder.cpp index f03941443..a2f6f2967 100644 --- a/mesalib/src/glsl/ir_builder.cpp +++ b/mesalib/src/glsl/ir_builder.cpp @@ -271,11 +271,7 @@ clamp(operand a, operand b, operand c) ir_expression * saturate(operand a) { - void *mem_ctx = ralloc_parent(a.val); - - return expr(ir_binop_max, - expr(ir_binop_min, a, new(mem_ctx) ir_constant(1.0f)), - new(mem_ctx) ir_constant(0.0f)); + return expr(ir_unop_saturate, a); } ir_expression * diff --git a/mesalib/src/glsl/ir_constant_expression.cpp b/mesalib/src/glsl/ir_constant_expression.cpp index eff2bc173..4593a13d1 100755 --- a/mesalib/src/glsl/ir_constant_expression.cpp +++ b/mesalib/src/glsl/ir_constant_expression.cpp @@ -1462,6 +1462,12 @@ ir_expression::constant_expression_value(struct hash_table *variable_context) } break; + case ir_unop_saturate: + for (unsigned c = 0; c < components; c++) { + data.f[c] = CLAMP(op[0]->value.f[c], 0.0f, 1.0f); + } + break; + case ir_triop_bitfield_extract: { int offset = op[1]->value.i[0]; int bits = op[2]->value.i[0]; diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h index b83c22592..1c6f72b54 100644 --- a/mesalib/src/glsl/ir_optimization.h +++ b/mesalib/src/glsl/ir_optimization.h @@ -40,6 +40,7 @@ #define LDEXP_TO_ARITH 0x100 #define CARRY_TO_ARITH 0x200 #define BORROW_TO_ARITH 0x400 +#define SAT_TO_CLAMP 0x800 /** * \see class lower_packing_builtins_visitor diff --git a/mesalib/src/glsl/ir_validate.cpp b/mesalib/src/glsl/ir_validate.cpp index 5b2067782..97a581dc2 100644 --- a/mesalib/src/glsl/ir_validate.cpp +++ b/mesalib/src/glsl/ir_validate.cpp @@ -241,6 +241,7 @@ ir_validate::visit_leave(ir_expression *ir) case ir_unop_log: case ir_unop_exp2: case ir_unop_log2: + case ir_unop_saturate: assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); assert(ir->type == ir->operands[0]->type); break; diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index d5473adc3..57be4931d 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -2439,8 +2439,10 @@ check_explicit_uniform_locations(struct gl_context *ctx, ir_variable *var = node->as_variable(); if ((var && var->data.mode == ir_var_uniform) && var->data.explicit_location) { - if (!reserve_explicit_locations(prog, uniform_map, var)) + if (!reserve_explicit_locations(prog, uniform_map, var)) { + delete uniform_map; return; + } } } } diff --git a/mesalib/src/glsl/lower_instructions.cpp b/mesalib/src/glsl/lower_instructions.cpp index 176070c87..684285350 100644 --- a/mesalib/src/glsl/lower_instructions.cpp +++ b/mesalib/src/glsl/lower_instructions.cpp @@ -41,6 +41,7 @@ * - BITFIELD_INSERT_TO_BFM_BFI * - CARRY_TO_ARITH * - BORROW_TO_ARITH + * - SAT_TO_CLAMP * * SUB_TO_ADD_NEG: * --------------- @@ -104,6 +105,10 @@ * ---------------- * Converts ir_borrow into (x < y). * + * SAT_TO_CLAMP: + * ------------- + * Converts ir_unop_saturate into min(max(x, 0.0), 1.0) + * */ #include "main/core.h" /* for M_LOG2E */ @@ -139,6 +144,7 @@ private: void ldexp_to_arith(ir_expression *); void carry_to_arith(ir_expression *); void borrow_to_arith(ir_expression *); + void sat_to_clamp(ir_expression *); }; } /* anonymous namespace */ @@ -484,6 +490,24 @@ lower_instructions_visitor::borrow_to_arith(ir_expression *ir) this->progress = true; } +void +lower_instructions_visitor::sat_to_clamp(ir_expression *ir) +{ + /* Translates + * ir_unop_saturate x + * into + * ir_binop_min (ir_binop_max(x, 0.0), 1.0) + */ + + ir->operation = ir_binop_min; + ir->operands[0] = new(ir) ir_expression(ir_binop_max, ir->operands[0]->type, + ir->operands[0], + new(ir) ir_constant(0.0f)); + ir->operands[1] = new(ir) ir_constant(1.0f); + + this->progress = true; +} + ir_visitor_status lower_instructions_visitor::visit_leave(ir_expression *ir) { @@ -540,6 +564,11 @@ lower_instructions_visitor::visit_leave(ir_expression *ir) borrow_to_arith(ir); break; + case ir_unop_saturate: + if (lowering(SAT_TO_CLAMP)) + sat_to_clamp(ir); + break; + default: return visit_continue; } diff --git a/mesalib/src/glsl/opt_algebraic.cpp b/mesalib/src/glsl/opt_algebraic.cpp index ac7514acf..447618f9e 100644 --- a/mesalib/src/glsl/opt_algebraic.cpp +++ b/mesalib/src/glsl/opt_algebraic.cpp @@ -110,6 +110,48 @@ is_vec_basis(ir_constant *ir) return (ir == NULL) ? false : ir->is_basis(); } +static inline bool +is_valid_vec_const(ir_constant *ir) +{ + if (ir == NULL) + return false; + + if (!ir->type->is_scalar() && !ir->type->is_vector()) + return false; + + return true; +} + +static inline bool +is_less_than_one(ir_constant *ir) +{ + if (!is_valid_vec_const(ir)) + return false; + + unsigned component = 0; + for (int c = 0; c < ir->type->vector_elements; c++) { + if (ir->get_float_component(c) < 1.0f) + component++; + } + + return (component == ir->type->vector_elements); +} + +static inline bool +is_greater_than_zero(ir_constant *ir) +{ + if (!is_valid_vec_const(ir)) + return false; + + unsigned component = 0; + for (int c = 0; c < ir->type->vector_elements; c++) { + if (ir->get_float_component(c) > 0.0f) + component++; + } + + return (component == ir->type->vector_elements); +} + static void update_type(ir_expression *ir) { @@ -614,6 +656,62 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) break; + case ir_binop_min: + case ir_binop_max: + if (ir->type->base_type != GLSL_TYPE_FLOAT) + break; + + /* Replace min(max) operations and its commutative combinations with + * a saturate operation + */ + for (int op = 0; op < 2; op++) { + ir_expression *minmax = op_expr[op]; + ir_constant *outer_const = op_const[1 - op]; + ir_expression_operation op_cond = (ir->operation == ir_binop_max) ? + ir_binop_min : ir_binop_max; + + if (!minmax || !outer_const || (minmax->operation != op_cond)) + continue; + + /* Found a min(max) combination. Now try to see if its operands + * meet our conditions that we can do just a single saturate operation + */ + for (int minmax_op = 0; minmax_op < 2; minmax_op++) { + ir_rvalue *inner_val_a = minmax->operands[minmax_op]; + ir_rvalue *inner_val_b = minmax->operands[1 - minmax_op]; + + if (!inner_val_a || !inner_val_b) + continue; + + /* Found a {min|max} ({max|min} (x, 0.0), 1.0) operation and its variations */ + if ((outer_const->is_one() && inner_val_a->is_zero()) || + (inner_val_a->is_one() && outer_const->is_zero())) + return saturate(inner_val_b); + + /* Found a {min|max} ({max|min} (x, 0.0), b) where b < 1.0 + * and its variations + */ + if (is_less_than_one(outer_const) && inner_val_b->is_zero()) + return expr(ir_binop_min, saturate(inner_val_a), outer_const); + + if (!inner_val_b->as_constant()) + continue; + + if (is_less_than_one(inner_val_b->as_constant()) && outer_const->is_zero()) + return expr(ir_binop_min, saturate(inner_val_a), inner_val_b); + + /* Found a {min|max} ({max|min} (x, b), 1.0), where b > 0.0 + * and its variations + */ + if (outer_const->is_one() && is_greater_than_zero(inner_val_b->as_constant())) + return expr(ir_binop_max, saturate(inner_val_a), inner_val_b); + if (inner_val_b->as_constant()->is_one() && is_greater_than_zero(outer_const)) + return expr(ir_binop_max, saturate(inner_val_a), outer_const); + } + } + + break; + case ir_unop_rcp: if (op_expr[0] && op_expr[0]->operation == ir_unop_rcp) return op_expr[0]->operands[0]; |