[Mesa-dev] [PATCH 08/10] glsl/linker: Modify array_sizing_visitor to handle named interface blocks.
Jordan Justen
jljusten at gmail.com
Wed Oct 9 06:17:01 CEST 2013
On Fri, Sep 27, 2013 at 12:05 PM, Paul Berry <stereotype441 at gmail.com> wrote:
> Unsized arrays appearing inside named interface blocks now get a
> proper size assigned by the array_sizing_visitor.
>
> Fixes piglit tests:
> - spec/glsl-1.50/execution/unsized-in-named-interface-block
> - spec/glsl-1.50/execution/unsized-in-named-interface-block-gs
> - spec/glsl-1.50/linker/unsized-in-named-interface-block
> - spec/glsl-1.50/linker/unsized-in-named-interface-block-gs
> - spec/glsl-1.50/linker/unsized-in-unnamed-interface-block-gs (*)
>
> (*) is fixed by dumb luck--support for unsized arrays in unnamed
> interface blocks will come in a later patch.
> ---
> src/glsl/ir.h | 16 +++++++++++
> src/glsl/linker.cpp | 77 ++++++++++++++++++++++++++++++++++++++++++++++++-----
> 2 files changed, 87 insertions(+), 6 deletions(-)
>
> diff --git a/src/glsl/ir.h b/src/glsl/ir.h
> index 4f63562..16bb76c 100644
> --- a/src/glsl/ir.h
> +++ b/src/glsl/ir.h
> @@ -420,6 +420,22 @@ public:
> }
> }
>
> + /**
> + * Change this->interface_type on a variable that previously had a
> + * different interface_type. This is used during linking to set the size
> + * of arrays in interface blocks.
> + */
> + void change_interface_type(const struct glsl_type *type)
> + {
> + if (this->max_ifc_array_access != NULL) {
> + /* max_ifc_array_access has already been allocated, so make sure the
> + * new interface has the same number of fields as the old one.
> + */
> + assert(this->interface_type->length == type->length);
> + }
> + this->interface_type = type;
> + }
> +
> const glsl_type *get_interface_type() const
> {
> return this->interface_type;
> diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
> index c54b704..fe4ccee 100644
> --- a/src/glsl/linker.cpp
> +++ b/src/glsl/linker.cpp
> @@ -1035,15 +1035,80 @@ class array_sizing_visitor : public ir_hierarchical_visitor {
> public:
> virtual ir_visitor_status visit(ir_variable *var)
> {
> - if (var->type->is_array() && (var->type->length == 0)) {
> - const glsl_type *type =
> - glsl_type::get_array_instance(var->type->fields.array,
> - var->max_array_access + 1);
> - assert(type != NULL);
> - var->type = type;
> + fixup_type(&var->type, var->max_array_access);
> + if (var->type->is_interface()) {
> + if (interface_contains_unsized_arrays(var->type)) {
> + const glsl_type *new_type =
> + resize_interface_members(var->type, var->max_ifc_array_access);
> + var->type = new_type;
> + var->change_interface_type(new_type);
> + }
> + } else if (var->type->is_array() &&
> + var->type->fields.array->is_interface()) {
> + if (interface_contains_unsized_arrays(var->type->fields.array)) {
> + const glsl_type *new_type =
> + resize_interface_members(var->type->fields.array,
> + var->max_ifc_array_access);
> + var->change_interface_type(new_type);
> + var->type =
> + glsl_type::get_array_instance(new_type, var->type->length);
> + }
> }
> return visit_continue;
> }
> +
> +private:
> + /**
> + * If the type pointed to by \c type represents an unsized array, replace
> + * it with a sized array whose size is determined by max_array_access.
> + */
> + static void fixup_type(const glsl_type **type, unsigned max_array_access)
> + {
> + if ((*type)->is_array() && (*type)->length == 0) {
> + *type = glsl_type::get_array_instance((*type)->fields.array,
> + max_array_access + 1);
> + assert(*type != NULL);
> + }
> + }
> +
> + /**
> + * Determine whether the given interface type contains unsized arrays (if
> + * it doesn't, array_sizing_visitor doesn't need to process it).
> + */
> + static bool interface_contains_unsized_arrays(const glsl_type *type)
> + {
> + for (unsigned i = 0; i < type->length; i++) {
> + const glsl_type *elem_type = type->fields.structure[i].type;
> + if (elem_type->is_array() && elem_type->length == 0)
> + return true;
> + }
> + return false;
> + }
> +
> + /**
> + * Create a new interface type based on the given type, with unsized arrays
> + * replaced by sized arrays whose size is determined by
> + * max_ifc_array_access.
> + */
> + static const glsl_type *
> + resize_interface_members(const glsl_type *type,
> + const unsigned *max_ifc_array_access)
> + {
> + unsigned num_fields = type->length;
> + glsl_struct_field *fields = new glsl_struct_field[num_fields];
Couldn't you use:
glsl_struct_field fields[num_fields];
to allocate on the stack, and drop the delete below?
> + memcpy(fields, type->fields.structure,
> + num_fields * sizeof(*fields));
> + for (unsigned i = 0; i < num_fields; i++) {
> + fixup_type(&fields[i].type, max_ifc_array_access[i]);
> + }
> + glsl_interface_packing packing =
> + (glsl_interface_packing) type->interface_packing;
> + const glsl_type *new_ifc_type =
> + glsl_type::get_interface_instance(fields, num_fields,
> + packing, type->name);
> + delete [] fields;
> + return new_ifc_type;
> + }
> };
>
> /**
> --
> 1.8.4
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list