[Mesa-dev] [PATCH v2 13/15] glsl linker: support arrays of interface block instances
Pohjolainen, Topi
topi.pohjolainen at intel.com
Mon Mar 25 03:21:50 PDT 2013
On Sat, Mar 23, 2013 at 01:48:44PM -0700, Kenneth Graunke wrote:
> 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.justen at 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.
Yes, I took a look at the implemention just after asking about it, and
understood that it is indeed the 'mem_ctx' bookkeeping that this "dropping on
the floor" is relying on as you explained. The implentation does, however,
allow one to use it without a context (mem_ctx == 0) and in that case there
would be nothing keeping track and hence the things "on the floor" getting
leaked. But I assume there is nothing using this logic without a proper memory
context.
More information about the mesa-dev
mailing list