glsl/opt_array_splitting: Fix crash when doing array indexing into other arrays
authorIago Toral Quiroga <itoral@igalia.com>
Thu, 3 Mar 2016 08:02:30 +0000 (09:02 +0100)
committerIago Toral Quiroga <itoral@igalia.com>
Thu, 3 Mar 2016 08:02:30 +0000 (09:02 +0100)
When we find indirect indexing into an array, the current implementation
of the array spliiting optimization pass does not look further into the
expression tree. However, if the variable expression involves variable
indexing into other arrays, we can miss that these other arrays also have
variable indexing. If that happens, the pass will crash later on after
hitting an assertion put there to ensure that split arrays are in fact
always indexed via constants:

shader_runner: opt_array_splitting.cpp:296:
void ir_array_splitting_visitor::split_deref(ir_dereference**): Assertion `constant' failed.

This patch fixes the problem by letting the pass step into the variable
index expression to identify these cases properly.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=89607
Reviewed-by: Timothy Arceri <timothy.arceri@collabora.com>
src/compiler/glsl/opt_array_splitting.cpp

index cceec6b6431be3412af8409d5c513022a6b10e9b..2f6afb080cc7d52e648cd964ae62da49f86d56c6 100644 (file)
@@ -185,8 +185,18 @@ ir_array_reference_visitor::visit_enter(ir_dereference_array *ir)
    /* If the access to the array has a variable index, we wouldn't
     * know which split variable this dereference should go to.
     */
-   if (entry && !ir->array_index->as_constant())
-      entry->split = false;
+   if (!ir->array_index->as_constant()) {
+      if (entry)
+         entry->split = false;
+      /* This variable indexing could come from a different array dereference
+       * that also has variable indexing, that is, something like a[b[a[b[0]]]].
+       * If we return visit_continue_with_parent here for the first appearence
+       * of a, then we can miss that b also has indirect indexing (if this is
+       * the only place in the program where such indirect indexing into b
+       * happens), so keep going.
+       */
+      return visit_continue;
+   }
 
    /* If the index is also array dereference, visit index. */
    if (ir->array_index->as_dereference_array())