mesa: add ARB_texture_buffer_range glTextureBufferRangeEXT function
[mesa.git] / src / mesa / main / shaderapi.c
index 10cee7b0220d5a5d07219d16d59e0b5ae4016574..8bca17a9352389f048e0d7f0e1b86cdfe5686fbc 100644 (file)
  *
  * Implementation of GLSL-related API functions.
  * The glUniform* functions are in uniforms.c
- *
- *
- * XXX things to do:
- * 1. Check that the right error code is generated for all _mesa_error() calls.
- * 2. Insert FLUSH_VERTICES calls in various places
  */
 
 
+#include <errno.h>
 #include <stdbool.h>
+#include <c99_alloca.h>
 #include "main/glheader.h"
 #include "main/context.h"
-#include "main/dispatch.h"
 #include "main/enums.h"
+#include "main/glspirv.h"
 #include "main/hash.h"
 #include "main/mtypes.h"
 #include "main/pipelineobj.h"
+#include "main/program_binary.h"
 #include "main/shaderapi.h"
 #include "main/shaderobj.h"
+#include "main/state.h"
 #include "main/transformfeedback.h"
 #include "main/uniforms.h"
+#include "compiler/glsl/builtin_functions.h"
 #include "compiler/glsl/glsl_parser_extras.h"
 #include "compiler/glsl/ir.h"
 #include "compiler/glsl/ir_uniform.h"
@@ -60,6 +60,7 @@
 #include "util/hash_table.h"
 #include "util/mesa-sha1.h"
 #include "util/crc32.h"
+#include "util/os_file.h"
 
 /**
  * Return mask of GLSL_x flags by examining the MESA_GLSL env var.
@@ -77,14 +78,14 @@ _mesa_get_shader_flags(void)
          flags |= GLSL_DUMP;
       if (strstr(env, "log"))
          flags |= GLSL_LOG;
+      if (strstr(env, "cache_fb"))
+         flags |= GLSL_CACHE_FALLBACK;
+      if (strstr(env, "cache_info"))
+         flags |= GLSL_CACHE_INFO;
       if (strstr(env, "nopvert"))
          flags |= GLSL_NOP_VERT;
       if (strstr(env, "nopfrag"))
          flags |= GLSL_NOP_FRAG;
-      if (strstr(env, "nopt"))
-         flags |= GLSL_NO_OPT;
-      else if (strstr(env, "opt"))
-         flags |= GLSL_OPT;
       if (strstr(env, "uniform"))
          flags |= GLSL_UNIFORMS;
       if (strstr(env, "useprog"))
@@ -140,8 +141,6 @@ _mesa_init_shader_state(struct gl_context *ctx)
 
    /* Extended for ARB_separate_shader_objects */
    ctx->Shader.RefCount = 1;
-   mtx_init(&ctx->Shader.Mutex, mtx_plain);
-
    ctx->TessCtrlProgram.patch_vertices = 3;
    for (i = 0; i < 4; ++i)
       ctx->TessCtrlProgram.patch_default_outer_level[i] = 1.0;
@@ -156,20 +155,20 @@ _mesa_init_shader_state(struct gl_context *ctx)
 void
 _mesa_free_shader_state(struct gl_context *ctx)
 {
-   int i;
-   for (i = 0; i < MESA_SHADER_STAGES; i++) {
-      _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram[i],
+   for (int i = 0; i < MESA_SHADER_STAGES; i++) {
+      _mesa_reference_program(ctx, &ctx->Shader.CurrentProgram[i], NULL);
+      _mesa_reference_shader_program(ctx,
+                                     &ctx->Shader.ReferencedPrograms[i],
                                      NULL);
+      free(ctx->SubroutineIndex[i].IndexPtr);
+      ctx->SubroutineIndex[i].IndexPtr = NULL;
    }
-   _mesa_reference_shader_program(ctx, &ctx->Shader._CurrentFragmentProgram,
-                                 NULL);
    _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, NULL);
 
    /* Extended for ARB_separate_shader_objects */
    _mesa_reference_pipeline_object(ctx, &ctx->_Shader, NULL);
 
    assert(ctx->Shader.RefCount == 1);
-   mtx_destroy(&ctx->Shader.Mutex);
 }
 
 
@@ -251,7 +250,27 @@ is_shader(struct gl_context *ctx, GLuint name)
  * Attach shader to a shader program.
  */
 static void
-attach_shader(struct gl_context *ctx, GLuint program, GLuint shader)
+attach_shader(struct gl_context *ctx, struct gl_shader_program *shProg,
+              struct gl_shader *sh)
+{
+   GLuint n = shProg->NumShaders;
+
+   shProg->Shaders = realloc(shProg->Shaders,
+                             (n + 1) * sizeof(struct gl_shader *));
+   if (!shProg->Shaders) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
+      return;
+   }
+
+   /* append */
+   shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
+   _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
+   shProg->NumShaders++;
+}
+
+static void
+attach_shader_err(struct gl_context *ctx, GLuint program, GLuint shader,
+                  const char *caller)
 {
    struct gl_shader_program *shProg;
    struct gl_shader *sh;
@@ -259,11 +278,11 @@ attach_shader(struct gl_context *ctx, GLuint program, GLuint shader)
 
    const bool same_type_disallowed = _mesa_is_gles(ctx);
 
-   shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader");
+   shProg = _mesa_lookup_shader_program_err(ctx, program, caller);
    if (!shProg)
       return;
 
-   sh = _mesa_lookup_shader_err(ctx, shader, "glAttachShader");
+   sh = _mesa_lookup_shader_err(ctx, shader, caller);
    if (!sh) {
       return;
    }
@@ -277,7 +296,7 @@ attach_shader(struct gl_context *ctx, GLuint program, GLuint shader)
           *     "The error INVALID_OPERATION is generated by AttachObjectARB
           *     if <obj> is already attached to <containerObj>."
           */
-         _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader");
+         _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
          return;
       } else if (same_type_disallowed &&
                  shProg->Shaders[i]->Stage == sh->Stage) {
@@ -289,25 +308,25 @@ attach_shader(struct gl_context *ctx, GLuint program, GLuint shader)
          *      is generated if [...] another shader object of the same type
          *      as shader is already attached to program."
          */
-         _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader");
+         _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
          return;
       }
    }
 
-   /* grow list */
-   shProg->Shaders = realloc(shProg->Shaders,
-                             (n + 1) * sizeof(struct gl_shader *));
-   if (!shProg->Shaders) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
-      return;
-   }
-
-   /* append */
-   shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
-   _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
-   shProg->NumShaders++;
+   attach_shader(ctx, shProg, sh);
 }
 
+static void
+attach_shader_no_error(struct gl_context *ctx, GLuint program, GLuint shader)
+{
+   struct gl_shader_program *shProg;
+   struct gl_shader *sh;
+
+   shProg = _mesa_lookup_shader_program(ctx, program);
+   sh = _mesa_lookup_shader(ctx, shader);
+
+   attach_shader(ctx, shProg, sh);
+}
 
 static GLuint
 create_shader(struct gl_context *ctx, GLenum type)
@@ -315,12 +334,6 @@ create_shader(struct gl_context *ctx, GLenum type)
    struct gl_shader *sh;
    GLuint name;
 
-   if (!_mesa_validate_shader_target(ctx, type)) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(%s)",
-                  _mesa_enum_to_string(type));
-      return 0;
-   }
-
    _mesa_HashLockMutex(ctx->Shared->ShaderObjects);
    name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
    sh = _mesa_new_shader(name, _mesa_shader_enum_to_shader_stage(type));
@@ -332,6 +345,19 @@ create_shader(struct gl_context *ctx, GLenum type)
 }
 
 
+static GLuint
+create_shader_err(struct gl_context *ctx, GLenum type, const char *caller)
+{
+   if (!_mesa_validate_shader_target(ctx, type)) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "%s(%s)",
+                  caller, _mesa_enum_to_string(type));
+      return 0;
+   }
+
+   return create_shader(ctx, type);
+}
+
+
 static GLuint
 create_shader_program(struct gl_context *ctx)
 {
@@ -403,16 +429,21 @@ delete_shader(struct gl_context *ctx, GLuint shader)
 }
 
 
-static void
-detach_shader(struct gl_context *ctx, GLuint program, GLuint shader)
+static ALWAYS_INLINE void
+detach_shader(struct gl_context *ctx, GLuint program, GLuint shader,
+              bool no_error)
 {
    struct gl_shader_program *shProg;
    GLuint n;
    GLuint i, j;
 
-   shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader");
-   if (!shProg)
-      return;
+   if (!no_error) {
+      shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader");
+      if (!shProg)
+         return;
+   } else {
+      shProg = _mesa_lookup_shader_program(ctx, program);
+   }
 
    n = shProg->NumShaders;
 
@@ -443,7 +474,7 @@ detach_shader(struct gl_context *ctx, GLuint program, GLuint shader)
          shProg->Shaders = newList;
          shProg->NumShaders = n - 1;
 
-#ifdef DEBUG
+#ifndef NDEBUG
          /* sanity check - make sure the new list's entries are sensible */
          for (j = 0; j < shProg->NumShaders; j++) {
             assert(shProg->Shaders[j]->Stage == MESA_SHADER_VERTEX ||
@@ -460,7 +491,7 @@ detach_shader(struct gl_context *ctx, GLuint program, GLuint shader)
    }
 
    /* not found */
-   {
+   if (!no_error) {
       GLenum err;
       if (is_shader(ctx, shader) || is_program(ctx, shader))
          err = GL_INVALID_OPERATION;
@@ -472,12 +503,28 @@ detach_shader(struct gl_context *ctx, GLuint program, GLuint shader)
 }
 
 
+static void
+detach_shader_error(struct gl_context *ctx, GLuint program, GLuint shader)
+{
+   detach_shader(ctx, program, shader, false);
+}
+
+
+static void
+detach_shader_no_error(struct gl_context *ctx, GLuint program, GLuint shader)
+{
+   detach_shader(ctx, program, shader, true);
+}
+
+
 /**
  * Return list of shaders attached to shader program.
+ * \param objOut  returns GLuint ids
+ * \param handleOut  returns GLhandleARB handles
  */
 static void
 get_attached_shaders(struct gl_context *ctx, GLuint program, GLsizei maxCount,
-                     GLsizei *count, GLuint *obj)
+                     GLsizei *countOut, GLuint *objOut, GLhandleARB *handleOut)
 {
    struct gl_shader_program *shProg;
 
@@ -492,14 +539,20 @@ get_attached_shaders(struct gl_context *ctx, GLuint program, GLsizei maxCount,
    if (shProg) {
       GLuint i;
       for (i = 0; i < (GLuint) maxCount && i < shProg->NumShaders; i++) {
-         obj[i] = shProg->Shaders[i]->Name;
+         if (objOut) {
+            objOut[i] = shProg->Shaders[i]->Name;
+         }
+
+         if (handleOut) {
+            handleOut[i] = (GLhandleARB) shProg->Shaders[i]->Name;
+         }
+      }
+      if (countOut) {
+         *countOut = i;
       }
-      if (count)
-         *count = i;
    }
 }
 
-
 /**
  * glGetHandleARB() - return ID/name of currently bound shader program.
  */
@@ -594,6 +647,13 @@ check_tes_query(struct gl_context *ctx, const struct gl_shader_program *shProg)
    return false;
 }
 
+/**
+ * Return the length of a string, or 0 if the pointer passed in is NULL
+ */
+static size_t strlen_or_zero(const char *s)
+{
+   return s ? strlen(s) : 0;
+}
 
 /**
  * glGetProgramiv() - get shader program state.
@@ -617,7 +677,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
    /* True if geometry shaders (of the form that was adopted into GLSL 1.50
     * and GL 3.2) are available in this context
     */
-   const bool has_core_gs = _mesa_has_geometry_shaders(ctx);
+   const bool has_gs = _mesa_has_geometry_shaders(ctx);
    const bool has_tess = _mesa_has_tessellation(ctx);
 
    /* Are uniform buffer objects available in this context?
@@ -636,8 +696,14 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
    case GL_DELETE_STATUS:
       *params = shProg->DeletePending;
       return;
+   case GL_COMPLETION_STATUS_ARB:
+      if (ctx->Driver.GetShaderProgramCompletionStatus)
+         *params = ctx->Driver.GetShaderProgramCompletionStatus(ctx, shProg);
+      else
+         *params = GL_TRUE;
+      return;
    case GL_LINK_STATUS:
-      *params = shProg->data->LinkStatus;
+      *params = shProg->data->LinkStatus ? GL_TRUE : GL_FALSE;
       return;
    case GL_VALIDATE_STATUS:
       *params = shProg->data->Validated;
@@ -675,11 +741,23 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
          if (shProg->data->UniformStorage[i].is_shader_storage)
             continue;
 
+         /* From ARB_gl_spirv spec:
+          *
+          *   "If pname is ACTIVE_UNIFORM_MAX_LENGTH, the length of the
+          *    longest active uniform name, including a null terminator, is
+          *    returned. If no active uniforms exist, zero is returned. If no
+          *    name reflection information is available, one is returned."
+          *
+          * We are setting 0 here, as below it will add 1 for the NUL character.
+          */
+         const GLint base_len =
+            strlen_or_zero(shProg->data->UniformStorage[i].name);
+
         /* Add one for the terminating NUL character for a non-array, and
          * 4 for the "[0]" and the NUL for an array.
          */
-         const GLint len = strlen(shProg->data->UniformStorage[i].name) + 1 +
-             ((shProg->data->UniformStorage[i].array_elements != 0) ? 3 : 0);
+         const GLint len = base_len + 1 +
+            ((shProg->data->UniformStorage[i].array_elements != 0) ? 3 : 0);
 
         if (len > max_len)
            max_len = len;
@@ -691,19 +769,48 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
    case GL_TRANSFORM_FEEDBACK_VARYINGS:
       if (!has_xfb)
          break;
-      *params = shProg->TransformFeedback.NumVarying;
+
+      /* Check first if there are transform feedback varyings specified in the
+       * shader (ARB_enhanced_layouts). If there isn't any, return the number of
+       * varyings specified using the API.
+       */
+      if (shProg->last_vert_prog &&
+          shProg->last_vert_prog->sh.LinkedTransformFeedback->NumVarying > 0)
+         *params =
+            shProg->last_vert_prog->sh.LinkedTransformFeedback->NumVarying;
+      else
+         *params = shProg->TransformFeedback.NumVarying;
       return;
    case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: {
       unsigned i;
       GLint max_len = 0;
+      bool in_shader_varyings;
+      int num_varying;
+
       if (!has_xfb)
          break;
 
-      for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
-         /* Add one for the terminating NUL character.
+      /* Check first if there are transform feedback varyings specified in the
+       * shader (ARB_enhanced_layouts). If there isn't any, use the ones
+       * specified using the API.
+       */
+      in_shader_varyings = shProg->last_vert_prog &&
+         shProg->last_vert_prog->sh.LinkedTransformFeedback->NumVarying > 0;
+
+      num_varying = in_shader_varyings ?
+         shProg->last_vert_prog->sh.LinkedTransformFeedback->NumVarying :
+         shProg->TransformFeedback.NumVarying;
+
+      for (i = 0; i < num_varying; i++) {
+         const char *name = in_shader_varyings ?
+            shProg->last_vert_prog->sh.LinkedTransformFeedback->Varyings[i].Name
+            : shProg->TransformFeedback.VaryingNames[i];
+
+         /* Add one for the terminating NUL character. We have to use
+          * strlen_or_zero, as for shaders constructed from SPIR-V binaries,
+          * it is possible that no name reflection information is available.
           */
-         const GLint len =
-            strlen(shProg->TransformFeedback.VaryingNames[i]) + 1;
+         const GLint len = strlen_or_zero(name) + 1;
 
          if (len > max_len)
             max_len = len;
@@ -718,35 +825,37 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
       *params = shProg->TransformFeedback.BufferMode;
       return;
    case GL_GEOMETRY_VERTICES_OUT:
-      if (!has_core_gs)
+      if (!has_gs)
          break;
       if (check_gs_query(ctx, shProg)) {
          *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
-            info.Geom.VerticesOut;
+            Program->info.gs.vertices_out;
       }
       return;
    case GL_GEOMETRY_SHADER_INVOCATIONS:
-      if (!has_core_gs || !ctx->Extensions.ARB_gpu_shader5)
+      if (!has_gs ||
+          (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_gpu_shader5)) {
          break;
+      }
       if (check_gs_query(ctx, shProg)) {
          *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
-            info.Geom.Invocations;
+            Program->info.gs.invocations;
       }
       return;
    case GL_GEOMETRY_INPUT_TYPE:
-      if (!has_core_gs)
+      if (!has_gs)
          break;
       if (check_gs_query(ctx, shProg)) {
          *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
-            info.Geom.InputType;
+            Program->info.gs.input_primitive;
       }
       return;
    case GL_GEOMETRY_OUTPUT_TYPE:
-      if (!has_core_gs)
+      if (!has_gs)
          break;
       if (check_gs_query(ctx, shProg)) {
          *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
-            info.Geom.OutputType;
+            Program->info.gs.output_primitive;
       }
       return;
    case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: {
@@ -757,9 +866,16 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
          break;
 
       for (i = 0; i < shProg->data->NumUniformBlocks; i++) {
-        /* Add one for the terminating NUL character.
+        /* Add one for the terminating NUL character. Name can be NULL, in
+          * that case, from ARB_gl_spirv:
+          *   "If pname is ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, the length of
+          *    the longest active uniform block name, including the null
+          *    terminator, is returned. If no active uniform blocks exist,
+          *    zero is returned. If no name reflection information is
+          *    available, one is returned."
          */
-         const GLint len = strlen(shProg->data->UniformBlocks[i].Name) + 1;
+         const GLint len =
+            strlen_or_zero(shProg->data->UniformBlocks[i].Name) + 1;
 
         if (len > max_len)
            max_len = len;
@@ -784,10 +900,14 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
       if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
          break;
 
-      *params = shProg->BinaryRetreivableHint;
+      *params = shProg->BinaryRetrievableHint;
       return;
    case GL_PROGRAM_BINARY_LENGTH:
-      *params = 0;
+      if (ctx->Const.NumProgramBinaryFormats == 0 || !shProg->data->LinkStatus) {
+         *params = 0;
+      } else {
+         _mesa_get_program_binary_length(ctx, shProg, params);
+      }
       return;
    case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
       if (!ctx->Extensions.ARB_shader_atomic_counters)
@@ -810,12 +930,13 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
          return;
       }
       for (i = 0; i < 3; i++)
-         params[i] = shProg->Comp.LocalSize[i];
+         params[i] = shProg->_LinkedShaders[MESA_SHADER_COMPUTE]->
+            Program->info.cs.local_size[i];
       return;
    }
    case GL_PROGRAM_SEPARABLE:
       /* If the program has not been linked, return initial value 0. */
-      *params = (shProg->data->LinkStatus == GL_FALSE) ? 0 : shProg->SeparateShader;
+      *params = (shProg->data->LinkStatus == LINKING_FAILURE) ? 0 : shProg->SeparateShader;
       return;
 
    /* ARB_tessellation_shader */
@@ -824,7 +945,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
          break;
       if (check_tcs_query(ctx, shProg)) {
          *params = shProg->_LinkedShaders[MESA_SHADER_TESS_CTRL]->
-            info.TessCtrl.VerticesOut;
+            Program->info.tess.tcs_vertices_out;
       }
       return;
    case GL_TESS_GEN_MODE:
@@ -832,15 +953,29 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
          break;
       if (check_tes_query(ctx, shProg)) {
          *params = shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]->
-            info.TessEval.PrimitiveMode;
+            Program->info.tess.primitive_mode;
       }
       return;
    case GL_TESS_GEN_SPACING:
       if (!has_tess)
          break;
       if (check_tes_query(ctx, shProg)) {
-         *params = shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]->
-            info.TessEval.Spacing;
+         const struct gl_linked_shader *tes =
+            shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL];
+         switch (tes->Program->info.tess.spacing) {
+         case TESS_SPACING_EQUAL:
+            *params = GL_EQUAL;
+            break;
+         case TESS_SPACING_FRACTIONAL_ODD:
+            *params = GL_FRACTIONAL_ODD;
+            break;
+         case TESS_SPACING_FRACTIONAL_EVEN:
+            *params = GL_FRACTIONAL_EVEN;
+            break;
+         case TESS_SPACING_UNSPECIFIED:
+            *params = 0;
+            break;
+         }
       }
       return;
    case GL_TESS_GEN_VERTEX_ORDER:
@@ -848,7 +983,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
          break;
       if (check_tes_query(ctx, shProg)) {
          *params = shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]->
-            info.TessEval.VertexOrder;
+            Program->info.tess.ccw ? GL_CCW : GL_CW;
          }
       return;
    case GL_TESS_GEN_POINT_MODE:
@@ -856,7 +991,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
          break;
       if (check_tes_query(ctx, shProg)) {
          *params = shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]->
-            info.TessEval.PointMode;
+            Program->info.tess.point_mode ? GL_TRUE : GL_FALSE;
       }
       return;
    default:
@@ -888,8 +1023,12 @@ get_shaderiv(struct gl_context *ctx, GLuint name, GLenum pname, GLint *params)
    case GL_DELETE_STATUS:
       *params = shader->DeletePending;
       break;
+   case GL_COMPLETION_STATUS_ARB:
+      /* _mesa_glsl_compile_shader is not offloaded to other threads. */
+      *params = GL_TRUE;
+      return;
    case GL_COMPILE_STATUS:
-      *params = shader->CompileStatus;
+      *params = shader->CompileStatus ? GL_TRUE : GL_FALSE;
       break;
    case GL_INFO_LOG_LENGTH:
       *params = (shader->InfoLog && shader->InfoLog[0] != '\0') ?
@@ -898,6 +1037,9 @@ get_shaderiv(struct gl_context *ctx, GLuint name, GLenum pname, GLint *params)
    case GL_SHADER_SOURCE_LENGTH:
       *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
       break;
+   case GL_SPIR_V_BINARY_ARB:
+      *params = (shader->spirv_data != NULL);
+      break;
    default:
       _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
       return;
@@ -985,18 +1127,45 @@ get_shader_source(struct gl_context *ctx, GLuint shader, GLsizei maxLength,
  * glShaderSource[ARB].
  */
 static void
-shader_source(struct gl_shader *sh, const GLchar *source)
+set_shader_source(struct gl_shader *sh, const GLchar *source)
 {
    assert(sh);
 
-   /* free old shader source string and install new one */
-   free((void *)sh->Source);
-   sh->Source = source;
+   /* The GL_ARB_gl_spirv spec adds the following to the end of the description
+    * of ShaderSource:
+    *
+    *   "If <shader> was previously associated with a SPIR-V module (via the
+    *    ShaderBinary command), that association is broken. Upon successful
+    *    completion of this command the SPIR_V_BINARY_ARB state of <shader>
+    *    is set to FALSE."
+    */
+   _mesa_shader_spirv_data_reference(&sh->spirv_data, NULL);
+
+   if (sh->CompileStatus == COMPILE_SKIPPED && !sh->FallbackSource) {
+      /* If shader was previously compiled back-up the source in case of cache
+       * fallback.
+       */
+      sh->FallbackSource = sh->Source;
+      sh->Source = source;
+   } else {
+      /* free old shader source string and install new one */
+      free((void *)sh->Source);
+      sh->Source = source;
+   }
+
 #ifdef DEBUG
    sh->SourceChecksum = util_hash_crc32(sh->Source, strlen(sh->Source));
 #endif
 }
 
+static void
+ensure_builtin_types(struct gl_context *ctx)
+{
+   if (!ctx->shader_builtin_ref) {
+      _mesa_glsl_builtin_functions_init_or_ref();
+      ctx->shader_builtin_ref = true;
+   }
+}
 
 /**
  * Compile a shader.
@@ -1007,11 +1176,23 @@ _mesa_compile_shader(struct gl_context *ctx, struct gl_shader *sh)
    if (!sh)
       return;
 
+   /* The GL_ARB_gl_spirv spec says:
+    *
+    *    "Add a new error for the CompileShader command:
+    *
+    *      An INVALID_OPERATION error is generated if the SPIR_V_BINARY_ARB
+    *      state of <shader> is TRUE."
+    */
+   if (sh->spirv_data) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glCompileShader(SPIR-V)");
+      return;
+   }
+
    if (!sh->Source) {
       /* If the user called glCompileShader without first calling
        * glShaderSource, we should fail to compile, but not raise a GL_ERROR.
        */
-      sh->CompileStatus = GL_FALSE;
+      sh->CompileStatus = COMPILE_FAILURE;
    } else {
       if (ctx->_Shader->Flags & GLSL_DUMP) {
          _mesa_log("GLSL source for %s shader %d:\n",
@@ -1019,10 +1200,12 @@ _mesa_compile_shader(struct gl_context *ctx, struct gl_shader *sh)
          _mesa_log("%s\n", sh->Source);
       }
 
+      ensure_builtin_types(ctx);
+
       /* this call will set the shader->CompileStatus field to indicate if
        * compilation was successful.
        */
-      _mesa_glsl_compile_shader(ctx, sh, false, false);
+      _mesa_glsl_compile_shader(ctx, sh, false, false, false);
 
       if (ctx->_Shader->Flags & GLSL_LOG) {
          _mesa_write_shader_to_file(sh);
@@ -1067,34 +1250,86 @@ _mesa_compile_shader(struct gl_context *ctx, struct gl_shader *sh)
 /**
  * Link a program's shaders.
  */
-void
-_mesa_link_program(struct gl_context *ctx, struct gl_shader_program *shProg)
+static ALWAYS_INLINE void
+link_program(struct gl_context *ctx, struct gl_shader_program *shProg,
+             bool no_error)
 {
    if (!shProg)
       return;
 
-   /* From the ARB_transform_feedback2 specification:
-    * "The error INVALID_OPERATION is generated by LinkProgram if <program> is
-    *  the name of a program being used by one or more transform feedback
-    *  objects, even if the objects are not currently bound or are paused."
-    */
-   if (_mesa_transform_feedback_is_using_program(ctx, shProg)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glLinkProgram(transform feedback is using the program)");
-      return;
+   if (!no_error) {
+      /* From the ARB_transform_feedback2 specification:
+       * "The error INVALID_OPERATION is generated by LinkProgram if <program>
+       * is the name of a program being used by one or more transform feedback
+       * objects, even if the objects are not currently bound or are paused."
+       */
+      if (_mesa_transform_feedback_is_using_program(ctx, shProg)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glLinkProgram(transform feedback is using the program)");
+         return;
+      }
+   }
+
+   unsigned programs_in_use = 0;
+   if (ctx->_Shader)
+      for (unsigned stage = 0; stage < MESA_SHADER_STAGES; stage++) {
+         if (ctx->_Shader->CurrentProgram[stage] &&
+             ctx->_Shader->CurrentProgram[stage]->Id == shProg->Name) {
+            programs_in_use |= 1 << stage;
+         }
    }
 
-   FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+   ensure_builtin_types(ctx);
 
+   FLUSH_VERTICES(ctx, 0);
    _mesa_glsl_link_shader(ctx, shProg);
 
+   /* From section 7.3 (Program Objects) of the OpenGL 4.5 spec:
+    *
+    *    "If LinkProgram or ProgramBinary successfully re-links a program
+    *     object that is active for any shader stage, then the newly generated
+    *     executable code will be installed as part of the current rendering
+    *     state for all shader stages where the program is active.
+    *     Additionally, the newly generated executable code is made part of
+    *     the state of any program pipeline for all stages where the program
+    *     is attached."
+    */
+   if (shProg->data->LinkStatus && programs_in_use) {
+      while (programs_in_use) {
+         const int stage = u_bit_scan(&programs_in_use);
+
+         struct gl_program *prog = NULL;
+         if (shProg->_LinkedShaders[stage])
+            prog = shProg->_LinkedShaders[stage]->Program;
+
+         _mesa_use_program(ctx, stage, shProg, prog, ctx->_Shader);
+      }
+   }
+
    /* Capture .shader_test files. */
    const char *capture_path = _mesa_get_shader_capture_path();
    if (shProg->Name != 0 && shProg->Name != ~0 && capture_path != NULL) {
-      FILE *file;
-      char *filename = ralloc_asprintf(NULL, "%s/%u.shader_test",
+      /* Find an unused filename. */
+      FILE *file = NULL;
+      char *filename = NULL;
+      for (unsigned i = 0;; i++) {
+         if (i) {
+            filename = ralloc_asprintf(NULL, "%s/%u-%u.shader_test",
+                                       capture_path, shProg->Name, i);
+         } else {
+            filename = ralloc_asprintf(NULL, "%s/%u.shader_test",
                                        capture_path, shProg->Name);
-      file = fopen(filename, "w");
+         }
+         file = os_file_create_unique(filename, 0644);
+         if (file)
+            break;
+         /* If we are failing for another reason than "this filename already
+          * exists", we are likely to fail again with another filename, so
+          * let's just give up */
+         if (errno != EEXIST)
+            break;
+         ralloc_free(filename);
+      }
       if (file) {
          fprintf(file, "[require]\nGLSL%s >= %u.%02u\n",
                  shProg->IsES ? " ES" : "",
@@ -1116,12 +1351,16 @@ _mesa_link_program(struct gl_context *ctx, struct gl_shader_program *shProg)
       ralloc_free(filename);
    }
 
-   if (shProg->data->LinkStatus == GL_FALSE &&
+   if (shProg->data->LinkStatus == LINKING_FAILURE &&
        (ctx->_Shader->Flags & GLSL_REPORT_ERRORS)) {
       _mesa_debug(ctx, "Error linking program %u:\n%s\n",
                   shProg->Name, shProg->data->InfoLog);
    }
 
+   _mesa_update_vertex_processing_mode(ctx);
+
+   shProg->BinaryRetrievableHint = shProg->BinaryRetrievableHintPending;
+
    /* debug code */
    if (0) {
       GLuint i;
@@ -1139,6 +1378,27 @@ _mesa_link_program(struct gl_context *ctx, struct gl_shader_program *shProg)
 }
 
 
+static void
+link_program_error(struct gl_context *ctx, struct gl_shader_program *shProg)
+{
+   link_program(ctx, shProg, false);
+}
+
+
+static void
+link_program_no_error(struct gl_context *ctx, struct gl_shader_program *shProg)
+{
+   link_program(ctx, shProg, true);
+}
+
+
+void
+_mesa_link_program(struct gl_context *ctx, struct gl_shader_program *shProg)
+{
+   link_program_error(ctx, shProg);
+}
+
+
 /**
  * Print basic shader info (for debug).
  */
@@ -1197,62 +1457,19 @@ _mesa_active_program(struct gl_context *ctx, struct gl_shader_program *shProg,
 }
 
 
-static void
-use_shader_program(struct gl_context *ctx, gl_shader_stage stage,
-                   struct gl_shader_program *shProg,
-                   struct gl_pipeline_object *shTarget)
-{
-   struct gl_shader_program **target;
-
-   target = &shTarget->CurrentProgram[stage];
-   if ((shProg != NULL) && (shProg->_LinkedShaders[stage] == NULL))
-      shProg = NULL;
-
-   if (shProg)
-      _mesa_shader_program_init_subroutine_defaults(ctx, shProg);
-
-   if (*target != shProg) {
-      /* Program is current, flush it */
-      if (shTarget == ctx->_Shader) {
-         FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
-      }
-
-      /* If the shader is also bound as the current rendering shader, unbind
-       * it from that binding point as well.  This ensures that the correct
-       * semantics of glDeleteProgram are maintained.
-       */
-      switch (stage) {
-      case MESA_SHADER_VERTEX:
-      case MESA_SHADER_TESS_CTRL:
-      case MESA_SHADER_TESS_EVAL:
-      case MESA_SHADER_GEOMETRY:
-      case MESA_SHADER_COMPUTE:
-         /* Empty for now. */
-         break;
-      case MESA_SHADER_FRAGMENT:
-         if (*target == ctx->_Shader->_CurrentFragmentProgram) {
-           _mesa_reference_shader_program(ctx,
-                                           &ctx->_Shader->_CurrentFragmentProgram,
-                                          NULL);
-        }
-        break;
-      }
-
-      _mesa_reference_shader_program(ctx, target, shProg);
-      return;
-   }
-}
-
-
 /**
  * Use the named shader program for subsequent rendering.
  */
 void
-_mesa_use_program(struct gl_context *ctx, struct gl_shader_program *shProg)
+_mesa_use_shader_program(struct gl_context *ctx,
+                         struct gl_shader_program *shProg)
 {
-   int i;
-   for (i = 0; i < MESA_SHADER_STAGES; i++)
-      use_shader_program(ctx, i, shProg, &ctx->Shader);
+   for (int i = 0; i < MESA_SHADER_STAGES; i++) {
+      struct gl_program *new_prog = NULL;
+      if (shProg && shProg->_LinkedShaders[i])
+         new_prog = shProg->_LinkedShaders[i]->Program;
+      _mesa_use_program(ctx, i, shProg, new_prog, &ctx->Shader);
+   }
    _mesa_active_program(ctx, shProg, "glUseProgram");
 }
 
@@ -1321,12 +1538,27 @@ validate_program(struct gl_context *ctx, GLuint program)
 }
 
 
+void GLAPIENTRY
+_mesa_AttachObjectARB_no_error(GLhandleARB program, GLhandleARB shader)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   attach_shader_no_error(ctx, program, shader);
+}
+
 
 void GLAPIENTRY
 _mesa_AttachObjectARB(GLhandleARB program, GLhandleARB shader)
 {
    GET_CURRENT_CONTEXT(ctx);
-   attach_shader(ctx, program, shader);
+   attach_shader_err(ctx, program, shader, "glAttachObjectARB");
+}
+
+
+void GLAPIENTRY
+_mesa_AttachShader_no_error(GLuint program, GLuint shader)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   attach_shader_no_error(ctx, program, shader);
 }
 
 
@@ -1334,7 +1566,7 @@ void GLAPIENTRY
 _mesa_AttachShader(GLuint program, GLuint shader)
 {
    GET_CURRENT_CONTEXT(ctx);
-   attach_shader(ctx, program, shader);
+   attach_shader_err(ctx, program, shader, "glAttachShader");
 }
 
 
@@ -1349,12 +1581,30 @@ _mesa_CompileShader(GLuint shaderObj)
 }
 
 
+GLuint GLAPIENTRY
+_mesa_CreateShader_no_error(GLenum type)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   return create_shader(ctx, type);
+}
+
+
 GLuint GLAPIENTRY
 _mesa_CreateShader(GLenum type)
 {
    GET_CURRENT_CONTEXT(ctx);
+
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glCreateShader %s\n", _mesa_enum_to_string(type));
+
+   return create_shader_err(ctx, type, "glCreateShader");
+}
+
+
+GLhandleARB GLAPIENTRY
+_mesa_CreateShaderObjectARB_no_error(GLenum type)
+{
+   GET_CURRENT_CONTEXT(ctx);
    return create_shader(ctx, type);
 }
 
@@ -1363,7 +1613,7 @@ GLhandleARB GLAPIENTRY
 _mesa_CreateShaderObjectARB(GLenum type)
 {
    GET_CURRENT_CONTEXT(ctx);
-   return create_shader(ctx, type);
+   return create_shader_err(ctx, type, "glCreateShaderObjectARB");
 }
 
 
@@ -1431,11 +1681,27 @@ _mesa_DeleteShader(GLuint name)
 }
 
 
+void GLAPIENTRY
+_mesa_DetachObjectARB_no_error(GLhandleARB program, GLhandleARB shader)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   detach_shader_no_error(ctx, program, shader);
+}
+
+
 void GLAPIENTRY
 _mesa_DetachObjectARB(GLhandleARB program, GLhandleARB shader)
 {
    GET_CURRENT_CONTEXT(ctx);
-   detach_shader(ctx, program, shader);
+   detach_shader_error(ctx, program, shader);
+}
+
+
+void GLAPIENTRY
+_mesa_DetachShader_no_error(GLuint program, GLuint shader)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   detach_shader_no_error(ctx, program, shader);
 }
 
 
@@ -1443,7 +1709,7 @@ void GLAPIENTRY
 _mesa_DetachShader(GLuint program, GLuint shader)
 {
    GET_CURRENT_CONTEXT(ctx);
-   detach_shader(ctx, program, shader);
+   detach_shader_error(ctx, program, shader);
 }
 
 
@@ -1452,7 +1718,7 @@ _mesa_GetAttachedObjectsARB(GLhandleARB container, GLsizei maxCount,
                             GLsizei * count, GLhandleARB * obj)
 {
    GET_CURRENT_CONTEXT(ctx);
-   get_attached_shaders(ctx, container, maxCount, count, obj);
+   get_attached_shaders(ctx, (GLuint)container, maxCount, count, NULL, obj);
 }
 
 
@@ -1461,7 +1727,7 @@ _mesa_GetAttachedShaders(GLuint program, GLsizei maxCount,
                          GLsizei *count, GLuint *obj)
 {
    GET_CURRENT_CONTEXT(ctx);
-   get_attached_shaders(ctx, program, maxCount, count, obj);
+   get_attached_shaders(ctx, program, maxCount, count, obj, NULL);
 }
 
 
@@ -1586,17 +1852,31 @@ _mesa_IsShader(GLuint name)
 }
 
 
+void GLAPIENTRY
+_mesa_LinkProgram_no_error(GLuint programObj)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   struct gl_shader_program *shProg =
+      _mesa_lookup_shader_program(ctx, programObj);
+   link_program_no_error(ctx, shProg);
+}
+
+
 void GLAPIENTRY
 _mesa_LinkProgram(GLuint programObj)
 {
    GET_CURRENT_CONTEXT(ctx);
+
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glLinkProgram %u\n", programObj);
-   _mesa_link_program(ctx, _mesa_lookup_shader_program_err(ctx, programObj,
-                                                           "glLinkProgram"));
+
+   struct gl_shader_program *shProg =
+      _mesa_lookup_shader_program_err(ctx, programObj, "glLinkProgram");
+   link_program_error(ctx, shProg);
 }
 
-#if defined(HAVE_SHA1)
+#ifdef ENABLE_SHADER_CACHE
 /**
  * Generate a SHA-1 hash value string for given source string.
  */
@@ -1613,6 +1893,7 @@ generate_sha1(const char *source, char sha_str[64])
  * following format:
  *
  * <path>/<stage prefix>_<CHECKSUM>.glsl
+ * <path>/<stage prefix>_<CHECKSUM>.arb
  */
 static char *
 construct_name(const gl_shader_stage stage, const char *source,
@@ -1623,15 +1904,17 @@ construct_name(const gl_shader_stage stage, const char *source,
       "VS", "TC", "TE", "GS", "FS", "CS",
    };
 
+   const char *format = strncmp(source, "!!ARB", 5) ? "glsl" : "arb";
+
    generate_sha1(source, sha);
-   return ralloc_asprintf(NULL, "%s/%s_%s.glsl", path, types[stage], sha);
+   return ralloc_asprintf(NULL, "%s/%s_%s.%s", path, types[stage], sha, format);
 }
 
 /**
  * Write given shader source to a file in MESA_SHADER_DUMP_PATH.
  */
-static void
-dump_shader(const gl_shader_stage stage, const char *source)
+void
+_mesa_dump_shader_source(const gl_shader_stage stage, const char *source)
 {
    static bool path_exists = true;
    char *dump_path;
@@ -1664,8 +1947,8 @@ dump_shader(const gl_shader_stage stage, const char *source)
  * Read shader source code from a file.
  * Useful for debugging to override an app's shader.
  */
-static GLcharARB *
-read_shader(const gl_shader_stage stage, const char *source)
+GLcharARB *
+_mesa_read_shader_source(const gl_shader_stage stage, const char *source)
 {
    char *read_path;
    static bool path_exists = true;
@@ -1707,34 +1990,34 @@ read_shader(const gl_shader_stage stage, const char *source)
 
    return buffer;
 }
-#endif /* HAVE_SHA1 */
+
+#endif /* ENABLE_SHADER_CACHE */
 
 /**
  * Called via glShaderSource() and glShaderSourceARB() API functions.
  * Basically, concatenate the source code strings into one long string
  * and pass it to _mesa_shader_source().
  */
-void GLAPIENTRY
-_mesa_ShaderSource(GLuint shaderObj, GLsizei count,
-                   const GLchar * const * string, const GLint * length)
+static ALWAYS_INLINE void
+shader_source(struct gl_context *ctx, GLuint shaderObj, GLsizei count,
+              const GLchar *const *string, const GLint *length, bool no_error)
 {
-   GET_CURRENT_CONTEXT(ctx);
    GLint *offsets;
    GLsizei i, totalLength;
    GLcharARB *source;
    struct gl_shader *sh;
 
-#if defined(HAVE_SHA1)
-   GLcharARB *replacement;
-#endif /* HAVE_SHA1 */
-
-   sh = _mesa_lookup_shader_err(ctx, shaderObj, "glShaderSourceARB");
-   if (!sh)
-      return;
+   if (!no_error) {
+      sh = _mesa_lookup_shader_err(ctx, shaderObj, "glShaderSourceARB");
+      if (!sh)
+         return;
 
-   if (string == NULL) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSourceARB");
-      return;
+      if (string == NULL) {
+         _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSourceARB");
+         return;
+      }
+   } else {
+      sh = _mesa_lookup_shader(ctx, shaderObj);
    }
 
    /*
@@ -1748,7 +2031,7 @@ _mesa_ShaderSource(GLuint shaderObj, GLsizei count,
    }
 
    for (i = 0; i < count; i++) {
-      if (string[i] == NULL) {
+      if (!no_error && string[i] == NULL) {
          free((GLvoid *) offsets);
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "glShaderSourceARB(null string)");
@@ -1783,59 +2066,83 @@ _mesa_ShaderSource(GLuint shaderObj, GLsizei count,
    source[totalLength - 1] = '\0';
    source[totalLength - 2] = '\0';
 
-#if defined(HAVE_SHA1)
+#ifdef ENABLE_SHADER_CACHE
+   GLcharARB *replacement;
+
    /* Dump original shader source to MESA_SHADER_DUMP_PATH and replace
     * if corresponding entry found from MESA_SHADER_READ_PATH.
     */
-   dump_shader(sh->Stage, source);
+   _mesa_dump_shader_source(sh->Stage, source);
 
-   replacement = read_shader(sh->Stage, source);
+   replacement = _mesa_read_shader_source(sh->Stage, source);
    if (replacement) {
       free(source);
       source = replacement;
    }
-#endif /* HAVE_SHA1 */
+#endif /* ENABLE_SHADER_CACHE */
 
-   shader_source(sh, source);
+   set_shader_source(sh, source);
 
    free(offsets);
 }
 
 
 void GLAPIENTRY
-_mesa_UseProgram(GLuint program)
+_mesa_ShaderSource_no_error(GLuint shaderObj, GLsizei count,
+                            const GLchar *const *string, const GLint *length)
 {
    GET_CURRENT_CONTEXT(ctx);
-   struct gl_shader_program *shProg;
+   shader_source(ctx, shaderObj, count, string, length, true);
+}
+
+
+void GLAPIENTRY
+_mesa_ShaderSource(GLuint shaderObj, GLsizei count,
+                   const GLchar *const *string, const GLint *length)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   shader_source(ctx, shaderObj, count, string, length, false);
+}
+
+
+static ALWAYS_INLINE void
+use_program(GLuint program, bool no_error)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_shader_program *shProg = NULL;
 
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glUseProgram %u\n", program);
 
-   if (_mesa_is_xfb_active_and_unpaused(ctx)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glUseProgram(transform feedback active)");
-      return;
-   }
-
-   if (program) {
-      shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
-      if (!shProg) {
-         return;
+   if (no_error) {
+      if (program) {
+         shProg = _mesa_lookup_shader_program(ctx, program);
       }
-      if (!shProg->data->LinkStatus) {
+   } else {
+      if (_mesa_is_xfb_active_and_unpaused(ctx)) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "glUseProgram(program %u not linked)", program);
+                     "glUseProgram(transform feedback active)");
          return;
       }
 
-      /* debug code */
-      if (ctx->_Shader->Flags & GLSL_USE_PROG) {
-         print_shader_info(shProg);
+      if (program) {
+         shProg =
+            _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
+         if (!shProg)
+            return;
+
+         if (!shProg->data->LinkStatus) {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glUseProgram(program %u not linked)", program);
+            return;
+         }
+
+         /* debug code */
+         if (ctx->_Shader->Flags & GLSL_USE_PROG) {
+            print_shader_info(shProg);
+         }
       }
    }
-   else {
-      shProg = NULL;
-   }
 
    /* The ARB_separate_shader_object spec says:
     *
@@ -1846,21 +2153,41 @@ _mesa_UseProgram(GLuint program)
     *     object (section 2.14.PPO), the program bound to the appropriate
     *     stage of the pipeline object is considered current."
     */
-   if (program) {
+   if (shProg) {
       /* Attach shader state to the binding point */
       _mesa_reference_pipeline_object(ctx, &ctx->_Shader, &ctx->Shader);
       /* Update the program */
-      _mesa_use_program(ctx, shProg);
+      _mesa_use_shader_program(ctx, shProg);
    } else {
       /* Must be done first: detach the progam */
-      _mesa_use_program(ctx, shProg);
+      _mesa_use_shader_program(ctx, shProg);
       /* Unattach shader_state binding point */
-      _mesa_reference_pipeline_object(ctx, &ctx->_Shader, ctx->Pipeline.Default);
+      _mesa_reference_pipeline_object(ctx, &ctx->_Shader,
+                                      ctx->Pipeline.Default);
       /* If a pipeline was bound, rebind it */
       if (ctx->Pipeline.Current) {
-         _mesa_BindProgramPipeline(ctx->Pipeline.Current->Name);
+         if (no_error)
+            _mesa_BindProgramPipeline_no_error(ctx->Pipeline.Current->Name);
+         else
+            _mesa_BindProgramPipeline(ctx->Pipeline.Current->Name);
       }
    }
+
+   _mesa_update_vertex_processing_mode(ctx);
+}
+
+
+void GLAPIENTRY
+_mesa_UseProgram_no_error(GLuint program)
+{
+   use_program(program, true);
+}
+
+
+void GLAPIENTRY
+_mesa_UseProgram(GLuint program)
+{
+   use_program(program, false);
 }
 
 
@@ -1933,7 +2260,12 @@ _mesa_GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype,
 void GLAPIENTRY
 _mesa_ReleaseShaderCompiler(void)
 {
-   _mesa_destroy_shader_compiler_caches();
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (ctx->shader_builtin_ref) {
+      _mesa_glsl_builtin_functions_decref();
+      ctx->shader_builtin_ref = false;
+   }
 }
 
 
@@ -1945,9 +2277,7 @@ _mesa_ShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat,
                    const void* binary, GLint length)
 {
    GET_CURRENT_CONTEXT(ctx);
-   (void) shaders;
-   (void) binaryformat;
-   (void) binary;
+   struct gl_shader **sh;
 
    /* Page 68, section 7.2 'Shader Binaries" of the of the OpenGL ES 3.1, and
     * page 88 of the OpenGL 4.5 specs state:
@@ -1961,6 +2291,37 @@ _mesa_ShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat,
       return;
    }
 
+   /* Get all shader objects at once so we can make the operation
+    * all-or-nothing.
+    */
+   if (n > SIZE_MAX / sizeof(*sh)) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderBinary(count)");
+      return;
+   }
+
+   sh = alloca(sizeof(*sh) * (size_t)n);
+   if (!sh) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderBinary");
+      return;
+   }
+
+   for (int i = 0; i < n; ++i) {
+      sh[i] = _mesa_lookup_shader_err(ctx, shaders[i], "glShaderBinary");
+      if (!sh[i])
+         return;
+   }
+
+   if (binaryformat == GL_SHADER_BINARY_FORMAT_SPIR_V_ARB) {
+      if (!ctx->Extensions.ARB_gl_spirv) {
+         _mesa_error(ctx, GL_INVALID_OPERATION, "glShaderBinary(SPIR-V)");
+      } else if (n > 0) {
+         _mesa_spirv_shader_binary(ctx, (unsigned) n, sh, binary,
+                                   (size_t) length);
+      }
+
+      return;
+   }
+
    _mesa_error(ctx, GL_INVALID_ENUM, "glShaderBinary(format)");
 }
 
@@ -2007,12 +2368,15 @@ _mesa_GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei *length,
       return;
    }
 
-   *length = 0;
-   _mesa_error(ctx, GL_INVALID_OPERATION,
-               "glGetProgramBinary(driver supports zero binary formats)");
-
-   (void) binaryFormat;
-   (void) binary;
+   if (ctx->Const.NumProgramBinaryFormats == 0) {
+      *length = 0;
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glGetProgramBinary(driver supports zero binary formats)");
+   } else {
+      _mesa_get_program_binary(ctx, shProg, bufSize, length, binaryFormat,
+                               binary);
+      assert(*length == 0 || *binaryFormat == GL_PROGRAM_BINARY_FORMAT_MESA);
+   }
 }
 
 void GLAPIENTRY
@@ -2026,8 +2390,8 @@ _mesa_ProgramBinary(GLuint program, GLenum binaryFormat,
    if (!shProg)
       return;
 
-   (void) binaryFormat;
-   (void) binary;
+   _mesa_clear_shader_program_data(ctx, shProg);
+   shProg->data = _mesa_create_shader_program_data();
 
    /* Section 2.3.1 (Errors) of the OpenGL 4.5 spec says:
     *
@@ -2039,34 +2403,32 @@ _mesa_ProgramBinary(GLuint program, GLenum binaryFormat,
       return;
    }
 
-   /* The ARB_get_program_binary spec says:
-    *
-    *     "<binaryFormat> and <binary> must be those returned by a previous
-    *     call to GetProgramBinary, and <length> must be the length of the
-    *     program binary as returned by GetProgramBinary or GetProgramiv with
-    *     <pname> PROGRAM_BINARY_LENGTH. Loading the program binary will fail,
-    *     setting the LINK_STATUS of <program> to FALSE, if these conditions
-    *     are not met."
-    *
-    * Since any value of binaryFormat passed "is not one of those specified as
-    * allowable for [this] command, an INVALID_ENUM error is generated."
-    */
-   shProg->data->LinkStatus = GL_FALSE;
-   _mesa_error(ctx, GL_INVALID_ENUM, "glProgramBinary");
+   if (ctx->Const.NumProgramBinaryFormats == 0 ||
+       binaryFormat != GL_PROGRAM_BINARY_FORMAT_MESA) {
+      /* The ARB_get_program_binary spec says:
+       *
+       *     "<binaryFormat> and <binary> must be those returned by a previous
+       *     call to GetProgramBinary, and <length> must be the length of the
+       *     program binary as returned by GetProgramBinary or GetProgramiv with
+       *     <pname> PROGRAM_BINARY_LENGTH. Loading the program binary will fail,
+       *     setting the LINK_STATUS of <program> to FALSE, if these conditions
+       *     are not met."
+       *
+       * Since any value of binaryFormat passed "is not one of those specified as
+       * allowable for [this] command, an INVALID_ENUM error is generated."
+       */
+      shProg->data->LinkStatus = LINKING_FAILURE;
+      _mesa_error(ctx, GL_INVALID_ENUM, "glProgramBinary");
+   } else {
+      _mesa_program_binary(ctx, shProg, binaryFormat, binary, length);
+   }
 }
 
 
-void GLAPIENTRY
-_mesa_ProgramParameteri(GLuint program, GLenum pname, GLint value)
+static ALWAYS_INLINE void
+program_parameteri(struct gl_context *ctx, struct gl_shader_program *shProg,
+                   GLuint pname, GLint value, bool no_error)
 {
-   struct gl_shader_program *shProg;
-   GET_CURRENT_CONTEXT(ctx);
-
-   shProg = _mesa_lookup_shader_program_err(ctx, program,
-                                            "glProgramParameteri");
-   if (!shProg)
-      return;
-
    switch (pname) {
    case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
       /* This enum isn't part of the OES extension for OpenGL ES 2.0, but it
@@ -2082,7 +2444,7 @@ _mesa_ProgramParameteri(GLuint program, GLenum pname, GLint value)
        *     "An INVALID_VALUE error is generated if the <value> argument to
        *     ProgramParameteri is not TRUE or FALSE."
        */
-      if (value != GL_TRUE && value != GL_FALSE) {
+      if (!no_error && value != GL_TRUE && value != GL_FALSE) {
          goto invalid_value;
       }
 
@@ -2097,7 +2459,7 @@ _mesa_ProgramParameteri(GLuint program, GLenum pname, GLint value)
        *     will not be in effect until the next time LinkProgram or
        *     ProgramBinary has been called successfully."
        *
-       * The resloution of issue 9 in the extension spec also says:
+       * The resolution of issue 9 in the extension spec also says:
        *
        *     "The application may use the PROGRAM_BINARY_RETRIEVABLE_HINT hint
        *     to indicate to the GL implementation that this program will
@@ -2106,22 +2468,24 @@ _mesa_ProgramParameteri(GLuint program, GLenum pname, GLint value)
        *     changes made to the program before being saved such that when it
        *     is loaded again a recompile can be avoided."
        */
-      shProg->BinaryRetreivableHint = value;
+      shProg->BinaryRetrievableHintPending = value;
       return;
 
    case GL_PROGRAM_SEPARABLE:
       /* Spec imply that the behavior is the same as ARB_get_program_binary
        * Chapter 7.3 Program Objects
        */
-      if (value != GL_TRUE && value != GL_FALSE) {
+      if (!no_error && value != GL_TRUE && value != GL_FALSE) {
          goto invalid_value;
       }
       shProg->SeparateShader = value;
       return;
 
    default:
-      _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameteri(pname=%s)",
-                  _mesa_enum_to_string(pname));
+      if (!no_error) {
+         _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameteri(pname=%s)",
+                     _mesa_enum_to_string(pname));
+      }
       return;
    }
 
@@ -2134,13 +2498,58 @@ invalid_value:
 }
 
 
+void GLAPIENTRY
+_mesa_ProgramParameteri_no_error(GLuint program, GLenum pname, GLint value)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, program);
+   program_parameteri(ctx, shProg, pname, value, true);
+}
+
+
+void GLAPIENTRY
+_mesa_ProgramParameteri(GLuint program, GLenum pname, GLint value)
+{
+   struct gl_shader_program *shProg;
+   GET_CURRENT_CONTEXT(ctx);
+
+   shProg = _mesa_lookup_shader_program_err(ctx, program,
+                                            "glProgramParameteri");
+   if (!shProg)
+      return;
+
+   program_parameteri(ctx, shProg, pname, value, false);
+}
+
+
 void
-_mesa_use_shader_program(struct gl_context *ctx, GLenum type,
-                         struct gl_shader_program *shProg,
-                         struct gl_pipeline_object *shTarget)
+_mesa_use_program(struct gl_context *ctx, gl_shader_stage stage,
+                  struct gl_shader_program *shProg, struct gl_program *prog,
+                  struct gl_pipeline_object *shTarget)
 {
-   gl_shader_stage stage = _mesa_shader_enum_to_shader_stage(type);
-   use_shader_program(ctx, stage, shProg, shTarget);
+   struct gl_program **target;
+
+   target = &shTarget->CurrentProgram[stage];
+   if (prog) {
+      _mesa_program_init_subroutine_defaults(ctx, prog);
+   }
+
+   if (*target != prog) {
+      /* Program is current, flush it */
+      if (shTarget == ctx->_Shader) {
+         FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
+      }
+
+      _mesa_reference_shader_program(ctx,
+                                     &shTarget->ReferencedPrograms[stage],
+                                     shProg);
+      _mesa_reference_program(ctx, target, prog);
+      if (stage == MESA_SHADER_VERTEX)
+         _mesa_update_vertex_processing_mode(ctx);
+      return;
+   }
+
 }
 
 
@@ -2159,48 +2568,20 @@ _mesa_copy_linked_program_data(const struct gl_shader_program *src,
 
    struct gl_program *dst = dst_sh->Program;
 
-   dst->info.num_images = dst_sh->NumImages;
+   dst->info.separate_shader = src->SeparateShader;
 
    switch (dst_sh->Stage) {
-   case MESA_SHADER_VERTEX:
-      dst->ClipDistanceArraySize = src->Vert.ClipDistanceArraySize;
-      dst->CullDistanceArraySize = src->Vert.CullDistanceArraySize;
-      break;
-   case MESA_SHADER_TESS_CTRL: {
-      dst->info.tcs.vertices_out = dst_sh->info.TessCtrl.VerticesOut;
-      break;
-   }
-   case MESA_SHADER_TESS_EVAL: {
-      dst->info.tes.primitive_mode = dst_sh->info.TessEval.PrimitiveMode;
-      dst->info.tes.spacing = dst_sh->info.TessEval.Spacing;
-      dst->info.tes.vertex_order = dst_sh->info.TessEval.VertexOrder;
-      dst->info.tes.point_mode = dst_sh->info.TessEval.PointMode;
-      dst->ClipDistanceArraySize = src->TessEval.ClipDistanceArraySize;
-      dst->CullDistanceArraySize = src->TessEval.CullDistanceArraySize;
-      break;
-   }
    case MESA_SHADER_GEOMETRY: {
       dst->info.gs.vertices_in = src->Geom.VerticesIn;
-      dst->info.gs.vertices_out = dst_sh->info.Geom.VerticesOut;
-      dst->info.gs.invocations = dst_sh->info.Geom.Invocations;
-      dst->info.gs.input_primitive = dst_sh->info.Geom.InputType;
-      dst->info.gs.output_primitive = dst_sh->info.Geom.OutputType;
-      dst->ClipDistanceArraySize = src->Geom.ClipDistanceArraySize;
-      dst->CullDistanceArraySize = src->Geom.CullDistanceArraySize;
       dst->info.gs.uses_end_primitive = src->Geom.UsesEndPrimitive;
       dst->info.gs.uses_streams = src->Geom.UsesStreams;
       break;
    }
    case MESA_SHADER_FRAGMENT: {
       dst->info.fs.depth_layout = src->FragDepthLayout;
-      dst->info.fs.early_fragment_tests = dst_sh->info.EarlyFragmentTests;
-      dst->info.fs.inner_coverage = dst_sh->info.InnerCoverage;
-      dst->info.fs.post_depth_coverage = dst_sh->info.PostDepthCoverage;
       break;
    }
    case MESA_SHADER_COMPUTE: {
-      for (int i = 0; i < 3; i++)
-         dst->info.cs.local_size[i] = src->Comp.LocalSize[i];
       dst->info.cs.shared_size = src->Comp.SharedSize;
       break;
    }
@@ -2218,7 +2599,7 @@ _mesa_CreateShaderProgramv(GLenum type, GLsizei count,
 {
    GET_CURRENT_CONTEXT(ctx);
 
-   const GLuint shader = create_shader(ctx, type);
+   const GLuint shader = create_shader_err(ctx, type, "glCreateShaderProgramv");
    GLuint program = 0;
 
    /*
@@ -2247,15 +2628,15 @@ _mesa_CreateShaderProgramv(GLenum type, GLsizei count,
 
         get_shaderiv(ctx, shader, GL_COMPILE_STATUS, &compiled);
         if (compiled) {
-           attach_shader(ctx, program, shader);
+           attach_shader_err(ctx, program, shader, "glCreateShaderProgramv");
            _mesa_link_program(ctx, shProg);
-           detach_shader(ctx, program, shader);
+           detach_shader_error(ctx, program, shader);
 
 #if 0
            /* Possibly... */
            if (active-user-defined-varyings-in-linked-program) {
               append-error-to-info-log;
-               shProg->data->LinkStatus = GL_FALSE;
+               shProg->data->LinkStatus = LINKING_FAILURE;
            }
 #endif
         }
@@ -2273,6 +2654,14 @@ _mesa_CreateShaderProgramv(GLenum type, GLsizei count,
 /**
  * For GL_ARB_tessellation_shader
  */
+void GLAPIENTRY
+_mesa_PatchParameteri_no_error(GLenum pname, GLint value)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ctx->TessCtrlProgram.patch_vertices = value;
+}
+
+
 extern void GLAPIENTRY
 _mesa_PatchParameteri(GLenum pname, GLint value)
 {
@@ -2339,11 +2728,6 @@ _mesa_GetSubroutineUniformLocation(GLuint program, GLenum shadertype,
    GLenum resource_type;
    gl_shader_stage stage;
 
-   if (!_mesa_has_ARB_shader_subroutine(ctx)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
-      return -1;
-   }
-
    if (!_mesa_validate_shader_target(ctx, shadertype)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
       return -1;
@@ -2374,11 +2758,6 @@ _mesa_GetSubroutineIndex(GLuint program, GLenum shadertype,
    GLenum resource_type;
    gl_shader_stage stage;
 
-   if (!_mesa_has_ARB_shader_subroutine(ctx)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
-      return -1;
-   }
-
    if (!_mesa_validate_shader_target(ctx, shadertype)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
       return -1;
@@ -2418,11 +2797,6 @@ _mesa_GetActiveSubroutineUniformiv(GLuint program, GLenum shadertype,
    GLenum resource_type;
    int count, i, j;
 
-   if (!_mesa_has_ARB_shader_subroutine(ctx)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
-      return;
-   }
-
    if (!_mesa_validate_shader_target(ctx, shadertype)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
       return;
@@ -2441,7 +2815,8 @@ _mesa_GetActiveSubroutineUniformiv(GLuint program, GLenum shadertype,
       return;
    }
 
-   if (index >= sh->NumSubroutineUniforms) {
+   struct gl_program *p = shProg->_LinkedShaders[stage]->Program;
+   if (index >= p->sh.NumSubroutineUniforms) {
       _mesa_error(ctx, GL_INVALID_VALUE, "%s: invalid index greater than GL_ACTIVE_SUBROUTINE_UNIFORMS", api_name);
       return;
    }
@@ -2460,8 +2835,8 @@ _mesa_GetActiveSubroutineUniformiv(GLuint program, GLenum shadertype,
       if (res) {
          uni = res->Data;
          count = 0;
-         for (i = 0; i < sh->NumSubroutineFunctions; i++) {
-            struct gl_subroutine_function *fn = &sh->SubroutineFunctions[i];
+         for (i = 0; i < p->sh.NumSubroutineFunctions; i++) {
+            struct gl_subroutine_function *fn = &p->sh.SubroutineFunctions[i];
             for (j = 0; j < fn->num_compat_types; j++) {
                if (fn->types[j] == uni->type) {
                   values[count++] = i;
@@ -2504,11 +2879,6 @@ _mesa_GetActiveSubroutineUniformName(GLuint program, GLenum shadertype,
    GLenum resource_type;
    gl_shader_stage stage;
 
-   if (!_mesa_has_ARB_shader_subroutine(ctx)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
-      return;
-   }
-
    if (!_mesa_validate_shader_target(ctx, shadertype)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
       return;
@@ -2543,11 +2913,6 @@ _mesa_GetActiveSubroutineName(GLuint program, GLenum shadertype,
    GLenum resource_type;
    gl_shader_stage stage;
 
-   if (!_mesa_has_ARB_shader_subroutine(ctx)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
-      return;
-   }
-
    if (!_mesa_validate_shader_target(ctx, shadertype)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
       return;
@@ -2574,60 +2939,53 @@ _mesa_UniformSubroutinesuiv(GLenum shadertype, GLsizei count,
 {
    GET_CURRENT_CONTEXT(ctx);
    const char *api_name = "glUniformSubroutinesuiv";
-   struct gl_shader_program *shProg;
-   struct gl_linked_shader *sh;
    gl_shader_stage stage;
    int i;
 
-   if (!_mesa_has_ARB_shader_subroutine(ctx)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
-      return;
-   }
-
    if (!_mesa_validate_shader_target(ctx, shadertype)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
       return;
    }
 
    stage = _mesa_shader_enum_to_shader_stage(shadertype);
-   shProg = ctx->_Shader->CurrentProgram[stage];
-   if (!shProg) {
+   struct gl_program *p = ctx->_Shader->CurrentProgram[stage];
+   if (!p) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
       return;
    }
 
-   sh = shProg->_LinkedShaders[stage];
-   if (!sh) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
-      return;
-   }
-
-   if (count != sh->NumSubroutineUniformRemapTable) {
+   if (count != p->sh.NumSubroutineUniformRemapTable) {
       _mesa_error(ctx, GL_INVALID_VALUE, "%s", api_name);
       return;
    }
 
    i = 0;
+   bool flushed = false;
    do {
-      struct gl_uniform_storage *uni = sh->SubroutineUniformRemapTable[i];
+      struct gl_uniform_storage *uni = p->sh.SubroutineUniformRemapTable[i];
       if (uni == NULL) {
          i++;
          continue;
       }
 
+      if (!flushed) {
+         _mesa_flush_vertices_for_uniforms(ctx, uni);
+         flushed = true;
+      }
+
       int uni_count = uni->array_elements ? uni->array_elements : 1;
       int j, k, f;
 
       for (j = i; j < i + uni_count; j++) {
          struct gl_subroutine_function *subfn = NULL;
-         if (indices[j] > sh->MaxSubroutineFunctionIndex) {
+         if (indices[j] > p->sh.MaxSubroutineFunctionIndex) {
             _mesa_error(ctx, GL_INVALID_VALUE, "%s", api_name);
             return;
          }
 
-         for (f = 0; f < sh->NumSubroutineFunctions; f++) {
-            if (sh->SubroutineFunctions[f].index == indices[j])
-               subfn = &sh->SubroutineFunctions[f];
+         for (f = 0; f < p->sh.NumSubroutineFunctions; f++) {
+            if (p->sh.SubroutineFunctions[f].index == indices[j])
+               subfn = &p->sh.SubroutineFunctions[f];
          }
 
          if (!subfn) {
@@ -2643,12 +3001,10 @@ _mesa_UniformSubroutinesuiv(GLenum shadertype, GLsizei count,
             return;
          }
 
-         ctx->SubroutineIndex[sh->Stage].IndexPtr[j] = indices[j];
+         ctx->SubroutineIndex[p->info.stage].IndexPtr[j] = indices[j];
       }
       i += uni_count;
    } while(i < count);
-
-   FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
 }
 
 
@@ -2658,39 +3014,26 @@ _mesa_GetUniformSubroutineuiv(GLenum shadertype, GLint location,
 {
    GET_CURRENT_CONTEXT(ctx);
    const char *api_name = "glGetUniformSubroutineuiv";
-   struct gl_shader_program *shProg;
-   struct gl_linked_shader *sh;
    gl_shader_stage stage;
 
-   if (!_mesa_has_ARB_shader_subroutine(ctx)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
-      return;
-   }
-
    if (!_mesa_validate_shader_target(ctx, shadertype)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
       return;
    }
 
    stage = _mesa_shader_enum_to_shader_stage(shadertype);
-   shProg = ctx->_Shader->CurrentProgram[stage];
-   if (!shProg) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
-      return;
-   }
-
-   sh = shProg->_LinkedShaders[stage];
-   if (!sh) {
+   struct gl_program *p = ctx->_Shader->CurrentProgram[stage];
+   if (!p) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
       return;
    }
 
-   if (location >= sh->NumSubroutineUniformRemapTable) {
+   if (location >= p->sh.NumSubroutineUniformRemapTable) {
       _mesa_error(ctx, GL_INVALID_VALUE, "%s", api_name);
       return;
    }
 
-   *params = ctx->SubroutineIndex[sh->Stage].IndexPtr[location];
+   *params = ctx->SubroutineIndex[p->info.stage].IndexPtr[location];
 }
 
 
@@ -2704,11 +3047,6 @@ _mesa_GetProgramStageiv(GLuint program, GLenum shadertype,
    struct gl_linked_shader *sh;
    gl_shader_stage stage;
 
-   if (!_mesa_has_ARB_shader_subroutine(ctx)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
-      return;
-   }
-
    if (!_mesa_validate_shader_target(ctx, shadertype)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
       return;
@@ -2742,15 +3080,16 @@ _mesa_GetProgramStageiv(GLuint program, GLenum shadertype,
       return;
    }
 
+   struct gl_program *p = sh->Program;
    switch (pname) {
    case GL_ACTIVE_SUBROUTINES:
-      values[0] = sh->NumSubroutineFunctions;
+      values[0] = p->sh.NumSubroutineFunctions;
       break;
    case GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS:
-      values[0] = sh->NumSubroutineUniformRemapTable;
+      values[0] = p->sh.NumSubroutineUniformRemapTable;
       break;
    case GL_ACTIVE_SUBROUTINE_UNIFORMS:
-      values[0] = sh->NumSubroutineUniforms;
+      values[0] = p->sh.NumSubroutineUniforms;
       break;
    case GL_ACTIVE_SUBROUTINE_MAX_LENGTH:
    {
@@ -2760,7 +3099,7 @@ _mesa_GetProgramStageiv(GLuint program, GLenum shadertype,
       struct gl_program_resource *res;
 
       resource_type = _mesa_shader_stage_to_subroutine(stage);
-      for (i = 0; i < sh->NumSubroutineFunctions; i++) {
+      for (i = 0; i < p->sh.NumSubroutineFunctions; i++) {
          res = _mesa_program_resource_find_index(shProg, resource_type, i);
          if (res) {
             const GLint len = strlen(_mesa_program_resource_name(res)) + 1;
@@ -2779,7 +3118,7 @@ _mesa_GetProgramStageiv(GLuint program, GLenum shadertype,
       struct gl_program_resource *res;
 
       resource_type = _mesa_shader_stage_to_subroutine_uniform(stage);
-      for (i = 0; i < sh->NumSubroutineUniformRemapTable; i++) {
+      for (i = 0; i < p->sh.NumSubroutineUniformRemapTable; i++) {
          res = _mesa_program_resource_find_index(shProg, resource_type, i);
          if (res) {
             const GLint len = strlen(_mesa_program_resource_name(res)) + 1
@@ -2800,13 +3139,12 @@ _mesa_GetProgramStageiv(GLuint program, GLenum shadertype,
 }
 
 static int
-find_compat_subroutine(struct gl_linked_shader *sh,
-                       const struct glsl_type *type)
+find_compat_subroutine(struct gl_program *p, const struct glsl_type *type)
 {
    int i, j;
 
-   for (i = 0; i < sh->NumSubroutineFunctions; i++) {
-      struct gl_subroutine_function *fn = &sh->SubroutineFunctions[i];
+   for (i = 0; i < p->sh.NumSubroutineFunctions; i++) {
+      struct gl_subroutine_function *fn = &p->sh.SubroutineFunctions[i];
       for (j = 0; j < fn->num_compat_types; j++) {
          if (fn->types[j] == type)
             return i;
@@ -2817,16 +3155,16 @@ find_compat_subroutine(struct gl_linked_shader *sh,
 
 static void
 _mesa_shader_write_subroutine_index(struct gl_context *ctx,
-                                    struct gl_linked_shader *sh)
+                                    struct gl_program *p)
 {
    int i, j;
 
-   if (sh->NumSubroutineUniformRemapTable == 0)
+   if (p->sh.NumSubroutineUniformRemapTable == 0)
       return;
 
    i = 0;
    do {
-      struct gl_uniform_storage *uni = sh->SubroutineUniformRemapTable[i];
+      struct gl_uniform_storage *uni = p->sh.SubroutineUniformRemapTable[i];
       int uni_count;
       int val;
 
@@ -2837,60 +3175,43 @@ _mesa_shader_write_subroutine_index(struct gl_context *ctx,
 
       uni_count = uni->array_elements ? uni->array_elements : 1;
       for (j = 0; j < uni_count; j++) {
-         val = ctx->SubroutineIndex[sh->Stage].IndexPtr[i + j];
+         val = ctx->SubroutineIndex[p->info.stage].IndexPtr[i + j];
          memcpy(&uni->storage[j], &val, sizeof(int));
       }
 
       _mesa_propagate_uniforms_to_driver_storage(uni, 0, uni_count);
       i += uni_count;
-   } while(i < sh->NumSubroutineUniformRemapTable);
+   } while(i < p->sh.NumSubroutineUniformRemapTable);
 }
 
 void
 _mesa_shader_write_subroutine_indices(struct gl_context *ctx,
                                       gl_shader_stage stage)
 {
-   if (ctx->_Shader->CurrentProgram[stage] &&
-       ctx->_Shader->CurrentProgram[stage]->_LinkedShaders[stage])
+   if (ctx->_Shader->CurrentProgram[stage])
       _mesa_shader_write_subroutine_index(ctx,
-                                          ctx->_Shader->CurrentProgram[stage]->_LinkedShaders[stage]);
+                                          ctx->_Shader->CurrentProgram[stage]);
 }
 
-static void
-_mesa_shader_init_subroutine_defaults(struct gl_context *ctx,
-                                      struct gl_linked_shader *sh)
+void
+_mesa_program_init_subroutine_defaults(struct gl_context *ctx,
+                                       struct gl_program *p)
 {
-   int i;
-   struct gl_subroutine_index_binding *binding = &ctx->SubroutineIndex[sh->Stage];
-   if (binding->NumIndex != sh->NumSubroutineUniformRemapTable) {
+   assert(p);
+
+   struct gl_subroutine_index_binding *binding = &ctx->SubroutineIndex[p->info.stage];
+   if (binding->NumIndex != p->sh.NumSubroutineUniformRemapTable) {
       binding->IndexPtr = realloc(binding->IndexPtr,
-                                  sh->NumSubroutineUniformRemapTable * (sizeof(GLuint)));
-      binding->NumIndex = sh->NumSubroutineUniformRemapTable;
+                                  p->sh.NumSubroutineUniformRemapTable * (sizeof(GLuint)));
+      binding->NumIndex = p->sh.NumSubroutineUniformRemapTable;
    }
 
-   for (i = 0; i < sh->NumSubroutineUniformRemapTable; i++) {
-      struct gl_uniform_storage *uni = sh->SubroutineUniformRemapTable[i];
+   for (int i = 0; i < p->sh.NumSubroutineUniformRemapTable; i++) {
+      struct gl_uniform_storage *uni = p->sh.SubroutineUniformRemapTable[i];
 
       if (!uni)
          continue;
 
-      binding->IndexPtr[i] = find_compat_subroutine(sh, uni->type);
-   }
-}
-
-void
-_mesa_shader_program_init_subroutine_defaults(struct gl_context *ctx,
-                                              struct gl_shader_program *shProg)
-{
-   int i;
-
-   if (!shProg)
-      return;
-
-   for (i = 0; i < MESA_SHADER_STAGES; i++) {
-      if (!shProg->_LinkedShaders[i])
-         continue;
-
-      _mesa_shader_init_subroutine_defaults(ctx, shProg->_LinkedShaders[i]);
+      binding->IndexPtr[i] = find_compat_subroutine(p, uni->type);
    }
 }