glsl: Assign locations for uniforms in UBOs using the std140 rules.
[profile/ivi/mesa.git] / src / glsl / linker.cpp
index 6587008..bfdde40 100644 (file)
@@ -101,7 +101,7 @@ public:
 
    virtual ir_visitor_status visit_enter(ir_call *ir)
    {
-      exec_list_iterator sig_iter = ir->get_callee()->parameters.iterator();
+      exec_list_iterator sig_iter = ir->callee->parameters.iterator();
       foreach_iter(exec_list_iterator, iter, *ir) {
         ir_rvalue *param_rval = (ir_rvalue *)iter.get();
         ir_variable *sig_param = (ir_variable *)sig_iter.get();
@@ -117,6 +117,15 @@ public:
         sig_iter.next();
       }
 
+      if (ir->return_deref != NULL) {
+        ir_variable *const var = ir->return_deref->variable_referenced();
+
+        if (strcmp(name, var->name) == 0) {
+           found = true;
+           return visit_stop;
+        }
+      }
+
       return visit_continue_with_parent;
    }
 
@@ -246,7 +255,8 @@ count_attribute_slots(const glsl_type *t)
 /**
  * Verify that a vertex shader executable meets all semantic requirements.
  *
- * Also sets prog->Vert.UsesClipDistance as a side effect.
+ * Also sets prog->Vert.UsesClipDistance and prog->Vert.ClipDistanceArraySize
+ * as a side effect.
  *
  * \param shader  Vertex shader executable to be verified
  */
@@ -257,13 +267,40 @@ validate_vertex_shader_executable(struct gl_shader_program *prog,
    if (shader == NULL)
       return true;
 
-   find_assignment_visitor find("gl_Position");
-   find.run(shader->ir);
-   if (!find.variable_found()) {
-      linker_error(prog, "vertex shader does not write to `gl_Position'\n");
-      return false;
+   /* From the GLSL 1.10 spec, page 48:
+    *
+    *     "The variable gl_Position is available only in the vertex
+    *      language and is intended for writing the homogeneous vertex
+    *      position. All executions of a well-formed vertex shader
+    *      executable must write a value into this variable. [...] The
+    *      variable gl_Position is available only in the vertex
+    *      language and is intended for writing the homogeneous vertex
+    *      position. All executions of a well-formed vertex shader
+    *      executable must write a value into this variable."
+    *
+    * while in GLSL 1.40 this text is changed to:
+    *
+    *     "The variable gl_Position is available only in the vertex
+    *      language and is intended for writing the homogeneous vertex
+    *      position. It can be written at any time during shader
+    *      execution. It may also be read back by a vertex shader
+    *      after being written. This value will be used by primitive
+    *      assembly, clipping, culling, and other fixed functionality
+    *      operations, if present, that operate on primitives after
+    *      vertex processing has occurred. Its value is undefined if
+    *      the vertex shader executable does not write gl_Position."
+    */
+   if (prog->Version < 140) {
+      find_assignment_visitor find("gl_Position");
+      find.run(shader->ir);
+      if (!find.variable_found()) {
+        linker_error(prog, "vertex shader does not write to `gl_Position'\n");
+        return false;
+      }
    }
 
+   prog->Vert.ClipDistanceArraySize = 0;
+
    if (prog->Version >= 130) {
       /* From section 7.1 (Vertex Shader Special Variables) of the
        * GLSL 1.30 spec:
@@ -282,6 +319,10 @@ validate_vertex_shader_executable(struct gl_shader_program *prog,
          return false;
       }
       prog->Vert.UsesClipDistance = clip_distance.variable_found();
+      ir_variable *clip_distance_var =
+         shader->symbols->get_variable("gl_ClipDistance");
+      if (clip_distance_var)
+         prog->Vert.ClipDistanceArraySize = clip_distance_var->type->length;
    }
 
    return true;
@@ -540,6 +581,48 @@ cross_validate_uniforms(struct gl_shader_program *prog)
                                 MESA_SHADER_TYPES, true);
 }
 
+/**
+ * Accumulates the array of prog->UniformBlocks and checks that all
+ * definitons of blocks agree on their contents.
+ */
+static bool
+interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog)
+{
+   unsigned max_num_uniform_blocks = 0;
+   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
+      if (prog->_LinkedShaders[i])
+        max_num_uniform_blocks += prog->_LinkedShaders[i]->NumUniformBlocks;
+   }
+
+   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
+      struct gl_shader *sh = prog->_LinkedShaders[i];
+
+      prog->UniformBlockStageIndex[i] = ralloc_array(prog, int,
+                                                    max_num_uniform_blocks);
+      for (unsigned int j = 0; j < max_num_uniform_blocks; j++)
+        prog->UniformBlockStageIndex[i][j] = -1;
+
+      if (sh == NULL)
+        continue;
+
+      for (unsigned int j = 0; j < sh->NumUniformBlocks; j++) {
+        int index = link_cross_validate_uniform_block(prog,
+                                                      &prog->UniformBlocks,
+                                                      &prog->NumUniformBlocks,
+                                                      &sh->UniformBlocks[j]);
+
+        if (index == -1) {
+           linker_error(prog, "uniform block `%s' has mismatching definitions",
+                        sh->UniformBlocks[j].Name);
+           return false;
+        }
+
+        prog->UniformBlockStageIndex[i][index] = j;
+      }
+   }
+
+   return true;
+}
 
 /**
  * Validate that outputs from one stage match inputs of another
@@ -798,6 +881,7 @@ move_non_declarations(exec_list *instructions, exec_node *last,
         continue;
 
       assert(inst->as_assignment()
+             || inst->as_call()
             || ((var != NULL) && (var->mode == ir_var_temporary)));
 
       if (make_copies) {
@@ -849,6 +933,26 @@ get_main_function_signature(gl_shader *sh)
 
 
 /**
+ * This class is only used in link_intrastage_shaders() below but declaring
+ * it inside that function leads to compiler warnings with some versions of
+ * gcc.
+ */
+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;
+      }
+      return visit_continue;
+   }
+};
+
+/**
  * Combine a group of shaders for a single stage to generate a linked shader
  *
  * \note
@@ -862,11 +966,33 @@ link_intrastage_shaders(void *mem_ctx,
                        struct gl_shader **shader_list,
                        unsigned num_shaders)
 {
+   struct gl_uniform_block *uniform_blocks = NULL;
+   unsigned num_uniform_blocks = 0;
+
    /* Check that global variables defined in multiple shaders are consistent.
     */
    if (!cross_validate_globals(prog, shader_list, num_shaders, false))
       return NULL;
 
+   /* Check that uniform blocks between shaders for a stage agree. */
+   for (unsigned i = 0; i < num_shaders; i++) {
+      struct gl_shader *sh = shader_list[i];
+
+      for (unsigned j = 0; j < shader_list[i]->NumUniformBlocks; j++) {
+        link_assign_uniform_block_offsets(shader_list[i]);
+
+        int index = link_cross_validate_uniform_block(mem_ctx,
+                                                      &uniform_blocks,
+                                                      &num_uniform_blocks,
+                                                      &sh->UniformBlocks[j]);
+        if (index == -1) {
+           linker_error(prog, "uniform block `%s' has mismatching definitions",
+                        sh->UniformBlocks[j].Name);
+           return NULL;
+        }
+      }
+   }
+
    /* Check that there is only a single definition of each function signature
     * across all shaders.
     */
@@ -934,6 +1060,10 @@ link_intrastage_shaders(void *mem_ctx,
    linked->ir = new(linked) exec_list;
    clone_ir_list(mem_ctx, linked->ir, main->ir);
 
+   linked->UniformBlocks = uniform_blocks;
+   linked->NumUniformBlocks = num_uniform_blocks;
+   ralloc_steal(linked, linked->UniformBlocks);
+
    populate_symbol_table(linked);
 
    /* The a pointer to the main function in the final linked shader (i.e., the
@@ -998,22 +1128,7 @@ link_intrastage_shaders(void *mem_ctx,
     * max_array_access field.
     */
    if (linked != NULL) {
-      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;
-           }
-
-           return visit_continue;
-        }
-      } v;
+      array_sizing_visitor v;
 
       v.run(linked->ir);
    }
@@ -1052,6 +1167,13 @@ update_array_sizes(struct gl_shader_program *prog)
             !var->type->is_array())
            continue;
 
+        /* GL_ARB_uniform_buffer_object says that std140 uniforms
+         * will not be eliminated.  Since we always do std140, just
+         * don't resize arrays in UBOs.
+         */
+        if (var->uniform_block != -1)
+           continue;
+
         unsigned int size = var->max_array_access;
         for (unsigned j = 0; j < MESA_SHADER_TYPES; j++) {
               if (prog->_LinkedShaders[j] == NULL)
@@ -1226,10 +1348,15 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
         }
       } else if (target_index == MESA_SHADER_FRAGMENT) {
         unsigned binding;
+        unsigned index;
 
         if (prog->FragDataBindings->get(binding, var->name)) {
            assert(binding >= FRAG_RESULT_DATA0);
            var->location = binding;
+
+           if (prog->FragDataIndexBindings->get(index, var->name)) {
+              var->index = index;
+           }
         }
       }
 
@@ -1240,7 +1367,7 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
        */
       const unsigned slots = count_attribute_slots(var->type);
       if (var->location != -1) {
-        if (var->location >= generic_base) {
+        if (var->location >= generic_base && var->index < 1) {
            /* From page 61 of the OpenGL 4.0 spec:
             *
             *     "LinkProgram will fail if the attribute bindings assigned
@@ -1281,10 +1408,12 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
             * attribute overlaps any previously allocated bits.
             */
            if ((~(use_mask << attr) & used_locations) != used_locations) {
+              const char *const string = (target_index == MESA_SHADER_VERTEX)
+                 ? "vertex shader input" : "fragment shader output";
               linker_error(prog,
-                           "insufficient contiguous attribute locations "
-                           "available for vertex shader input `%s'",
-                           var->name);
+                           "insufficient contiguous locations "
+                           "available for %s `%s' %d %d %d", string,
+                           var->name, used_locations, use_mask, attr);
               return false;
            }
 
@@ -1332,7 +1461,7 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
            ? "vertex shader input" : "fragment shader output";
 
         linker_error(prog,
-                     "insufficient contiguous attribute locations "
+                     "insufficient contiguous locations "
                      "available for %s `%s'",
                      string, to_assign[i].var->name);
         return false;
@@ -1376,14 +1505,15 @@ demote_shader_inputs_and_outputs(gl_shader *sh, enum ir_variable_mode mode)
 class tfeedback_decl
 {
 public:
-   bool init(struct gl_shader_program *prog, const void *mem_ctx,
-             const char *input);
+   bool init(struct gl_context *ctx, struct gl_shader_program *prog,
+             const void *mem_ctx, const char *input);
    static bool is_same(const tfeedback_decl &x, const tfeedback_decl &y);
    bool assign_location(struct gl_context *ctx, struct gl_shader_program *prog,
                         ir_variable *output_var);
-   bool store(struct gl_shader_program *prog,
-              struct gl_transform_feedback_info *info, unsigned buffer) const;
-
+   bool accumulate_num_outputs(struct gl_shader_program *prog, unsigned *count);
+   bool store(struct gl_context *ctx, struct gl_shader_program *prog,
+              struct gl_transform_feedback_info *info, unsigned buffer,
+              const unsigned max_outputs) const;
 
    /**
     * True if assign_location() has been called for this object.
@@ -1393,12 +1523,25 @@ public:
       return this->location != -1;
    }
 
+   bool is_next_buffer_separator() const
+   {
+      return this->next_buffer_separator;
+   }
+
+   bool is_varying() const
+   {
+      return !this->next_buffer_separator && !this->skip_components;
+   }
+
    /**
     * Determine whether this object refers to the variable var.
     */
    bool matches_var(ir_variable *var) const
    {
-      return strcmp(var->name, this->var_name) == 0;
+      if (this->is_clip_distance_mesa)
+         return strcmp(var->name, "gl_ClipDistanceMESA") == 0;
+      else
+         return strcmp(var->name, this->var_name) == 0;
    }
 
    /**
@@ -1407,30 +1550,39 @@ public:
     */
    unsigned num_components() const
    {
-      return this->vector_elements * this->matrix_columns;
+      if (this->is_clip_distance_mesa)
+         return this->size;
+      else
+         return this->vector_elements * this->matrix_columns * this->size;
    }
 
 private:
    /**
     * The name that was supplied to glTransformFeedbackVaryings.  Used for
-    * error reporting.
+    * error reporting and glGetTransformFeedbackVarying().
     */
    const char *orig_name;
 
    /**
     * The name of the variable, parsed from orig_name.
     */
-   char *var_name;
+   const char *var_name;
 
    /**
     * True if the declaration in orig_name represents an array.
     */
-   bool is_array;
+   bool is_subscripted;
 
    /**
-    * If is_array is true, the array index that was specified in orig_name.
+    * If is_subscripted is true, the subscript that was specified in orig_name.
     */
-   unsigned array_index;
+   unsigned array_subscript;
+
+   /**
+    * True if the variable is gl_ClipDistance and the driver lowers
+    * gl_ClipDistance to gl_ClipDistanceMESA.
+    */
+   bool is_clip_distance_mesa;
 
    /**
     * The vertex shader output location that the linker assigned for this
@@ -1449,6 +1601,26 @@ private:
     * if this variable is not a matrix.
     */
    unsigned matrix_columns;
+
+   /** Type of the varying returned by glGetTransformFeedbackVarying() */
+   GLenum type;
+
+   /**
+    * If location != -1, the size that should be returned by
+    * glGetTransformFeedbackVarying().
+    */
+   unsigned size;
+
+   /**
+    * How many components to skip. If non-zero, this is
+    * gl_SkipComponents{1,2,3,4} from ARB_transform_feedback3.
+    */
+   unsigned skip_components;
+
+   /**
+    * Whether this is gl_NextBuffer from ARB_transform_feedback3.
+    */
+   bool next_buffer_separator;
 };
 
 
@@ -1458,8 +1630,8 @@ private:
  * reported using linker_error(), and false is returned.
  */
 bool
-tfeedback_decl::init(struct gl_shader_program *prog, const void *mem_ctx,
-                     const char *input)
+tfeedback_decl::init(struct gl_context *ctx, struct gl_shader_program *prog,
+                     const void *mem_ctx, const char *input)
 {
    /* We don't have to be pedantic about what is a valid GLSL variable name,
     * because any variable with an invalid name can't exist in the IR anyway.
@@ -1467,23 +1639,56 @@ tfeedback_decl::init(struct gl_shader_program *prog, const void *mem_ctx,
 
    this->location = -1;
    this->orig_name = input;
+   this->is_clip_distance_mesa = false;
+   this->skip_components = 0;
+   this->next_buffer_separator = false;
+
+   if (ctx->Extensions.ARB_transform_feedback3) {
+      /* Parse gl_NextBuffer. */
+      if (strcmp(input, "gl_NextBuffer") == 0) {
+         this->next_buffer_separator = true;
+         return true;
+      }
+
+      /* Parse gl_SkipComponents. */
+      if (strcmp(input, "gl_SkipComponents1") == 0)
+         this->skip_components = 1;
+      else if (strcmp(input, "gl_SkipComponents2") == 0)
+         this->skip_components = 2;
+      else if (strcmp(input, "gl_SkipComponents3") == 0)
+         this->skip_components = 3;
+      else if (strcmp(input, "gl_SkipComponents4") == 0)
+         this->skip_components = 4;
+
+      if (this->skip_components)
+         return true;
+   }
 
+   /* Parse a declaration. */
    const char *bracket = strrchr(input, '[');
 
    if (bracket) {
       this->var_name = ralloc_strndup(mem_ctx, input, bracket - input);
-      if (sscanf(bracket, "[%u]", &this->array_index) == 1) {
-         this->is_array = true;
-         return true;
+      if (sscanf(bracket, "[%u]", &this->array_subscript) != 1) {
+         linker_error(prog, "Cannot parse transform feedback varying %s", input);
+         return false;
       }
+      this->is_subscripted = true;
    } else {
       this->var_name = ralloc_strdup(mem_ctx, input);
-      this->is_array = false;
-      return true;
+      this->is_subscripted = false;
    }
 
-   linker_error(prog, "Cannot parse transform feedback varying %s", input);
-   return false;
+   /* For drivers that lower gl_ClipDistance to gl_ClipDistanceMESA, this
+    * class must behave specially to account for the fact that gl_ClipDistance
+    * is converted from a float[8] to a vec4[2].
+    */
+   if (ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].LowerClipDistance &&
+       strcmp(this->var_name, "gl_ClipDistance") == 0) {
+      this->is_clip_distance_mesa = true;
+   }
+
+   return true;
 }
 
 
@@ -1494,11 +1699,13 @@ tfeedback_decl::init(struct gl_shader_program *prog, const void *mem_ctx,
 bool
 tfeedback_decl::is_same(const tfeedback_decl &x, const tfeedback_decl &y)
 {
+   assert(x.is_varying() && y.is_varying());
+
    if (strcmp(x.var_name, y.var_name) != 0)
       return false;
-   if (x.is_array != y.is_array)
+   if (x.is_subscripted != y.is_subscripted)
       return false;
-   if (x.is_array && x.array_index != y.array_index)
+   if (x.is_subscripted && x.array_subscript != y.array_subscript)
       return false;
    return true;
 }
@@ -1516,40 +1723,57 @@ tfeedback_decl::assign_location(struct gl_context *ctx,
                                 struct gl_shader_program *prog,
                                 ir_variable *output_var)
 {
+   assert(this->is_varying());
+
    if (output_var->type->is_array()) {
       /* Array variable */
-      if (!this->is_array) {
-         linker_error(prog, "Transform feedback varying %s found, "
-                      "but it's not an array ([] not expected).",
-                      this->orig_name);
-         return false;
-      }
-      /* Check array bounds. */
-      if (this->array_index >=
-          (unsigned) output_var->type->array_size()) {
-         linker_error(prog, "Transform feedback varying %s has index "
-                      "%i, but the array size is %i.",
-                      this->orig_name, this->array_index,
-                      output_var->type->array_size());
-         return false;
-      }
       const unsigned matrix_cols =
          output_var->type->fields.array->matrix_columns;
-      this->location = output_var->location + this->array_index * matrix_cols;
+      unsigned actual_array_size = this->is_clip_distance_mesa ?
+         prog->Vert.ClipDistanceArraySize : output_var->type->array_size();
+
+      if (this->is_subscripted) {
+         /* Check array bounds. */
+         if (this->array_subscript >= actual_array_size) {
+            linker_error(prog, "Transform feedback varying %s has index "
+                         "%i, but the array size is %u.",
+                         this->orig_name, this->array_subscript,
+                         actual_array_size);
+            return false;
+         }
+         if (this->is_clip_distance_mesa) {
+            this->location =
+               output_var->location + this->array_subscript / 4;
+         } else {
+            this->location =
+               output_var->location + this->array_subscript * matrix_cols;
+         }
+         this->size = 1;
+      } else {
+         this->location = output_var->location;
+         this->size = actual_array_size;
+      }
       this->vector_elements = output_var->type->fields.array->vector_elements;
       this->matrix_columns = matrix_cols;
+      if (this->is_clip_distance_mesa)
+         this->type = GL_FLOAT;
+      else
+         this->type = output_var->type->fields.array->gl_type;
    } else {
       /* Regular variable (scalar, vector, or matrix) */
-      if (this->is_array) {
-         linker_error(prog, "Transform feedback varying %s found, "
-                      "but it's an array ([] expected).",
-                      this->orig_name);
+      if (this->is_subscripted) {
+         linker_error(prog, "Transform feedback varying %s requested, "
+                      "but %s is not an array.",
+                      this->orig_name, this->var_name);
          return false;
       }
       this->location = output_var->location;
+      this->size = 1;
       this->vector_elements = output_var->type->vector_elements;
       this->matrix_columns = output_var->type->matrix_columns;
+      this->type = output_var->type->gl_type;
    }
+
    /* From GL_EXT_transform_feedback:
     *   A program will fail to link if:
     *
@@ -1571,17 +1795,14 @@ tfeedback_decl::assign_location(struct gl_context *ctx,
 }
 
 
-/**
- * Update gl_transform_feedback_info to reflect this tfeedback_decl.
- *
- * If an error occurs, the error is reported through linker_error() and false
- * is returned.
- */
 bool
-tfeedback_decl::store(struct gl_shader_program *prog,
-                      struct gl_transform_feedback_info *info,
-                      unsigned buffer) const
+tfeedback_decl::accumulate_num_outputs(struct gl_shader_program *prog,
+                                       unsigned *count)
 {
+   if (!this->is_varying()) {
+      return true;
+   }
+
    if (!this->is_assigned()) {
       /* From GL_EXT_transform_feedback:
        *   A program will fail to link if:
@@ -1594,14 +1815,86 @@ tfeedback_decl::store(struct gl_shader_program *prog,
                    this->orig_name);
       return false;
    }
-   for (unsigned v = 0; v < this->matrix_columns; ++v) {
-      info->Outputs[info->NumOutputs].OutputRegister = this->location + v;
-      info->Outputs[info->NumOutputs].NumComponents = this->vector_elements;
-      info->Outputs[info->NumOutputs].OutputBuffer = buffer;
-      info->Outputs[info->NumOutputs].DstOffset = info->BufferStride[buffer];
-      ++info->NumOutputs;
-      info->BufferStride[buffer] += this->vector_elements;
+
+   unsigned translated_size = this->size;
+   if (this->is_clip_distance_mesa)
+      translated_size = (translated_size + 3) / 4;
+
+   *count += translated_size * this->matrix_columns;
+
+   return true;
+}
+
+
+/**
+ * Update gl_transform_feedback_info to reflect this tfeedback_decl.
+ *
+ * If an error occurs, the error is reported through linker_error() and false
+ * is returned.
+ */
+bool
+tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog,
+                      struct gl_transform_feedback_info *info,
+                      unsigned buffer, const unsigned max_outputs) const
+{
+   assert(!this->next_buffer_separator);
+
+   /* Handle gl_SkipComponents. */
+   if (this->skip_components) {
+      info->BufferStride[buffer] += this->skip_components;
+      return true;
+   }
+
+   /* From GL_EXT_transform_feedback:
+    *   A program will fail to link if:
+    *
+    *     * the total number of components to capture is greater than
+    *       the constant MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT
+    *       and the buffer mode is INTERLEAVED_ATTRIBS_EXT.
+    */
+   if (prog->TransformFeedback.BufferMode == GL_INTERLEAVED_ATTRIBS &&
+       info->BufferStride[buffer] + this->num_components() >
+       ctx->Const.MaxTransformFeedbackInterleavedComponents) {
+      linker_error(prog, "The MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS "
+                   "limit has been exceeded.");
+      return false;
+   }
+
+   unsigned translated_size = this->size;
+   if (this->is_clip_distance_mesa)
+      translated_size = (translated_size + 3) / 4;
+   unsigned components_so_far = 0;
+   for (unsigned index = 0; index < translated_size; ++index) {
+      for (unsigned v = 0; v < this->matrix_columns; ++v) {
+         unsigned num_components = this->vector_elements;
+         assert(info->NumOutputs < max_outputs);
+         info->Outputs[info->NumOutputs].ComponentOffset = 0;
+         if (this->is_clip_distance_mesa) {
+            if (this->is_subscripted) {
+               num_components = 1;
+               info->Outputs[info->NumOutputs].ComponentOffset =
+                  this->array_subscript % 4;
+            } else {
+               num_components = MIN2(4, this->size - components_so_far);
+            }
+         }
+         info->Outputs[info->NumOutputs].OutputRegister =
+            this->location + v + index * this->matrix_columns;
+         info->Outputs[info->NumOutputs].NumComponents = num_components;
+         info->Outputs[info->NumOutputs].OutputBuffer = buffer;
+         info->Outputs[info->NumOutputs].DstOffset = info->BufferStride[buffer];
+         ++info->NumOutputs;
+         info->BufferStride[buffer] += num_components;
+         components_so_far += num_components;
+      }
    }
+   assert(components_so_far == this->num_components());
+
+   info->Varyings[info->NumVarying].Name = ralloc_strdup(prog, this->orig_name);
+   info->Varyings[info->NumVarying].Type = this->type;
+   info->Varyings[info->NumVarying].Size = this->size;
+   info->NumVarying++;
+
    return true;
 }
 
@@ -1614,13 +1907,17 @@ tfeedback_decl::store(struct gl_shader_program *prog,
  * is returned.
  */
 static bool
-parse_tfeedback_decls(struct gl_shader_program *prog, const void *mem_ctx,
-                      unsigned num_names, char **varying_names,
-                      tfeedback_decl *decls)
+parse_tfeedback_decls(struct gl_context *ctx, struct gl_shader_program *prog,
+                      const void *mem_ctx, unsigned num_names,
+                      char **varying_names, tfeedback_decl *decls)
 {
    for (unsigned i = 0; i < num_names; ++i) {
-      if (!decls[i].init(prog, mem_ctx, varying_names[i]))
+      if (!decls[i].init(ctx, prog, mem_ctx, varying_names[i]))
          return false;
+
+      if (!decls[i].is_varying())
+         continue;
+
       /* From GL_EXT_transform_feedback:
        *   A program will fail to link if:
        *
@@ -1632,6 +1929,9 @@ parse_tfeedback_decls(struct gl_shader_program *prog, const void *mem_ctx,
        * feedback of arrays would be useless otherwise.
        */
       for (unsigned j = 0; j < i; ++j) {
+         if (!decls[j].is_varying())
+            continue;
+
          if (tfeedback_decl::is_same(decls[i], decls[j])) {
             linker_error(prog, "Transform feedback varying %s specified "
                          "more than once.", varying_names[i]);
@@ -1699,6 +1999,32 @@ assign_varying_location(ir_variable *input_var, ir_variable *output_var,
 
 
 /**
+ * Is the given variable a varying variable to be counted against the
+ * limit in ctx->Const.MaxVarying?
+ * This includes variables such as texcoords, colors and generic
+ * varyings, but excludes variables such as gl_FrontFacing and gl_FragCoord.
+ */
+static bool
+is_varying_var(GLenum shaderType, const ir_variable *var)
+{
+   /* Only fragment shaders will take a varying variable as an input */
+   if (shaderType == GL_FRAGMENT_SHADER &&
+       var->mode == ir_var_in &&
+       var->explicit_location) {
+      switch (var->location) {
+      case FRAG_ATTRIB_WPOS:
+      case FRAG_ATTRIB_FACE:
+      case FRAG_ATTRIB_PNTC:
+         return false;
+      default:
+         return true;
+      }
+   }
+   return false;
+}
+
+
+/**
  * Assign locations for all variables that are produced in one pipeline stage
  * (the "producer") and consumed in the next stage (the "consumer").
  *
@@ -1762,6 +2088,9 @@ assign_varying_locations(struct gl_context *ctx,
       }
 
       for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
+         if (!tfeedback_decls[i].is_varying())
+            continue;
+
          if (!tfeedback_decls[i].is_assigned() &&
              tfeedback_decls[i].matches_var(output_var)) {
             if (output_var->location == -1) {
@@ -1806,7 +2135,7 @@ assign_varying_locations(struct gl_context *ctx,
              * value is written by the previous stage.
              */
             var->mode = ir_var_auto;
-         } else {
+         } else if (is_varying_var(consumer->Type, var)) {
             /* The packing rules are used for vertex shader inputs are also
              * used for fragment shader inputs.
              */
@@ -1864,33 +2193,61 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
                      unsigned num_tfeedback_decls,
                      tfeedback_decl *tfeedback_decls)
 {
-   unsigned total_tfeedback_components = 0;
+   bool separate_attribs_mode =
+      prog->TransformFeedback.BufferMode == GL_SEPARATE_ATTRIBS;
+
+   ralloc_free(prog->LinkedTransformFeedback.Varyings);
+   ralloc_free(prog->LinkedTransformFeedback.Outputs);
+
    memset(&prog->LinkedTransformFeedback, 0,
           sizeof(prog->LinkedTransformFeedback));
-   for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
-      unsigned buffer =
-         prog->TransformFeedback.BufferMode == GL_SEPARATE_ATTRIBS ? i : 0;
-      if (!tfeedback_decls[i].store(prog, &prog->LinkedTransformFeedback,
-                                    buffer))
+
+   prog->LinkedTransformFeedback.Varyings =
+      rzalloc_array(prog,
+                   struct gl_transform_feedback_varying_info,
+                   num_tfeedback_decls);
+
+   unsigned num_outputs = 0;
+   for (unsigned i = 0; i < num_tfeedback_decls; ++i)
+      if (!tfeedback_decls[i].accumulate_num_outputs(prog, &num_outputs))
          return false;
-      total_tfeedback_components += tfeedback_decls[i].num_components();
+
+   prog->LinkedTransformFeedback.Outputs =
+      rzalloc_array(prog,
+                    struct gl_transform_feedback_output,
+                    num_outputs);
+
+   unsigned num_buffers = 0;
+
+   if (separate_attribs_mode) {
+      /* GL_SEPARATE_ATTRIBS */
+      for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
+         if (!tfeedback_decls[i].store(ctx, prog, &prog->LinkedTransformFeedback,
+                                       num_buffers, num_outputs))
+            return false;
+
+         num_buffers++;
+      }
    }
+   else {
+      /* GL_INVERLEAVED_ATTRIBS */
+      for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
+         if (tfeedback_decls[i].is_next_buffer_separator()) {
+            num_buffers++;
+            continue;
+         }
 
-   /* From GL_EXT_transform_feedback:
-    *   A program will fail to link if:
-    *
-    *     * the total number of components to capture is greater than
-    *       the constant MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT
-    *       and the buffer mode is INTERLEAVED_ATTRIBS_EXT.
-    */
-   if (prog->TransformFeedback.BufferMode == GL_INTERLEAVED_ATTRIBS &&
-       total_tfeedback_components >
-       ctx->Const.MaxTransformFeedbackInterleavedComponents) {
-      linker_error(prog, "The MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS "
-                   "limit has been exceeded.");
-      return false;
+         if (!tfeedback_decls[i].store(ctx, prog,
+                                       &prog->LinkedTransformFeedback,
+                                       num_buffers, num_outputs))
+            return false;
+      }
+      num_buffers++;
    }
 
+   assert(prog->LinkedTransformFeedback.NumOutputs == num_outputs);
+
+   prog->LinkedTransformFeedback.NumBuffers = num_buffers;
    return true;
 }
 
@@ -2006,11 +2363,17 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
    prog->Validated = false;
    prog->_Used = false;
 
-   if (prog->InfoLog != NULL)
-      ralloc_free(prog->InfoLog);
-
+   ralloc_free(prog->InfoLog);
    prog->InfoLog = ralloc_strdup(NULL, "");
 
+   ralloc_free(prog->UniformBlocks);
+   prog->UniformBlocks = NULL;
+   prog->NumUniformBlocks = 0;
+   for (int i = 0; i < MESA_SHADER_TYPES; i++) {
+      ralloc_free(prog->UniformBlockStageIndex[i]);
+      prog->UniformBlockStageIndex[i] = NULL;
+   }
+
    /* Separate the shaders into groups based on their type.
     */
    struct gl_shader **vert_shader_list;
@@ -2049,7 +2412,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
     * of all shaders must match.
     */
    assert(min_version >= 100);
-   assert(max_version <= 130);
+   assert(max_version <= 140);
    if ((max_version >= 130 || min_version == 100)
        && min_version != max_version) {
       linker_error(prog, "all shaders must use same shading "
@@ -2128,6 +2491,20 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
       prog->LinkStatus = true;
    }
 
+   /* Implement the GLSL 1.30+ rule for discard vs infinite loops Do
+    * it before optimization because we want most of the checks to get
+    * dropped thanks to constant propagation.
+    */
+   if (max_version >= 130) {
+      struct gl_shader *sh = prog->_LinkedShaders[MESA_SHADER_FRAGMENT];
+      if (sh) {
+        lower_discard_flow(sh->ir);
+      }
+   }
+
+   if (!interstage_cross_validate_uniform_blocks(prog))
+      goto done;
+
    /* Do common optimization before assigning storage for attributes,
     * uniforms, and varyings.  Later optimization could possibly make
     * some of that unused.
@@ -2143,7 +2520,9 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
       if (ctx->ShaderCompilerOptions[i].LowerClipDistance)
          lower_clip_distance(prog->_LinkedShaders[i]->ir);
 
-      while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, false, 32))
+      unsigned max_unroll = ctx->ShaderCompilerOptions[i].MaxUnrollIterations;
+
+      while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, false, max_unroll))
         ;
    }
 
@@ -2156,7 +2535,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
       goto done;
    }
 
-   if (!assign_attribute_or_color_locations(prog, MESA_SHADER_FRAGMENT, ctx->Const.MaxDrawBuffers)) {
+   if (!assign_attribute_or_color_locations(prog, MESA_SHADER_FRAGMENT, MAX2(ctx->Const.MaxDrawBuffers, ctx->Const.MaxDualSourceDrawBuffers))) {
       goto done;
    }
 
@@ -2182,7 +2561,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
 
       tfeedback_decls = ralloc_array(mem_ctx, tfeedback_decl,
                                      prog->TransformFeedback.NumVarying);
-      if (!parse_tfeedback_decls(prog, mem_ctx, num_tfeedback_decls,
+      if (!parse_tfeedback_decls(ctx, prog, mem_ctx, num_tfeedback_decls,
                                  prog->TransformFeedback.VaryingNames,
                                  tfeedback_decls))
          goto done;