+
+ /* Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1 spec
+ * says:
+ *
+ * - An output variable is considered to match an input variable in
+ * the subsequent shader if:
+ *
+ * - the two variables match in name, type, and qualification; or
+ *
+ * - the two variables are declared with the same location
+ * qualifier and match in type and qualification.
+ */
+ if (producer_var == NULL) {
+ valid = false;
+ goto out;
+ }
+
+ /* An output cannot match more than one input, so remove the output from
+ * the set of possible outputs.
+ */
+ outputs[match_index] = NULL;
+ num_outputs--;
+ if (match_index < num_outputs)
+ outputs[match_index] = outputs[num_outputs];
+
+ /* Section 7.4.1 (Shader Interface Matching) of the ES 3.2 spec says:
+ *
+ * "Tessellation control shader per-vertex output variables and
+ * blocks and tessellation control, tessellation evaluation, and
+ * geometry shader per-vertex input variables and blocks are
+ * required to be declared as arrays, with each element representing
+ * input or output values for a single vertex of a multi-vertex
+ * primitive. For the purposes of interface matching, such variables
+ * and blocks are treated as though they were not declared as
+ * arrays."
+ *
+ * So we unwrap those types before matching.
+ */
+ const glsl_type *consumer_type = consumer_var->type;
+ const glsl_type *consumer_interface_type = consumer_var->interface_type;
+ const glsl_type *producer_type = producer_var->type;
+ const glsl_type *producer_interface_type = producer_var->interface_type;
+
+ if (consumer_is_array_stage) {
+ if (consumer_interface_type) {
+ /* the interface is the array; the underlying types should match */
+ if (consumer_interface_type->is_array() && !consumer_var->patch)
+ consumer_interface_type = consumer_interface_type->fields.array;
+ } else {
+ if (consumer_type->is_array() && !consumer_var->patch)
+ consumer_type = consumer_type->fields.array;
+ }
+ }
+
+ if (producer_is_array_stage) {
+ if (producer_interface_type) {
+ /* the interface is the array; the underlying types should match */
+ if (producer_interface_type->is_array() && !producer_var->patch)
+ producer_interface_type = producer_interface_type->fields.array;
+ } else {
+ if (producer_type->is_array() && !producer_var->patch)
+ producer_type = producer_type->fields.array;
+ }
+ }
+
+ if (producer_type != consumer_type) {
+ valid = false;
+ goto out;
+ }
+
+ if (producer_interface_type != consumer_interface_type) {
+ valid = false;
+ goto out;
+ }
+
+ /* Section 9.2.2 (Separable Programs) of the GLSL ES spec says:
+ *
+ * Qualifier Class| Qualifier |in/out
+ * ---------------+-------------+------
+ * Storage | in |
+ * | out | N/A
+ * | uniform |
+ * ---------------+-------------+------
+ * Auxiliary | centroid | No
+ * ---------------+-------------+------
+ * | location | Yes
+ * | Block layout| N/A
+ * | binding | N/A
+ * | offset | N/A
+ * | format | N/A
+ * ---------------+-------------+------
+ * Interpolation | smooth |
+ * | flat | Yes
+ * ---------------+-------------+------
+ * | lowp |
+ * Precision | mediump | Yes
+ * | highp |
+ * ---------------+-------------+------
+ * Variance | invariant | No
+ * ---------------+-------------+------
+ * Memory | all | N/A
+ *
+ * Note that location mismatches are detected by the loops above that
+ * find the producer variable that goes with the consumer variable.
+ */
+ unsigned producer_interpolation = producer_var->interpolation;
+ unsigned consumer_interpolation = consumer_var->interpolation;
+ if (producer_interpolation == INTERP_MODE_NONE)
+ producer_interpolation = INTERP_MODE_SMOOTH;
+ if (consumer_interpolation == INTERP_MODE_NONE)
+ consumer_interpolation = INTERP_MODE_SMOOTH;
+ if (producer_interpolation != consumer_interpolation) {
+ valid = false;
+ goto out;
+ }
+
+ if (producer_var->precision != consumer_var->precision) {
+ valid = false;
+ goto out;
+ }
+
+ if (producer_var->outermost_struct_type != consumer_var->outermost_struct_type) {
+ valid = false;
+ goto out;
+ }