glsl: Propagate explicit binding information from the AST all the way to the linker
authorIan Romanick <ian.d.romanick@intel.com>
Thu, 3 Apr 2014 01:58:54 +0000 (18:58 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Fri, 11 Apr 2014 19:26:01 +0000 (12:26 -0700)
Information about the binding was not being properly communicated from
the front-end compiler to the linker.  As a result, the linker never
knew that any UBOs had explicit bindings!

Fixes the piglit test arb_shading_language_420pack-binding-layout.

Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=76323
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Tested-by: github@socker.lepus.uberspace.de [v0]
Cc: "10.1" <mesa-stable@lists.freedesktop.org>
Cc: github@socker.lepus.uberspace.de
src/glsl/ast_to_hir.cpp
src/glsl/link_uniform_block_active_visitor.cpp
src/glsl/link_uniform_block_active_visitor.h
src/glsl/link_uniform_blocks.cpp

index 8d55ee317135736586afd69cc5c7fbbdcab9c7bf..1d15e6213e73c0a03e4f27543c0c6f970ae0d7fe 100644 (file)
@@ -5316,6 +5316,13 @@ ast_interface_block::hir(exec_list *instructions,
          earlier->reinit_interface_type(block_type);
          delete var;
       } else {
+         /* Propagate the "binding" keyword into this UBO's fields;
+          * the UBO declaration itself doesn't get an ir_variable unless it
+          * has an instance name.  This is ugly.
+          */
+         var->data.explicit_binding = this->layout.flags.q.explicit_binding;
+         var->data.binding = this->layout.binding;
+
          state->symbols->add_variable(var);
          instructions->push_tail(var);
       }
index f2f46a211308916b920ce0191eae52a7b6d41ba2..d19ce20c7826b8ca97d1915ca302da99caac4ff6 100644 (file)
@@ -46,6 +46,14 @@ process_block(void *mem_ctx, struct hash_table *ht, ir_variable *var)
       b->type = block_type;
       b->has_instance_name = var->is_interface_instance();
 
+      if (var->data.explicit_binding) {
+         b->has_binding = true;
+         b->binding = var->data.binding;
+      } else {
+         b->has_binding = false;
+         b->binding = 0;
+      }
+
       _mesa_hash_table_insert(ht, h, var->get_interface_type()->name,
                              (void *) b);
       return b;
index fba628a8f44342d160a5e5c55a9024b9f3442aa5..d76dbcaf12b82555fa1c6a5d08fc6c3f74bd6e9e 100644 (file)
@@ -36,7 +36,10 @@ struct link_uniform_block_active {
    unsigned *array_elements;
    unsigned num_array_elements;
 
+   unsigned binding;
+
    bool has_instance_name;
+   bool has_binding;
 };
 
 class link_uniform_block_active_visitor : public ir_hierarchical_visitor {
index 72d6c5323a6ebe90a4117bf4e8ac56eaa88d4df6..1a0e6431805e9c26a13992cc10e25f21be2c6039 100644 (file)
@@ -251,7 +251,17 @@ link_uniform_blocks(void *mem_ctx,
             blocks[i].Name = ralloc_asprintf(blocks, "%s[%u]", name,
                                              b->array_elements[j]);
             blocks[i].Uniforms = &variables[parcel.index];
-            blocks[i].Binding = 0;
+
+            /* The GL_ARB_shading_language_420pack spec says:
+             *
+             *     "If the binding identifier is used with a uniform block
+             *     instanced as an array then the first element of the array
+             *     takes the specified block binding and each subsequent
+             *     element takes the next consecutive uniform block binding
+             *     point."
+             */
+            blocks[i].Binding = (b->has_binding) ? b->binding + j : 0;
+
             blocks[i].UniformBufferSize = 0;
             blocks[i]._Packing =
                gl_uniform_block_packing(block_type->interface_packing);
@@ -269,7 +279,7 @@ link_uniform_blocks(void *mem_ctx,
       } else {
          blocks[i].Name = ralloc_strdup(blocks, block_type->name);
          blocks[i].Uniforms = &variables[parcel.index];
-         blocks[i].Binding = 0;
+         blocks[i].Binding = (b->has_binding) ? b->binding : 0;
          blocks[i].UniformBufferSize = 0;
          blocks[i]._Packing =
             gl_uniform_block_packing(block_type->interface_packing);