glsl: Accept nonconstant array references in lower_ubo_reference
authorChris Forbes <chrisf@ijw.co.nz>
Fri, 16 May 2014 10:07:24 +0000 (22:07 +1200)
committerChris Forbes <chrisf@ijw.co.nz>
Sat, 26 Jul 2014 04:46:03 +0000 (16:46 +1200)
Instead of falling back to just the block name (which we won't find),
look for the first element of the block array. We'll deal with the rest
in the backend by arranging for the blocks to be laid out contiguously.

V2: Squashed together patches 3, 5 of V1, plus a naming tweak.

Signed-off-by: Chris Forbes <chrisf@ijw.co.nz>
Reviewed-by: Ilia Mirkin <imirkin@alum.mit.edu>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/glsl/lower_ubo_reference.cpp

index 9729ea071b32a51cf3572a80a819b4c03f3d9079..67b752d3d22131d7245fd9e0dedd592abdd2bc8a 100644 (file)
@@ -69,9 +69,11 @@ public:
  * \c UniformBlocks array.
  */
 static const char *
-interface_field_name(void *mem_ctx, char *base_name, ir_dereference *d)
+interface_field_name(void *mem_ctx, char *base_name, ir_dereference *d,
+                     ir_rvalue **nonconst_block_index)
 {
-   ir_constant *previous_index = NULL;
+   ir_rvalue *previous_index = NULL;
+   *nonconst_block_index = NULL;
 
    while (d != NULL) {
       switch (d->ir_type) {
@@ -79,13 +81,21 @@ interface_field_name(void *mem_ctx, char *base_name, ir_dereference *d)
          ir_dereference_variable *v = (ir_dereference_variable *) d;
          if (previous_index
              && v->var->is_interface_instance()
-             && v->var->type->is_array())
-            return ralloc_asprintf(mem_ctx,
-                                   "%s[%d]",
-                                   base_name,
-                                   previous_index->get_uint_component(0));
-         else
+             && v->var->type->is_array()) {
+
+            ir_constant *const_index = previous_index->as_constant();
+            if (!const_index) {
+               *nonconst_block_index = previous_index;
+               return ralloc_asprintf(mem_ctx, "%s[0]", base_name);
+            } else {
+               return ralloc_asprintf(mem_ctx,
+                                      "%s[%d]",
+                                      base_name,
+                                      const_index->get_uint_component(0));
+            }
+         } else {
             return base_name;
+         }
 
          break;
       }
@@ -101,7 +111,8 @@ interface_field_name(void *mem_ctx, char *base_name, ir_dereference *d)
          ir_dereference_array *a = (ir_dereference_array *) d;
 
          d = a->array->as_dereference();
-         previous_index = a->array_index->as_constant();
+         previous_index = a->array_index;
+
          break;
       }
 
@@ -131,14 +142,24 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue)
 
    mem_ctx = ralloc_parent(*rvalue);
 
+   ir_rvalue *nonconst_block_index;
    const char *const field_name =
       interface_field_name(mem_ctx, (char *) var->get_interface_type()->name,
-                           deref);
+                           deref, &nonconst_block_index);
 
    this->uniform_block = NULL;
    for (unsigned i = 0; i < shader->NumUniformBlocks; i++) {
       if (strcmp(field_name, shader->UniformBlocks[i].Name) == 0) {
-         this->uniform_block = new(mem_ctx) ir_constant(i);
+
+         ir_constant *index = new(mem_ctx) ir_constant(i);
+
+         if (nonconst_block_index) {
+            if (nonconst_block_index->type != glsl_type::uint_type)
+               nonconst_block_index = i2u(nonconst_block_index);
+            this->uniform_block = add(nonconst_block_index, index);
+         } else {
+            this->uniform_block = index;
+         }
 
          struct gl_uniform_block *block = &shader->UniformBlocks[i];