+ if (!out->name)
+ return NULL;
+
+ /* 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 (glsl_get_base_type(in->type) == GLSL_TYPE_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->precision = in->data.precision;
+ out->explicit_location = in->data.explicit_location;
+
+ 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, nir_variable *var,
+ const char *name, const struct glsl_type *type,
+ bool use_implicit_location, int location,
+ bool inouts_share_location,
+ const struct glsl_type *outermost_struct_type)
+{
+ const struct glsl_type *interface_type = var->interface_type;
+
+ if (outermost_struct_type == NULL) {
+ if (var->data.from_named_ifc_block) {
+ const char *interface_name = glsl_get_type_name(interface_type);
+
+ if (glsl_type_is_array(interface_type)) {
+ /* 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 = glsl_get_array_element(type);
+
+ interface_name =
+ glsl_get_type_name(glsl_get_array_element(interface_type));
+ }
+
+ name = ralloc_asprintf(shProg, "%s.%s", interface_name, name);
+ }
+ }
+
+ switch (glsl_get_base_type(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 < glsl_get_length(type); i++) {
+ const struct glsl_type *field_type = glsl_get_struct_field(type, i);
+ const struct glsl_struct_field *field =
+ glsl_get_struct_field_data(type, 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,
+ false, outermost_struct_type))
+ return false;
+
+ field_location += glsl_count_attribute_slots(field_type, false);
+ }
+ return true;
+ }
+
+ case GLSL_TYPE_ARRAY: {
+ /* The ARB_program_interface_query spec says:
+ *
+ * "For an active variable declared as an array of basic types, a
+ * single entry will be generated, with its name string formed by
+ * concatenating the name of the array and the string "[0]"."
+ *
+ * "For an active variable declared as an array of an aggregate data
+ * type (structures or arrays), a separate entry will be generated
+ * for each active array element, unless noted immediately below.
+ * The name of each entry is formed by concatenating the name of
+ * the array, the "[" character, an integer identifying the element
+ * number, and the "]" character. These enumeration rules are
+ * applied recursively, treating each enumerated array element as a
+ * separate active variable."
+ */
+ const struct glsl_type *array_type = glsl_get_array_element(type);
+ if (glsl_get_base_type(array_type) == GLSL_TYPE_STRUCT ||
+ glsl_get_base_type(array_type) == GLSL_TYPE_ARRAY) {
+ unsigned elem_location = location;
+ unsigned stride = inouts_share_location ? 0 :
+ glsl_count_attribute_slots(array_type, false);
+ for (unsigned i = 0; i < glsl_get_length(type); i++) {
+ char *elem = ralloc_asprintf(shProg, "%s[%d]", name, i);
+ if (!add_shader_variable(ctx, shProg, resource_set,
+ stage_mask, programInterface,
+ var, elem, array_type,
+ use_implicit_location, elem_location,
+ false, outermost_struct_type))
+ return false;
+ elem_location += stride;
+ }
+ return true;
+ }
+ }
+ /* fallthrough */
+
+ 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."
+ */
+ struct 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;
+
+ return link_util_add_program_resource(shProg, resource_set,
+ programInterface, sha_v, stage_mask);
+ }
+ }
+}
+
+static bool
+add_vars_with_modes(const struct gl_context *ctx,
+ struct gl_shader_program *prog, struct set *resource_set,
+ nir_shader *nir, nir_variable_mode modes,
+ unsigned stage, GLenum programInterface)
+{
+ nir_foreach_variable_with_modes(var, nir, modes) {