On 03/19/2013 03:57 AM, Pohjolainen, Topi wrote:
On Mon, Mar 18, 2013 at 04:35:10PM -0700, Jordan Justen wrote:
With this change we now support interface block arrays.
For example, cases like this:

out block_name {
     float f;
} block_instance[2];

This allows Mesa to pass the piglit glsl-1.50 test:
* execution/interface-blocks-complex-vs-fs.shader_test

Signed-off-by: Jordan Justen <jordan.l.jus...@intel.com>
---
  src/glsl/lower_named_interface_blocks.cpp |   53 ++++++++++++++++++++++++-----
  1 file changed, 44 insertions(+), 9 deletions(-)

diff --git a/src/glsl/lower_named_interface_blocks.cpp 
b/src/glsl/lower_named_interface_blocks.cpp
index 2e0c322..405e7a9 100644
--- a/src/glsl/lower_named_interface_blocks.cpp
+++ b/src/glsl/lower_named_interface_blocks.cpp
@@ -107,22 +107,47 @@ 
flatten_named_interface_blocks_declarations::run(exec_list *instructions)
           if (var->mode == ir_var_uniform)
              continue;

-         const glsl_type *const t = var->type;
+         const glsl_type * iface_t = var->type;
+         const glsl_type * array_t = NULL;
           exec_node *insert_pos = var;
-         char *iface_field_name;
-         for (unsigned i = 0; i < t->length; i++) {
-            iface_field_name = ralloc_asprintf(mem_ctx, "%s.%s", t->name,
-                                               t->fields.structure[i].name);
+
+         if (iface_t->is_array()) {
+            array_t = iface_t;
+            iface_t = array_t->fields.array;
+         }
+
+         assert (iface_t->is_interface());
+
+         for (unsigned i = 0; i < iface_t->length; i++) {
+            const char * field_name = iface_t->fields.structure[i].name;
+            char *iface_field_name =
+               ralloc_asprintf(mem_ctx, "%s.%s",
+                               iface_t->name, field_name);

              ir_variable *found_var =
                 (ir_variable *) hash_table_find(interface_namespace,
                                                 iface_field_name);
              if (!found_var) {
                 ir_variable *new_var =
-                  new(mem_ctx) ir_variable(t->fields.structure[i].type,
-                                           ralloc_strdup(mem_ctx, 
t->fields.structure[i].name),
+                  new(mem_ctx) ir_variable(iface_t->fields.structure[i].type,
+                                           ralloc_strdup(mem_ctx, 
iface_t->fields.structure[i].name),
                                             (ir_variable_mode) var->mode);
-               new_var->interface_type = t;
+               if (array_t != NULL) {
+                  const glsl_type *new_array_type =
+                     glsl_type::get_array_instance(
+                        iface_t->fields.structure[i].type,
+                        array_t->length);
+                  char *array_var_name =
+                     ralloc_asprintf(mem_ctx, "%s[%d]",
+                                     new_var->name, array_t->length);
+                  ir_variable *new_array_var =
+                     new(mem_ctx) ir_variable(new_array_type,
+                                              array_var_name,
+                                              (ir_variable_mode) var->mode);
+                  new_var = new_array_var;

Don't you leak the previously allocated instance of 'ir_variable' (assigned to
'new_var')? Or is it just left until 'mem_ctx' gets released?
I'm not that familiar with the glsl core that I may well be missing something.

This is actually fairly common in the GLSL code - we routinely just drop allocated memory on the floor. But, it all works out thanks to the magic of talloc/ralloc(*).

With talloc, you allocate memory out af a 'context'. Freeing a context frees any memory associated with it, which means you can free a whole bunch of things without tracking them all down and calling free() on each individual pointer. It also means you don't need to explicitly keep pointers to each object, as the memory context does that for you.

Any talloced piece of memory is also a new context, which allows you to create a tree-like structure (the 't' in talloc is for 'tree', and the 'r' in ralloc is for 'recursive').

In the GLSL compiler, we allocate IR out of either the parser state or the gl_shader object (I forget which). During optimization, linking, and so on, we create new IR, and remove other IR, all without worrying about memory. Then, when we're done compiling/linking, we walk through the remaining IR tree, calling talloc_steal() on each remaining IR node to reparent the memory to a second memory context. Then we free the original memory context, which now contains only the junk we don't need anymore.

(*) ralloc is my poor man's reimplementation of talloc, licensed under the MIT license rather than LGPLv3. It also has a slightly different API and performance characteristics.
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to