summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElie Tournier <tournier.elie@gmail.com>2017-08-18 17:03:39 +0100
committerDave Airlie <airlied@redhat.com>2018-01-18 14:16:27 +1000
commita82c344bb1b35ee981358d321b11429d85851e40 (patch)
tree15d53436a54ea7ca89a03020989cc33864e2872e
parent34657902a55ee4cb6137404dc6f1fb56a14e115d (diff)
glsl: Add a lowering pass for 64-bit float ceil()
Signed-off-by: Elie Tournier <elie.tournier@collabora.com>
-rw-r--r--src/compiler/glsl/lower_instructions.cpp31
1 files changed, 29 insertions, 2 deletions
diff --git a/src/compiler/glsl/lower_instructions.cpp b/src/compiler/glsl/lower_instructions.cpp
index 9ff80a502f0..266bfc9911e 100644
--- a/src/compiler/glsl/lower_instructions.cpp
+++ b/src/compiler/glsl/lower_instructions.cpp
@@ -180,6 +180,7 @@ private:
void min_to_less(ir_expression *ir);
void max_to_less(ir_expression *ir);
void dfloor_to_dtrunc(ir_expression *ir);
+ void dceil_to_dtrunc(ir_expression *ir);
ir_expression *_carry(operand a, operand b);
};
@@ -1728,6 +1729,27 @@ lower_instructions_visitor::dfloor_to_dtrunc(ir_expression *ir)
this->progress = true;
}
+void
+lower_instructions_visitor::dceil_to_dtrunc(ir_expression *ir)
+{
+ /* if x < 0, ceil(x) = trunc(x)
+ * else if (x - trunc(x) == 0), ceil(x) = x
+ * else, ceil(x) = trunc(x) + 1
+ */
+
+ ir_rvalue *src = ir->operands[0]->clone(ir, NULL);
+ ir_rvalue *tr = trunc(src);
+
+ ir->operation = ir_triop_csel;
+ ir->init_num_operands();
+ ir->operands[0] = logic_or(less(src, new(ir) ir_constant(0.0, 1)),
+ equal(src, tr));
+ ir->operands[1] = tr;
+ ir->operands[2] = add(tr, new(ir) ir_constant(1.0, 1));
+
+ this->progress = true;
+}
+
ir_visitor_status
lower_instructions_visitor::visit_leave(ir_expression *ir)
{
@@ -1811,8 +1833,13 @@ lower_instructions_visitor::visit_leave(ir_expression *ir)
break;
case ir_unop_ceil:
- if (lowering(DOPS_TO_DFRAC) && ir->type->is_double())
- dceil_to_dfrac(ir);
+ if (ir->type->is_double()) {
+ if (lowering(DOPS_TO_DFRAC)) {
+ dceil_to_dfrac(ir);
+ } else if (lowering(DOPS_TO_DTRUNC) && ir->type->is_scalar()) {
+ dceil_to_dtrunc(ir);
+ }
+ }
break;
case ir_unop_floor: