glsl: fix conversions from uint to bool and from float/bool to uint
[mesa.git] / src / glsl / lower_if_to_cond_assign.cpp
index cf48cfb8d611f92a786e64d17581415693824c4f..e3a1065d9963e5026df7af2745c33450f87f4e71 100644 (file)
 /**
  * \file lower_if_to_cond_assign.cpp
  *
- * This attempts to flatten all if statements to conditional
- * assignments for GPUs that don't do control flow.
+ * This attempts to flatten if-statements to conditional assignments for
+ * GPUs with limited or no flow control support.
  *
  * It can't handle other control flow being inside of its block, such
  * as calls or loops.  Hopefully loop unrolling and inlining will take
  * care of those.
+ *
+ * Drivers for GPUs with no control flow support should simply call
+ *
+ *    lower_if_to_cond_assign(instructions)
+ *
+ * to attempt to flatten all if-statements.
+ *
+ * Some GPUs (such as i965 prior to gen6) do support control flow, but have a
+ * maximum nesting depth N.  Drivers for such hardware can call
+ *
+ *    lower_if_to_cond_assign(instructions, N)
+ *
+ * to attempt to flatten any if-statements appearing at depth > N.
  */
 
 #include "glsl_types.h"
 
 class ir_if_to_cond_assign_visitor : public ir_hierarchical_visitor {
 public:
-   ir_if_to_cond_assign_visitor()
+   ir_if_to_cond_assign_visitor(unsigned max_depth)
    {
       this->progress = false;
+      this->max_depth = max_depth;
+      this->depth = 0;
    }
 
+   ir_visitor_status visit_enter(ir_if *);
    ir_visitor_status visit_leave(ir_if *);
 
    bool progress;
+   unsigned max_depth;
+   unsigned depth;
 };
 
 bool
-do_if_to_cond_assign(exec_list *instructions)
+lower_if_to_cond_assign(exec_list *instructions, unsigned max_depth)
 {
-   ir_if_to_cond_assign_visitor v;
+   ir_if_to_cond_assign_visitor v(max_depth);
 
    visit_list_elements(&v, instructions);
 
@@ -119,9 +137,23 @@ move_block_to_cond_assign(void *mem_ctx,
    }
 }
 
+ir_visitor_status
+ir_if_to_cond_assign_visitor::visit_enter(ir_if *ir)
+{
+   (void) ir;
+   this->depth++;
+   return visit_continue;
+}
+
 ir_visitor_status
 ir_if_to_cond_assign_visitor::visit_leave(ir_if *ir)
 {
+   /* Only flatten when beyond the GPU's maximum supported nesting depth. */
+   if (this->depth <= this->max_depth)
+      return visit_continue;
+
+   this->depth--;
+
    bool found_control_flow = false;
    ir_variable *cond_var;
    ir_assignment *assign;
@@ -139,7 +171,7 @@ ir_if_to_cond_assign_visitor::visit_leave(ir_if *ir)
    if (found_control_flow)
       return visit_continue;
 
-   void *mem_ctx = talloc_parent(ir);
+   void *mem_ctx = ralloc_parent(ir);
 
    /* Store the condition to a variable so the assignment conditions are
     * simpler.