+ /* The ARB_program_interface_query spec says:
+ *
+ * "Not all active variables are assigned valid locations; the
+ * following variables will have an effective location of -1:
+ *
+ * * uniforms declared as atomic counters;
+ *
+ * * members of a uniform block;
+ *
+ * * built-in inputs, outputs, and uniforms (starting with "gl_"); and
+ *
+ * * inputs or outputs not declared with a "location" layout
+ * qualifier, except for vertex shader inputs and fragment shader
+ * outputs."
+ */
+ if (in->type->is_atomic_uint() || is_gl_identifier(in->name) ||
+ !(in->data.explicit_location || use_implicit_location)) {
+ out->location = -1;
+ } else {
+ out->location = location;
+ }
+
+ out->type = type;
+ out->outermost_struct_type = outermost_struct_type;
+ out->interface_type = interface_type;
+ out->component = in->data.location_frac;
+ out->index = in->data.index;
+ out->patch = in->data.patch;
+ out->mode = in->data.mode;
+ out->interpolation = in->data.interpolation;
+ out->explicit_location = in->data.explicit_location;
+ out->precision = in->data.precision;
+
+ return out;
+}
+
+static bool
+add_shader_variable(const struct gl_context *ctx,
+ struct gl_shader_program *shProg,
+ struct set *resource_set,
+ unsigned stage_mask,
+ GLenum programInterface, ir_variable *var,
+ const char *name, const glsl_type *type,
+ bool use_implicit_location, int location,
+ const glsl_type *outermost_struct_type = NULL)
+{
+ const glsl_type *interface_type = var->get_interface_type();
+
+ if (outermost_struct_type == NULL) {
+ if (var->data.from_named_ifc_block) {
+ const char *interface_name = interface_type->name;
+
+ if (interface_type->is_array()) {
+ /* Issue #16 of the ARB_program_interface_query spec says:
+ *
+ * "* If a variable is a member of an interface block without an
+ * instance name, it is enumerated using just the variable name.
+ *
+ * * If a variable is a member of an interface block with an
+ * instance name, it is enumerated as "BlockName.Member", where
+ * "BlockName" is the name of the interface block (not the
+ * instance name) and "Member" is the name of the variable."
+ *
+ * In particular, it indicates that it should be "BlockName",
+ * not "BlockName[array length]". The conformance suite and
+ * dEQP both require this behavior.
+ *
+ * Here, we unwrap the extra array level added by named interface
+ * block array lowering so we have the correct variable type. We
+ * also unwrap the interface type when constructing the name.
+ *
+ * We leave interface_type the same so that ES 3.x SSO pipeline
+ * validation can enforce the rules requiring array length to
+ * match on interface blocks.
+ */
+ type = type->fields.array;
+
+ interface_name = interface_type->fields.array->name;
+ }
+
+ name = ralloc_asprintf(shProg, "%s.%s", interface_name, name);
+ }
+ }
+
+ switch (type->base_type) {
+ case GLSL_TYPE_STRUCT: {
+ /* The ARB_program_interface_query spec says:
+ *
+ * "For an active variable declared as a structure, a separate entry
+ * will be generated for each active structure member. The name of
+ * each entry is formed by concatenating the name of the structure,
+ * the "." character, and the name of the structure member. If a
+ * structure member to enumerate is itself a structure or array,
+ * these enumeration rules are applied recursively."
+ */
+ if (outermost_struct_type == NULL)
+ outermost_struct_type = type;
+
+ unsigned field_location = location;
+ for (unsigned i = 0; i < type->length; i++) {
+ const struct glsl_struct_field *field = &type->fields.structure[i];
+ char *field_name = ralloc_asprintf(shProg, "%s.%s", name, field->name);
+ if (!add_shader_variable(ctx, shProg, resource_set,
+ stage_mask, programInterface,
+ var, field_name, field->type,
+ use_implicit_location, field_location,
+ outermost_struct_type))
+ return false;
+
+ field_location += field->type->count_attribute_slots(false);
+ }
+ return true;
+ }
+
+ default: {
+ /* The ARB_program_interface_query spec says:
+ *
+ * "For an active variable declared as a single instance of a basic
+ * type, a single entry will be generated, using the variable name
+ * from the shader source."
+ */
+ gl_shader_variable *sha_v =
+ create_shader_variable(shProg, var, name, type, interface_type,
+ use_implicit_location, location,
+ outermost_struct_type);
+ if (!sha_v)
+ return false;