diff options
author | Paul Berry <[email protected]> | 2013-09-23 10:44:19 -0700 |
---|---|---|
committer | Paul Berry <[email protected]> | 2013-10-09 16:49:41 -0700 |
commit | e226669eea47e2075c1188e5c61e0ba479ff8d47 (patch) | |
tree | b72ebabd99ae6e1cd1623dce58bb504e259e33e5 /src/glsl/linker.cpp | |
parent | f878d2060c196c8130af0912ffc4493c631b1c34 (diff) |
glsl/linker: Modify array_sizing_visitor to handle named interface blocks.
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.
Reviewed-by: Jordan Justen <[email protected]>
Diffstat (limited to 'src/glsl/linker.cpp')
-rw-r--r-- | src/glsl/linker.cpp | 77 |
1 files changed, 71 insertions, 6 deletions
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 61904dc0ed5..db1fe9a0d85 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]; + 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; + } }; /** |