mesa: add KHR_no_error support for glAttachShader() and glAttachObjectARB()
[mesa.git] / src / mesa / main / shaderapi.c
index eb6b1f5a7e83938d860812054ac8580fee4ce4e9..16d9f1e64867b528f2525ae037452d5e8d77ba2e 100644 (file)
@@ -59,7 +59,7 @@
 #include "util/ralloc.h"
 #include "util/hash_table.h"
 #include "util/mesa-sha1.h"
-
+#include "util/crc32.h"
 
 /**
  * Return mask of GLSL_x flags by examining the MESA_GLSL env var.
@@ -77,14 +77,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"))
@@ -108,13 +108,6 @@ _mesa_get_shader_capture_path(void)
    if (!read_env_var) {
       path = getenv("MESA_SHADER_CAPTURE_PATH");
       read_env_var = true;
-      if (path &&
-          strlen(path) > PATH_MAX - strlen("/fp-4294967295.shader_test")) {
-         GET_CURRENT_CONTEXT(ctx);
-         _mesa_warning(ctx, "MESA_SHADER_CAPTURE_PATH too long; ignoring "
-                            "request to capture shaders");
-         path = NULL;
-      }
    }
 
    return path;
@@ -147,8 +140,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;
@@ -163,20 +154,15 @@ _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],
-                                     NULL);
+   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._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);
 }
 
 
@@ -258,7 +244,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;
@@ -266,11 +272,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;
    }
@@ -284,10 +290,10 @@ 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, caller);
          return;
       } else if (same_type_disallowed &&
-                 shProg->Shaders[i]->Type == sh->Type) {
+                 shProg->Shaders[i]->Stage == sh->Stage) {
         /* Shader with the same type is already attached to this program,
          * OpenGL ES 2.0 and 3.0 specs say:
          *
@@ -296,25 +302,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, 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)
@@ -330,7 +336,8 @@ create_shader(struct gl_context *ctx, GLenum type)
 
    _mesa_HashLockMutex(ctx->Shared->ShaderObjects);
    name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
-   sh = ctx->Driver.NewShader(ctx, name, type);
+   sh = _mesa_new_shader(name, _mesa_shader_enum_to_shader_stage(type));
+   sh->Type = type;
    _mesa_HashInsertLocked(ctx->Shared->ShaderObjects, name, sh);
    _mesa_HashUnlockMutex(ctx->Shared->ShaderObjects);
 
@@ -452,11 +459,11 @@ detach_shader(struct gl_context *ctx, GLuint program, GLuint shader)
 #ifdef DEBUG
          /* sanity check - make sure the new list's entries are sensible */
          for (j = 0; j < shProg->NumShaders; j++) {
-            assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER ||
-                   shProg->Shaders[j]->Type == GL_TESS_CONTROL_SHADER ||
-                   shProg->Shaders[j]->Type == GL_TESS_EVALUATION_SHADER ||
-                   shProg->Shaders[j]->Type == GL_GEOMETRY_SHADER ||
-                   shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER);
+            assert(shProg->Shaders[j]->Stage == MESA_SHADER_VERTEX ||
+                   shProg->Shaders[j]->Stage == MESA_SHADER_TESS_CTRL ||
+                   shProg->Shaders[j]->Stage == MESA_SHADER_TESS_EVAL ||
+                   shProg->Shaders[j]->Stage == MESA_SHADER_GEOMETRY ||
+                   shProg->Shaders[j]->Stage == MESA_SHADER_FRAGMENT);
             assert(shProg->Shaders[j]->RefCount > 0);
          }
 #endif
@@ -539,7 +546,7 @@ get_handle(struct gl_context *ctx, GLenum pname)
 static bool
 check_gs_query(struct gl_context *ctx, const struct gl_shader_program *shProg)
 {
-   if (shProg->LinkStatus &&
+   if (shProg->data->LinkStatus &&
        shProg->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL) {
       return true;
    }
@@ -564,7 +571,7 @@ check_gs_query(struct gl_context *ctx, const struct gl_shader_program *shProg)
 static bool
 check_tcs_query(struct gl_context *ctx, const struct gl_shader_program *shProg)
 {
-   if (shProg->LinkStatus &&
+   if (shProg->data->LinkStatus &&
        shProg->_LinkedShaders[MESA_SHADER_TESS_CTRL] != NULL) {
       return true;
    }
@@ -590,7 +597,7 @@ check_tcs_query(struct gl_context *ctx, const struct gl_shader_program *shProg)
 static bool
 check_tes_query(struct gl_context *ctx, const struct gl_shader_program *shProg)
 {
-   if (shProg->LinkStatus &&
+   if (shProg->data->LinkStatus &&
        shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL] != NULL) {
       return true;
    }
@@ -643,13 +650,14 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
       *params = shProg->DeletePending;
       return;
    case GL_LINK_STATUS:
-      *params = shProg->LinkStatus;
+      *params = shProg->data->LinkStatus ? GL_TRUE : GL_FALSE;
       return;
    case GL_VALIDATE_STATUS:
-      *params = shProg->Validated;
+      *params = shProg->data->Validated;
       return;
    case GL_INFO_LOG_LENGTH:
-      *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0;
+      *params = (shProg->data->InfoLog && shProg->data->InfoLog[0] != '\0') ?
+         strlen(shProg->data->InfoLog) + 1 : 0;
       return;
    case GL_ATTACHED_SHADERS:
       *params = shProg->NumShaders;
@@ -663,9 +671,9 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
    case GL_ACTIVE_UNIFORMS: {
       unsigned i;
       const unsigned num_uniforms =
-         shProg->NumUniformStorage - shProg->NumHiddenUniforms;
+         shProg->data->NumUniformStorage - shProg->data->NumHiddenUniforms;
       for (*params = 0, i = 0; i < num_uniforms; i++) {
-         if (!shProg->UniformStorage[i].is_shader_storage)
+         if (!shProg->data->UniformStorage[i].is_shader_storage)
             (*params)++;
       }
       return;
@@ -674,17 +682,17 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
       unsigned i;
       GLint max_len = 0;
       const unsigned num_uniforms =
-         shProg->NumUniformStorage - shProg->NumHiddenUniforms;
+         shProg->data->NumUniformStorage - shProg->data->NumHiddenUniforms;
 
       for (i = 0; i < num_uniforms; i++) {
-         if (shProg->UniformStorage[i].is_shader_storage)
+         if (shProg->data->UniformStorage[i].is_shader_storage)
             continue;
 
         /* 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->UniformStorage[i].name) + 1 +
-            ((shProg->UniformStorage[i].array_elements != 0) ? 3 : 0);
+         const GLint len = strlen(shProg->data->UniformStorage[i].name) + 1 +
+             ((shProg->data->UniformStorage[i].array_elements != 0) ? 3 : 0);
 
         if (len > max_len)
            max_len = len;
@@ -725,26 +733,34 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
    case GL_GEOMETRY_VERTICES_OUT:
       if (!has_core_gs)
          break;
-      if (check_gs_query(ctx, shProg))
-         *params = shProg->Geom.VerticesOut;
+      if (check_gs_query(ctx, shProg)) {
+         *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
+            Program->info.gs.vertices_out;
+      }
       return;
    case GL_GEOMETRY_SHADER_INVOCATIONS:
       if (!has_core_gs || !ctx->Extensions.ARB_gpu_shader5)
          break;
-      if (check_gs_query(ctx, shProg))
-         *params = shProg->Geom.Invocations;
+      if (check_gs_query(ctx, shProg)) {
+         *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
+            Program->info.gs.invocations;
+      }
       return;
    case GL_GEOMETRY_INPUT_TYPE:
       if (!has_core_gs)
          break;
-      if (check_gs_query(ctx, shProg))
-         *params = shProg->Geom.InputType;
+      if (check_gs_query(ctx, shProg)) {
+         *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
+            Program->info.gs.input_primitive;
+      }
       return;
    case GL_GEOMETRY_OUTPUT_TYPE:
       if (!has_core_gs)
          break;
-      if (check_gs_query(ctx, shProg))
-         *params = shProg->Geom.OutputType;
+      if (check_gs_query(ctx, shProg)) {
+         *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->
+            Program->info.gs.output_primitive;
+      }
       return;
    case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: {
       unsigned i;
@@ -753,10 +769,10 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
       if (!has_ubo)
          break;
 
-      for (i = 0; i < shProg->NumUniformBlocks; i++) {
+      for (i = 0; i < shProg->data->NumUniformBlocks; i++) {
         /* Add one for the terminating NUL character.
          */
-        const GLint len = strlen(shProg->UniformBlocks[i].Name) + 1;
+         const GLint len = strlen(shProg->data->UniformBlocks[i].Name) + 1;
 
         if (len > max_len)
            max_len = len;
@@ -769,7 +785,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
       if (!has_ubo)
          break;
 
-      *params = shProg->NumUniformBlocks;
+      *params = shProg->data->NumUniformBlocks;
       return;
    case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
       /* This enum isn't part of the OES extension for OpenGL ES 2.0.  It is
@@ -790,13 +806,13 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
       if (!ctx->Extensions.ARB_shader_atomic_counters)
          break;
 
-      *params = shProg->NumAtomicBuffers;
+      *params = shProg->data->NumAtomicBuffers;
       return;
    case GL_COMPUTE_WORK_GROUP_SIZE: {
       int i;
       if (!_mesa_has_compute_shaders(ctx))
          break;
-      if (!shProg->LinkStatus) {
+      if (!shProg->data->LinkStatus) {
          _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramiv(program not "
                      "linked)");
          return;
@@ -807,44 +823,69 @@ 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->LinkStatus == GL_FALSE) ? 0 : shProg->SeparateShader;
+      *params = (shProg->data->LinkStatus == linking_failure) ? 0 : shProg->SeparateShader;
       return;
 
    /* ARB_tessellation_shader */
    case GL_TESS_CONTROL_OUTPUT_VERTICES:
       if (!has_tess)
          break;
-      if (check_tcs_query(ctx, shProg))
-         *params = shProg->TessCtrl.VerticesOut;
+      if (check_tcs_query(ctx, shProg)) {
+         *params = shProg->_LinkedShaders[MESA_SHADER_TESS_CTRL]->
+            Program->info.tess.tcs_vertices_out;
+      }
       return;
    case GL_TESS_GEN_MODE:
       if (!has_tess)
          break;
-      if (check_tes_query(ctx, shProg))
-         *params = shProg->TessEval.PrimitiveMode;
+      if (check_tes_query(ctx, shProg)) {
+         *params = shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]->
+            Program->info.tess.primitive_mode;
+      }
       return;
    case GL_TESS_GEN_SPACING:
       if (!has_tess)
          break;
-      if (check_tes_query(ctx, shProg))
-         *params = shProg->TessEval.Spacing;
+      if (check_tes_query(ctx, shProg)) {
+         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:
       if (!has_tess)
          break;
-      if (check_tes_query(ctx, shProg))
-         *params = shProg->TessEval.VertexOrder;
+      if (check_tes_query(ctx, shProg)) {
+         *params = shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]->
+            Program->info.tess.ccw ? GL_CCW : GL_CW;
+         }
       return;
    case GL_TESS_GEN_POINT_MODE:
       if (!has_tess)
          break;
-      if (check_tes_query(ctx, shProg))
-         *params = shProg->TessEval.PointMode;
+      if (check_tes_query(ctx, shProg)) {
+         *params = shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]->
+            Program->info.tess.point_mode ? GL_TRUE : GL_FALSE;
+      }
       return;
    default:
       break;
@@ -876,10 +917,11 @@ get_shaderiv(struct gl_context *ctx, GLuint name, GLenum pname, GLint *params)
       *params = shader->DeletePending;
       break;
    case GL_COMPILE_STATUS:
-      *params = shader->CompileStatus;
+      *params = shader->CompileStatus ? GL_TRUE : GL_FALSE;
       break;
    case GL_INFO_LOG_LENGTH:
-      *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0;
+      *params = (shader->InfoLog && shader->InfoLog[0] != '\0') ?
+         strlen(shader->InfoLog) + 1 : 0;
       break;
    case GL_SHADER_SOURCE_LENGTH:
       *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
@@ -914,7 +956,7 @@ get_program_info_log(struct gl_context *ctx, GLuint program, GLsizei bufSize,
       return;
    }
 
-   _mesa_copy_string(infoLog, bufSize, length, shProg->InfoLog);
+   _mesa_copy_string(infoLog, bufSize, length, shProg->data->InfoLog);
 }
 
 
@@ -975,11 +1017,20 @@ 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;
+   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 = _mesa_str_checksum(sh->Source);
+   sh->SourceChecksum = util_hash_crc32(sh->Source, strlen(sh->Source));
 #endif
 }
 
@@ -997,7 +1048,7 @@ _mesa_compile_shader(struct gl_context *ctx, struct gl_shader *sh)
       /* 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",
@@ -1008,7 +1059,7 @@ _mesa_compile_shader(struct gl_context *ctx, struct gl_shader *sh)
       /* 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);
@@ -1016,8 +1067,13 @@ _mesa_compile_shader(struct gl_context *ctx, struct gl_shader *sh)
 
       if (ctx->_Shader->Flags & GLSL_DUMP) {
          if (sh->CompileStatus) {
-            _mesa_log("GLSL IR for shader %d:\n", sh->Name);
-            _mesa_print_ir(_mesa_get_log_file(), sh->ir, NULL);
+            if (sh->ir) {
+               _mesa_log("GLSL IR for shader %d:\n", sh->Name);
+               _mesa_print_ir(_mesa_get_log_file(), sh->ir, NULL);
+            } else {
+               _mesa_log("No GLSL IR for shader %d (shader may be from "
+                         "cache)\n", sh->Name);
+            }
             _mesa_log("\n\n");
          } else {
             _mesa_log("GLSL shader %d failed to compile.\n", sh->Name);
@@ -1065,24 +1121,51 @@ _mesa_link_program(struct gl_context *ctx, struct gl_shader_program *shProg)
       return;
    }
 
-   FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+   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, 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 && capture_path != NULL) {
+   if (shProg->Name != 0 && shProg->Name != ~0 && capture_path != NULL) {
       FILE *file;
-      char filename[PATH_MAX];
-
-      _mesa_snprintf(filename, sizeof(filename), "%s/%u.shader_test",
-                     capture_path, shProg->Name);
-
+      char *filename = ralloc_asprintf(NULL, "%s/%u.shader_test",
+                                       capture_path, shProg->Name);
       file = fopen(filename, "w");
       if (file) {
          fprintf(file, "[require]\nGLSL%s >= %u.%02u\n",
                  shProg->IsES ? " ES" : "",
-                 shProg->Version / 100, shProg->Version % 100);
+                 shProg->data->Version / 100, shProg->data->Version % 100);
          if (shProg->SeparateShader)
             fprintf(file, "GL_ARB_separate_shader_objects\nSSO ENABLED\n");
          fprintf(file, "\n");
@@ -1096,12 +1179,14 @@ _mesa_link_program(struct gl_context *ctx, struct gl_shader_program *shProg)
       } else {
          _mesa_warning(ctx, "Failed to open %s", filename);
       }
+
+      ralloc_free(filename);
    }
 
-   if (shProg->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->InfoLog);
+                  shProg->Name, shProg->data->InfoLog);
    }
 
    /* debug code */
@@ -1110,12 +1195,12 @@ _mesa_link_program(struct gl_context *ctx, struct gl_shader_program *shProg)
 
       printf("Link %u shaders in program %u: %s\n",
                    shProg->NumShaders, shProg->Name,
-                   shProg->LinkStatus ? "Success" : "Failed");
+                   shProg->data->LinkStatus ? "Success" : "Failed");
 
       for (i = 0; i < shProg->NumShaders; i++) {
-         printf(" shader %u, type 0x%x\n",
+         printf(" shader %u, stage %u\n",
                       shProg->Shaders[i]->Name,
-                      shProg->Shaders[i]->Type);
+                      shProg->Shaders[i]->Stage);
       }
    }
 }
@@ -1131,10 +1216,16 @@ print_shader_info(const struct gl_shader_program *shProg)
 
    printf("Mesa: glUseProgram(%u)\n", shProg->Name);
    for (i = 0; i < shProg->NumShaders; i++) {
+#ifdef DEBUG
       printf("  %s shader %u, checksum %u\n",
              _mesa_shader_stage_to_string(shProg->Shaders[i]->Stage),
             shProg->Shaders[i]->Name,
             shProg->Shaders[i]->SourceChecksum);
+#else
+      printf("  %s shader %u\n",
+             _mesa_shader_stage_to_string(shProg->Shaders[i]->Stage),
+             shProg->Shaders[i]->Name);
+#endif
    }
    if (shProg->_LinkedShaders[MESA_SHADER_VERTEX])
       printf("  vert prog %u\n",
@@ -1161,7 +1252,7 @@ void
 _mesa_active_program(struct gl_context *ctx, struct gl_shader_program *shProg,
                     const char *caller)
 {
-   if ((shProg != NULL) && !shProg->LinkStatus) {
+   if ((shProg != NULL) && !shProg->data->LinkStatus) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                  "%s(program %u not linked)", caller, shProg->Name);
       return;
@@ -1173,66 +1264,20 @@ _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(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");
-
-   if (ctx->Driver.UseProgram)
-      ctx->Driver.UseProgram(ctx, shProg);
 }
 
 
@@ -1245,7 +1290,7 @@ static GLboolean
 validate_shader_program(const struct gl_shader_program *shProg,
                         char *errMsg)
 {
-   if (!shProg->LinkStatus) {
+   if (!shProg->data->LinkStatus) {
       return GL_FALSE;
    }
 
@@ -1289,23 +1334,38 @@ validate_program(struct gl_context *ctx, GLuint program)
       return;
    }
 
-   shProg->Validated = validate_shader_program(shProg, errMsg);
-   if (!shProg->Validated) {
+   shProg->data->Validated = validate_shader_program(shProg, errMsg);
+   if (!shProg->data->Validated) {
       /* update info log */
-      if (shProg->InfoLog) {
-         ralloc_free(shProg->InfoLog);
+      if (shProg->data->InfoLog) {
+         ralloc_free(shProg->data->InfoLog);
       }
-      shProg->InfoLog = ralloc_strdup(shProg, errMsg);
+      shProg->data->InfoLog = ralloc_strdup(shProg->data, errMsg);
    }
 }
 
 
+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);
 }
 
 
@@ -1313,7 +1373,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");
 }
 
 
@@ -1575,7 +1635,7 @@ _mesa_LinkProgram(GLuint programObj)
                                                            "glLinkProgram"));
 }
 
-#if defined(HAVE_SHA1)
+#ifdef ENABLE_SHADER_CACHE
 /**
  * Generate a SHA-1 hash value string for given source string.
  */
@@ -1593,9 +1653,9 @@ generate_sha1(const char *source, char sha_str[64])
  *
  * <path>/<stage prefix>_<CHECKSUM>.glsl
  */
-static void
+static char *
 construct_name(const gl_shader_stage stage, const char *source,
-               const char *path, char *name, unsigned length)
+               const char *path)
 {
    char sha[64];
    static const char *types[] = {
@@ -1603,8 +1663,7 @@ construct_name(const gl_shader_stage stage, const char *source,
    };
 
    generate_sha1(source, sha);
-   _mesa_snprintf(name, length, "%s/%s_%s.glsl", path, types[stage],
-                  sha);
+   return ralloc_asprintf(NULL, "%s/%s_%s.glsl", path, types[stage], sha);
 }
 
 /**
@@ -1613,7 +1672,6 @@ construct_name(const gl_shader_stage stage, const char *source,
 static void
 dump_shader(const gl_shader_stage stage, const char *source)
 {
-   char name[PATH_MAX];
    static bool path_exists = true;
    char *dump_path;
    FILE *f;
@@ -1627,7 +1685,7 @@ dump_shader(const gl_shader_stage stage, const char *source)
       return;
    }
 
-   construct_name(stage, source, dump_path, name, PATH_MAX);
+   char *name = construct_name(stage, source, dump_path);
 
    f = fopen(name, "w");
    if (f) {
@@ -1638,6 +1696,7 @@ dump_shader(const gl_shader_stage stage, const char *source)
       _mesa_warning(ctx, "could not open %s for dumping shader (%s)", name,
                     strerror(errno));
    }
+   ralloc_free(name);
 }
 
 /**
@@ -1647,7 +1706,6 @@ dump_shader(const gl_shader_stage stage, const char *source)
 static GLcharARB *
 read_shader(const gl_shader_stage stage, const char *source)
 {
-   char name[PATH_MAX];
    char *read_path;
    static bool path_exists = true;
    int len, shader_size = 0;
@@ -1663,9 +1721,9 @@ read_shader(const gl_shader_stage stage, const char *source)
       return NULL;
    }
 
-   construct_name(stage, source, read_path, name, PATH_MAX);
-
+   char *name = construct_name(stage, source, read_path);
    f = fopen(name, "r");
+   ralloc_free(name);
    if (!f)
       return NULL;
 
@@ -1688,7 +1746,8 @@ 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.
@@ -1705,10 +1764,6 @@ _mesa_ShaderSource(GLuint shaderObj, GLsizei count,
    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;
@@ -1764,7 +1819,9 @@ _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.
     */
@@ -1775,7 +1832,7 @@ _mesa_ShaderSource(GLuint shaderObj, GLsizei count,
       free(source);
       source = replacement;
    }
-#endif /* HAVE_SHA1 */
+#endif /* ENABLE_SHADER_CACHE */
 
    shader_source(sh, source);
 
@@ -1783,40 +1840,44 @@ _mesa_ShaderSource(GLuint shaderObj, GLsizei count,
 }
 
 
-void GLAPIENTRY
-_mesa_UseProgram(GLuint program)
+static ALWAYS_INLINE void
+use_program(GLuint program, bool no_error)
 {
    GET_CURRENT_CONTEXT(ctx);
-   struct gl_shader_program *shProg;
+   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->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:
     *
@@ -1827,24 +1888,42 @@ _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);
       }
    }
 }
 
 
+void GLAPIENTRY
+_mesa_UseProgram_no_error(GLuint program)
+{
+   use_program(program, true);
+}
+
+
+void GLAPIENTRY
+_mesa_UseProgram(GLuint program)
+{
+   use_program(program, false);
+}
+
+
 void GLAPIENTRY
 _mesa_ValidateProgram(GLuint program)
 {
@@ -1980,7 +2059,7 @@ _mesa_GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei *length,
     *     length is zero, and a call to GetProgramBinary will generate an
     *     INVALID_OPERATION error.
     */
-   if (!shProg->LinkStatus) {
+   if (!shProg->data->LinkStatus) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glGetProgramBinary(program %u not linked)",
                   shProg->Name);
@@ -2032,7 +2111,7 @@ _mesa_ProgramBinary(GLuint program, GLenum binaryFormat,
     * Since any value of binaryFormat passed "is not one of those specified as
     * allowable for [this] command, an INVALID_ENUM error is generated."
     */
-   shProg->LinkStatus = GL_FALSE;
+   shProg->data->LinkStatus = linking_failure;
    _mesa_error(ctx, GL_INVALID_ENUM, "glProgramBinary");
 }
 
@@ -2116,73 +2195,63 @@ invalid_value:
 
 
 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);
+      return;
+   }
 
-   if (ctx->Driver.UseProgram)
-      ctx->Driver.UseProgram(ctx, shProg);
 }
 
 
 /**
  * Copy program-specific data generated by linking from the gl_shader_program
- * object to a specific gl_program object.
+ * object to the gl_program object referred to by the gl_linked_shader.
+ *
+ * This function expects _mesa_reference_program() to have been previously
+ * called setting the gl_linked_shaders program reference.
  */
 void
-_mesa_copy_linked_program_data(gl_shader_stage type,
-                               const struct gl_shader_program *src,
-                               struct gl_program *dst)
+_mesa_copy_linked_program_data(const struct gl_shader_program *src,
+                               struct gl_linked_shader *dst_sh)
 {
-   switch (type) {
-   case MESA_SHADER_VERTEX:
-      dst->ClipDistanceArraySize = src->Vert.ClipDistanceArraySize;
-      dst->CullDistanceArraySize = src->Vert.CullDistanceArraySize;
-      break;
-   case MESA_SHADER_TESS_CTRL: {
-      struct gl_tess_ctrl_program *dst_tcp =
-         (struct gl_tess_ctrl_program *) dst;
-      dst_tcp->VerticesOut = src->TessCtrl.VerticesOut;
-      break;
-   }
-   case MESA_SHADER_TESS_EVAL: {
-      struct gl_tess_eval_program *dst_tep =
-         (struct gl_tess_eval_program *) dst;
-      dst_tep->PrimitiveMode = src->TessEval.PrimitiveMode;
-      dst_tep->Spacing = src->TessEval.Spacing;
-      dst_tep->VertexOrder = src->TessEval.VertexOrder;
-      dst_tep->PointMode = src->TessEval.PointMode;
-      dst->ClipDistanceArraySize = src->TessEval.ClipDistanceArraySize;
-      dst->CullDistanceArraySize = src->TessEval.CullDistanceArraySize;
-      break;
-   }
+   assert(dst_sh->Program);
+
+   struct gl_program *dst = dst_sh->Program;
+
+   dst->info.separate_shader = src->SeparateShader;
+
+   switch (dst_sh->Stage) {
    case MESA_SHADER_GEOMETRY: {
-      struct gl_geometry_program *dst_gp = (struct gl_geometry_program *) dst;
-      dst_gp->VerticesIn = src->Geom.VerticesIn;
-      dst_gp->VerticesOut = src->Geom.VerticesOut;
-      dst_gp->Invocations = src->Geom.Invocations;
-      dst_gp->InputType = src->Geom.InputType;
-      dst_gp->OutputType = src->Geom.OutputType;
-      dst->ClipDistanceArraySize = src->Geom.ClipDistanceArraySize;
-      dst->CullDistanceArraySize = src->Geom.CullDistanceArraySize;
-      dst_gp->UsesEndPrimitive = src->Geom.UsesEndPrimitive;
-      dst_gp->UsesStreams = src->Geom.UsesStreams;
+      dst->info.gs.vertices_in = src->Geom.VerticesIn;
+      dst->info.gs.uses_end_primitive = src->Geom.UsesEndPrimitive;
+      dst->info.gs.uses_streams = src->Geom.UsesStreams;
       break;
    }
    case MESA_SHADER_FRAGMENT: {
-      struct gl_fragment_program *dst_fp = (struct gl_fragment_program *) dst;
-      dst_fp->FragDepthLayout = src->FragDepthLayout;
+      dst->info.fs.depth_layout = src->FragDepthLayout;
       break;
    }
    case MESA_SHADER_COMPUTE: {
-      struct gl_compute_program *dst_cp = (struct gl_compute_program *) dst;
-      int i;
-      for (i = 0; i < 3; i++)
-         dst_cp->LocalSize[i] = src->Comp.LocalSize[i];
-      dst_cp->SharedSize = src->Comp.SharedSize;
+      dst->info.cs.shared_size = src->Comp.SharedSize;
       break;
    }
    default:
@@ -2228,7 +2297,7 @@ _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);
 
@@ -2236,12 +2305,12 @@ _mesa_CreateShaderProgramv(GLenum type, GLsizei count,
            /* Possibly... */
            if (active-user-defined-varyings-in-linked-program) {
               append-error-to-info-log;
-              shProg->LinkStatus = GL_FALSE;
+               shProg->data->LinkStatus = linking_failure;
            }
 #endif
         }
          if (sh->InfoLog)
-            ralloc_strcat(&shProg->InfoLog, sh->InfoLog);
+            ralloc_strcat(&shProg->data->InfoLog, sh->InfoLog);
       }
 
       delete_shader(ctx, shader);
@@ -2320,11 +2389,6 @@ _mesa_GetSubroutineUniformLocation(GLuint program, GLenum shadertype,
    GLenum resource_type;
    gl_shader_stage stage;
 
-   if (!_mesa_has_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;
@@ -2355,11 +2419,6 @@ _mesa_GetSubroutineIndex(GLuint program, GLenum shadertype,
    GLenum resource_type;
    gl_shader_stage stage;
 
-   if (!_mesa_has_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;
@@ -2392,18 +2451,13 @@ _mesa_GetActiveSubroutineUniformiv(GLuint program, GLenum shadertype,
    GET_CURRENT_CONTEXT(ctx);
    const char *api_name = "glGetActiveSubroutineUniformiv";
    struct gl_shader_program *shProg;
-   struct gl_shader *sh;
+   struct gl_linked_shader *sh;
    gl_shader_stage stage;
    struct gl_program_resource *res;
    const struct gl_uniform_storage *uni;
    GLenum resource_type;
    int count, i, j;
 
-   if (!_mesa_has_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;
@@ -2422,7 +2476,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;
    }
@@ -2441,8 +2496,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;
@@ -2485,11 +2540,6 @@ _mesa_GetActiveSubroutineUniformName(GLuint program, GLenum shadertype,
    GLenum resource_type;
    gl_shader_stage stage;
 
-   if (!_mesa_has_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;
@@ -2524,11 +2574,6 @@ _mesa_GetActiveSubroutineName(GLuint program, GLenum shadertype,
    GLenum resource_type;
    gl_shader_stage stage;
 
-   if (!_mesa_has_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;
@@ -2549,67 +2594,59 @@ _mesa_GetActiveSubroutineName(GLuint program, GLenum shadertype,
                                    length, name, api_name);
 }
 
-
 GLvoid GLAPIENTRY
 _mesa_UniformSubroutinesuiv(GLenum shadertype, GLsizei count,
                             const GLuint *indices)
 {
    GET_CURRENT_CONTEXT(ctx);
    const char *api_name = "glUniformSubroutinesuiv";
-   struct gl_shader_program *shProg;
-   struct gl_shader *sh;
    gl_shader_stage stage;
    int i;
 
-   if (!_mesa_has_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) {
@@ -2624,25 +2661,9 @@ _mesa_UniformSubroutinesuiv(GLenum shadertype, GLsizei count,
             _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
             return;
          }
-      }
-      i += uni_count;
-   } while(i < count);
 
-   FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
-   i = 0;
-   do {
-      struct gl_uniform_storage *uni = sh->SubroutineUniformRemapTable[i];
-      if (uni == NULL) {
-         i++;
-         continue;
+         ctx->SubroutineIndex[p->info.stage].IndexPtr[j] = indices[j];
       }
-
-      int uni_count = uni->array_elements ? uni->array_elements : 1;
-
-      memcpy(&uni->storage[0], &indices[i],
-             sizeof(GLuint) * uni_count);
-
-      _mesa_propagate_uniforms_to_driver_storage(uni, 0, uni_count);
       i += uni_count;
    } while(i < count);
 }
@@ -2654,44 +2675,26 @@ _mesa_GetUniformSubroutineuiv(GLenum shadertype, GLint location,
 {
    GET_CURRENT_CONTEXT(ctx);
    const char *api_name = "glGetUniformSubroutineuiv";
-   struct gl_shader_program *shProg;
-   struct gl_shader *sh;
    gl_shader_stage stage;
 
-   if (!_mesa_has_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;
    }
 
-   {
-      struct gl_uniform_storage *uni = sh->SubroutineUniformRemapTable[location];
-      int offset = location - uni->opaque[stage].index;
-      memcpy(params, &uni->storage[offset],
-            sizeof(GLuint));
-   }
+   *params = ctx->SubroutineIndex[p->info.stage].IndexPtr[location];
 }
 
 
@@ -2702,14 +2705,9 @@ _mesa_GetProgramStageiv(GLuint program, GLenum shadertype,
    GET_CURRENT_CONTEXT(ctx);
    const char *api_name = "glGetProgramStageiv";
    struct gl_shader_program *shProg;
-   struct gl_shader *sh;
+   struct gl_linked_shader *sh;
    gl_shader_stage stage;
 
-   if (!_mesa_has_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;
@@ -2721,20 +2719,38 @@ _mesa_GetProgramStageiv(GLuint program, GLenum shadertype,
 
    stage = _mesa_shader_enum_to_shader_stage(shadertype);
    sh = shProg->_LinkedShaders[stage];
+
+   /* ARB_shader_subroutine doesn't ask the program to be linked, or list any
+    * INVALID_OPERATION in the case of not be linked.
+    *
+    * And for some pnames, like GL_ACTIVE_SUBROUTINE_UNIFORMS, you can ask the
+    * same info using other specs (ARB_program_interface_query), without the
+    * need of the program to be linked, being the value for that case 0.
+    *
+    * But at the same time, some other methods require the program to be
+    * linked for pname related to locations, so it would be inconsistent to
+    * not do the same here. So we are:
+    *   * Return GL_INVALID_OPERATION if not linked only for locations.
+    *   * Setting a default value of 0, to be returned if not linked.
+    */
    if (!sh) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
+      values[0] = 0;
+      if (pname == GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS) {
+         _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name);
+      }
       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:
    {
@@ -2744,7 +2760,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;
@@ -2763,7 +2779,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
@@ -2784,12 +2800,12 @@ _mesa_GetProgramStageiv(GLuint program, GLenum shadertype,
 }
 
 static int
-find_compat_subroutine(struct gl_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;
@@ -2799,39 +2815,64 @@ find_compat_subroutine(struct gl_shader *sh, const struct glsl_type *type)
 }
 
 static void
-_mesa_shader_init_subroutine_defaults(struct gl_shader *sh)
+_mesa_shader_write_subroutine_index(struct gl_context *ctx,
+                                    struct gl_program *p)
 {
    int i, j;
 
-   for (i = 0; i < sh->NumSubroutineUniformRemapTable; i++) {
-      struct gl_uniform_storage *uni = sh->SubroutineUniformRemapTable[i];
+   if (p->sh.NumSubroutineUniformRemapTable == 0)
+      return;
+
+   i = 0;
+   do {
+      struct gl_uniform_storage *uni = p->sh.SubroutineUniformRemapTable[i];
       int uni_count;
       int val;
 
-      if (!uni)
+      if (!uni) {
+         i++;
          continue;
-      uni_count = uni->array_elements ? uni->array_elements : 1;
-      val = find_compat_subroutine(sh, uni->type);
+      }
 
-      for (j = 0; j < uni_count; j++)
+      uni_count = uni->array_elements ? uni->array_elements : 1;
+      for (j = 0; j < uni_count; 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 < p->sh.NumSubroutineUniformRemapTable);
 }
 
 void
-_mesa_shader_program_init_subroutine_defaults(struct gl_shader_program *shProg)
+_mesa_shader_write_subroutine_indices(struct gl_context *ctx,
+                                      gl_shader_stage stage)
 {
-   int i;
+   if (ctx->_Shader->CurrentProgram[stage])
+      _mesa_shader_write_subroutine_index(ctx,
+                                          ctx->_Shader->CurrentProgram[stage]);
+}
 
-   if (!shProg)
-      return;
+void
+_mesa_program_init_subroutine_defaults(struct gl_context *ctx,
+                                       struct gl_program *p)
+{
+   assert(p);
 
-   for (i = 0; i < MESA_SHADER_STAGES; i++) {
-      if (!shProg->_LinkedShaders[i])
+   struct gl_subroutine_index_binding *binding = &ctx->SubroutineIndex[p->info.stage];
+   if (binding->NumIndex != p->sh.NumSubroutineUniformRemapTable) {
+      binding->IndexPtr = realloc(binding->IndexPtr,
+                                  p->sh.NumSubroutineUniformRemapTable * (sizeof(GLuint)));
+      binding->NumIndex = p->sh.NumSubroutineUniformRemapTable;
+   }
+
+   for (int i = 0; i < p->sh.NumSubroutineUniformRemapTable; i++) {
+      struct gl_uniform_storage *uni = p->sh.SubroutineUniformRemapTable[i];
+
+      if (!uni)
          continue;
 
-      _mesa_shader_init_subroutine_defaults(shProg->_LinkedShaders[i]);
+      binding->IndexPtr[i] = find_compat_subroutine(p, uni->type);
    }
 }