Hi,

I am trying to make the shaders from a sky scattering shader work with mesa.
One of the problems is that the shader contains a nested 16 x 32 loop with an 
instruction intensive body. The glsl loop unrolling pass is trying to unroll 
both loops since both of them have a fixed size <=32. Compiling this shader 
gets stuck in do_common_optimization (= takes more than 10 minutes) since 
unrolling and then optimizing that huge 16*32*(function body) intruction count 
kills the runtime behavour of other optimization passes.

Attached is a change that additionally skips loop unrolling if either the loop 
is a nested loop or the instruction count of the body times the constant 
iteration count exceeds the former max iteration count times 5 instructions.
This makes the above shaders at least compile within the usual fraction of a 
second.

Comments/Review?

Thanks

Mathias
>From d6a2a0ac66b8594c258468fc5f42b0dae720e632 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mathias=20Fr=C3=B6hlich?= <mathias.froehl...@gmx.net>
Date: Wed, 25 Jan 2012 17:35:01 +0100
Subject: [PATCH] glsl: Avoid excessive loop unrolling.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Avoid unrollong loops that are either nested loops or
where the loop body times the unroll count is huge.

The change is far from being perfect but it extends the
loop unrolling decision heuristic by some additional
safeguard. In particular this cuts down compilation of
a shader precomputing atmospheric scattering integral
tables containing two nesting levels in a loop from
something way beyond some minutes (I never waited for
it to finish) to some fractions of a second.

Signed-off-by: Mathias Fröhlich <mathias.froehl...@web.de>
---
 src/glsl/loop_unroll.cpp |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/src/glsl/loop_unroll.cpp b/src/glsl/loop_unroll.cpp
index 5b84e10..d0bcaa6 100644
--- a/src/glsl/loop_unroll.cpp
+++ b/src/glsl/loop_unroll.cpp
@@ -56,6 +56,7 @@ loop_unroll_visitor::visit_leave(ir_loop *ir)
 {
    loop_variable_state *const ls = this->state->get(ir);
    int iterations;
+   unsigned ir_count;
 
    /* If we've entered a loop that hasn't been analyzed, something really,
     * really bad has happened.
@@ -78,6 +79,20 @@ loop_unroll_visitor::visit_leave(ir_loop *ir)
    if (iterations > (int) max_iterations)
       return visit_continue;
 
+   /* Don't try to unroll nested loops and loops with a huge body.
+    */
+   ir_count = 0;
+   foreach_list(node, &ir->body_instructions) {
+      ++ir_count;
+
+      /* If the loop body gets to huge, do not unroll. */
+      if (5*max_iterations < ir_count*iterations)
+          return visit_continue;
+      /* Do not unroll loops with child loop nodes. */
+      if (((ir_instruction *) node)->as_loop())
+          return visit_continue;
+   }
+
    if (ls->num_loop_jumps > 1)
       return visit_continue;
    else if (ls->num_loop_jumps) {
-- 
1.7.7.6

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to