summaryrefslogtreecommitdiffstats
path: root/src/glsl
diff options
context:
space:
mode:
authorAbdiel Janulgue <[email protected]>2014-07-08 14:12:50 +0300
committerAbdiel Janulgue <[email protected]>2014-08-31 21:04:08 +0300
commit0e2ba3ee827f77af0b1f322d95c650f6f7f4da88 (patch)
tree67aa3010ed58583f981dfa9ab712b57cb9e4aac3 /src/glsl
parentd92394c5d88c77f7ff9676b6ade935f922e377a4 (diff)
glsl: Optimize clamp(x, b, 1.0), where b > 0.0 as max(saturate(x),b)
v2: - Output max(saturate(x),b) instead of saturate(max(x,b)) - Make sure we do component-wise comparison for vectors (Ian Romanick) v3: - Add missing condition where the outer constant value is > 0.0 and inner constant is 1.0. - Fix comments to show that the optimization is a commutative operation (Matt Turner) Reviewed-by: Ian Romanick <[email protected]> Signed-off-by: Abdiel Janulgue <[email protected]>
Diffstat (limited to 'src/glsl')
-rw-r--r--src/glsl/opt_algebraic.cpp23
1 files changed, 23 insertions, 0 deletions
diff --git a/src/glsl/opt_algebraic.cpp b/src/glsl/opt_algebraic.cpp
index 6dfb6819820..447618f9ef9 100644
--- a/src/glsl/opt_algebraic.cpp
+++ b/src/glsl/opt_algebraic.cpp
@@ -137,6 +137,21 @@ is_less_than_one(ir_constant *ir)
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)
{
@@ -684,6 +699,14 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
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);
}
}