==== ./Mesa-10.0.3/src/glsl/linker.cpp#2 (text) ==== @@ -556,7 +556,56 @@ prog->Geom.UsesEndPrimitive = end_primitive.end_primitive_found(); } +/** + * Checks if the types are the same under the rules of GLSL spec section 4.2 + */ +bool +are_glsl_uniform_types_same(const struct glsl_type *left, + const struct glsl_type *right) +{ + if (left == right) + return true; + + if (left->base_type != right->base_type) + return false; + + if (left->is_record()) { + // same names + if (strcmp(left->name, right->name) != 0) { + return false; + } + // same number of fields + if (left->length != right->length) { + return false; + } + + for (unsigned i = 0; i < left->length; ++i) { + glsl_struct_field* lf = left->fields.structure + i; + glsl_struct_field* rf = right->fields.structure + i; + + // field name and type must be the same + if (strcmp(lf->name, rf->name) != 0 || + !are_glsl_uniform_types_same(lf->type, rf->type) || + lf->row_major != rf->row_major) { + return false; + } + } + + // no mismatches found, must be good + return true; + } + + if (left->is_array()) { + // same length and element type + return left->length == right->length && + are_glsl_uniform_types_same(left->element_type(), right->element_type()); + } + + return false; +} + + /** * Perform validation of global variables used across multiple shaders */ @@ -609,7 +658,7 @@ if (var->type->length != 0) { existing->type = var->type; } - } else { + } else if (!are_glsl_uniform_types_same(var->type, existing->type)) { linker_error(prog, "%s `%s' declared as type " "`%s' and type `%s'\n", mode_string(var),