nir: Return progress from nir_lower_io().
[mesa.git] / src / compiler / glsl / shader_cache.cpp
index c03a190cee1203fead7a5b95013357b8e2fa208f..dd8c6c0b408708dffd3cdcda3bfa83dcd4dcfd62 100644 (file)
@@ -207,6 +207,354 @@ decode_type_from_blob(struct blob_reader *blob)
    }
 }
 
+static void
+write_subroutines(struct blob *metadata, struct gl_shader_program *prog)
+{
+   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+      struct gl_linked_shader *sh = prog->_LinkedShaders[i];
+      if (!sh)
+         continue;
+
+      struct gl_program *glprog = sh->Program;
+
+      blob_write_uint32(metadata, glprog->sh.NumSubroutineUniforms);
+      blob_write_uint32(metadata, glprog->sh.MaxSubroutineFunctionIndex);
+      blob_write_uint32(metadata, glprog->sh.NumSubroutineFunctions);
+      for (unsigned j = 0; j < glprog->sh.NumSubroutineFunctions; j++) {
+         int num_types = glprog->sh.SubroutineFunctions[j].num_compat_types;
+
+         blob_write_string(metadata, glprog->sh.SubroutineFunctions[j].name);
+         blob_write_uint32(metadata, glprog->sh.SubroutineFunctions[j].index);
+         blob_write_uint32(metadata, num_types);
+
+         for (int k = 0; k < num_types; k++) {
+            encode_type_to_blob(metadata,
+                                glprog->sh.SubroutineFunctions[j].types[k]);
+         }
+      }
+   }
+}
+
+static void
+read_subroutines(struct blob_reader *metadata, struct gl_shader_program *prog)
+{
+   struct gl_subroutine_function *subs;
+
+   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+      struct gl_linked_shader *sh = prog->_LinkedShaders[i];
+      if (!sh)
+         continue;
+
+      struct gl_program *glprog = sh->Program;
+
+      glprog->sh.NumSubroutineUniforms = blob_read_uint32(metadata);
+      glprog->sh.MaxSubroutineFunctionIndex = blob_read_uint32(metadata);
+      glprog->sh.NumSubroutineFunctions = blob_read_uint32(metadata);
+
+      subs = rzalloc_array(prog, struct gl_subroutine_function,
+                           glprog->sh.NumSubroutineFunctions);
+      glprog->sh.SubroutineFunctions = subs;
+
+      for (unsigned j = 0; j < glprog->sh.NumSubroutineFunctions; j++) {
+         subs[j].name = ralloc_strdup(prog, blob_read_string (metadata));
+         subs[j].index = (int) blob_read_uint32(metadata);
+         subs[j].num_compat_types = (int) blob_read_uint32(metadata);
+
+         subs[j].types = rzalloc_array(prog, const struct glsl_type *,
+                                       subs[j].num_compat_types);
+         for (int k = 0; k < subs[j].num_compat_types; k++) {
+            subs[j].types[k] = decode_type_from_blob(metadata);
+         }
+      }
+   }
+}
+
+static void
+write_buffer_block(struct blob *metadata, struct gl_uniform_block *b)
+{
+   blob_write_string(metadata, b->Name);
+   blob_write_uint32(metadata, b->NumUniforms);
+   blob_write_uint32(metadata, b->Binding);
+   blob_write_uint32(metadata, b->UniformBufferSize);
+   blob_write_uint32(metadata, b->stageref);
+
+   for (unsigned j = 0; j < b->NumUniforms; j++) {
+      blob_write_string(metadata, b->Uniforms[j].Name);
+      blob_write_string(metadata, b->Uniforms[j].IndexName);
+      encode_type_to_blob(metadata, b->Uniforms[j].Type);
+      blob_write_uint32(metadata, b->Uniforms[j].Offset);
+   }
+}
+
+static void
+write_buffer_blocks(struct blob *metadata, struct gl_shader_program *prog)
+{
+   blob_write_uint32(metadata, prog->data->NumUniformBlocks);
+   blob_write_uint32(metadata, prog->data->NumShaderStorageBlocks);
+
+   for (unsigned i = 0; i < prog->data->NumUniformBlocks; i++) {
+      write_buffer_block(metadata, &prog->data->UniformBlocks[i]);
+   }
+
+   for (unsigned i = 0; i < prog->data->NumShaderStorageBlocks; i++) {
+      write_buffer_block(metadata, &prog->data->ShaderStorageBlocks[i]);
+   }
+
+   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+      struct gl_linked_shader *sh = prog->_LinkedShaders[i];
+      if (!sh)
+         continue;
+
+      struct gl_program *glprog = sh->Program;
+
+      blob_write_uint32(metadata, glprog->info.num_ubos);
+      blob_write_uint32(metadata, glprog->info.num_ssbos);
+
+      for (unsigned j = 0; j < glprog->info.num_ubos; j++) {
+         uint32_t offset =
+            glprog->sh.UniformBlocks[j] - prog->data->UniformBlocks;
+         blob_write_uint32(metadata, offset);
+      }
+
+      for (unsigned j = 0; j < glprog->info.num_ssbos; j++) {
+         uint32_t offset = glprog->sh.ShaderStorageBlocks[j] -
+            prog->data->ShaderStorageBlocks;
+         blob_write_uint32(metadata, offset);
+      }
+   }
+}
+
+static void
+read_buffer_block(struct blob_reader *metadata, struct gl_uniform_block *b,
+                  struct gl_shader_program *prog)
+{
+      b->Name = ralloc_strdup(prog->data, blob_read_string (metadata));
+      b->NumUniforms = blob_read_uint32(metadata);
+      b->Binding = blob_read_uint32(metadata);
+      b->UniformBufferSize = blob_read_uint32(metadata);
+      b->stageref = blob_read_uint32(metadata);
+
+      b->Uniforms =
+         rzalloc_array(prog->data, struct gl_uniform_buffer_variable,
+                       b->NumUniforms);
+      for (unsigned j = 0; j < b->NumUniforms; j++) {
+         b->Uniforms[j].Name = ralloc_strdup(prog->data,
+                                             blob_read_string (metadata));
+
+         char *index_name = blob_read_string(metadata);
+         if (strcmp(b->Uniforms[j].Name, index_name) == 0) {
+            b->Uniforms[j].IndexName = b->Uniforms[j].Name;
+         } else {
+            b->Uniforms[j].IndexName = ralloc_strdup(prog->data, index_name);
+         }
+
+         b->Uniforms[j].Type = decode_type_from_blob(metadata);
+         b->Uniforms[j].Offset = blob_read_uint32(metadata);
+      }
+}
+
+static void
+read_buffer_blocks(struct blob_reader *metadata,
+                   struct gl_shader_program *prog)
+{
+   prog->data->NumUniformBlocks = blob_read_uint32(metadata);
+   prog->data->NumShaderStorageBlocks = blob_read_uint32(metadata);
+
+   prog->data->UniformBlocks =
+      rzalloc_array(prog->data, struct gl_uniform_block,
+                    prog->data->NumUniformBlocks);
+
+   prog->data->ShaderStorageBlocks =
+      rzalloc_array(prog->data, struct gl_uniform_block,
+                    prog->data->NumShaderStorageBlocks);
+
+   for (unsigned i = 0; i < prog->data->NumUniformBlocks; i++) {
+      read_buffer_block(metadata, &prog->data->UniformBlocks[i], prog);
+   }
+
+   for (unsigned i = 0; i < prog->data->NumShaderStorageBlocks; i++) {
+      read_buffer_block(metadata, &prog->data->ShaderStorageBlocks[i], prog);
+   }
+
+   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+      struct gl_linked_shader *sh = prog->_LinkedShaders[i];
+      if (!sh)
+         continue;
+
+      struct gl_program *glprog = sh->Program;
+
+      glprog->info.num_ubos = blob_read_uint32(metadata);
+      glprog->info.num_ssbos = blob_read_uint32(metadata);
+
+      glprog->sh.UniformBlocks =
+         rzalloc_array(glprog, gl_uniform_block *, glprog->info.num_ubos);
+      glprog->sh.ShaderStorageBlocks =
+         rzalloc_array(glprog, gl_uniform_block *, glprog->info.num_ssbos);
+
+      for (unsigned j = 0; j < glprog->info.num_ubos; j++) {
+         uint32_t offset = blob_read_uint32(metadata);
+         glprog->sh.UniformBlocks[j] = prog->data->UniformBlocks + offset;
+      }
+
+      for (unsigned j = 0; j < glprog->info.num_ssbos; j++) {
+         uint32_t offset = blob_read_uint32(metadata);
+         glprog->sh.ShaderStorageBlocks[j] =
+            prog->data->ShaderStorageBlocks + offset;
+      }
+   }
+}
+
+static void
+write_atomic_buffers(struct blob *metadata, struct gl_shader_program *prog)
+{
+   blob_write_uint32(metadata, prog->data->NumAtomicBuffers);
+
+   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+      if (prog->_LinkedShaders[i]) {
+         struct gl_program *glprog = prog->_LinkedShaders[i]->Program;
+         blob_write_uint32(metadata, glprog->info.num_abos);
+      }
+   }
+
+   for (unsigned i = 0; i < prog->data->NumAtomicBuffers; i++) {
+      blob_write_uint32(metadata, prog->data->AtomicBuffers[i].Binding);
+      blob_write_uint32(metadata, prog->data->AtomicBuffers[i].MinimumSize);
+      blob_write_uint32(metadata, prog->data->AtomicBuffers[i].NumUniforms);
+
+      blob_write_bytes(metadata, prog->data->AtomicBuffers[i].StageReferences,
+                       sizeof(prog->data->AtomicBuffers[i].StageReferences));
+
+      for (unsigned j = 0; j < prog->data->AtomicBuffers[i].NumUniforms; j++) {
+         blob_write_uint32(metadata, prog->data->AtomicBuffers[i].Uniforms[j]);
+      }
+   }
+}
+
+static void
+read_atomic_buffers(struct blob_reader *metadata,
+                     struct gl_shader_program *prog)
+{
+   prog->data->NumAtomicBuffers = blob_read_uint32(metadata);
+   prog->data->AtomicBuffers =
+      rzalloc_array(prog, gl_active_atomic_buffer,
+                    prog->data->NumAtomicBuffers);
+
+   struct gl_active_atomic_buffer **stage_buff_list[MESA_SHADER_STAGES];
+   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+      if (prog->_LinkedShaders[i]) {
+         struct gl_program *glprog = prog->_LinkedShaders[i]->Program;
+
+         glprog->info.num_abos = blob_read_uint32(metadata);
+         glprog->sh.AtomicBuffers =
+            rzalloc_array(glprog, gl_active_atomic_buffer *,
+                          glprog->info.num_abos);
+         stage_buff_list[i] = glprog->sh.AtomicBuffers;
+      }
+   }
+
+   for (unsigned i = 0; i < prog->data->NumAtomicBuffers; i++) {
+      prog->data->AtomicBuffers[i].Binding = blob_read_uint32(metadata);
+      prog->data->AtomicBuffers[i].MinimumSize = blob_read_uint32(metadata);
+      prog->data->AtomicBuffers[i].NumUniforms = blob_read_uint32(metadata);
+
+      blob_copy_bytes(metadata,
+                      (uint8_t *) &prog->data->AtomicBuffers[i].StageReferences,
+                      sizeof(prog->data->AtomicBuffers[i].StageReferences));
+
+      prog->data->AtomicBuffers[i].Uniforms = rzalloc_array(prog, unsigned,
+         prog->data->AtomicBuffers[i].NumUniforms);
+
+      for (unsigned j = 0; j < prog->data->AtomicBuffers[i].NumUniforms; j++) {
+         prog->data->AtomicBuffers[i].Uniforms[j] = blob_read_uint32(metadata);
+      }
+
+      for (unsigned j = 0; j < MESA_SHADER_STAGES; j++) {
+         if (prog->data->AtomicBuffers[i].StageReferences[j]) {
+            *stage_buff_list[j] = &prog->data->AtomicBuffers[i];
+            stage_buff_list[j]++;
+         }
+      }
+   }
+}
+
+static void
+write_xfb(struct blob *metadata, struct gl_shader_program *shProg)
+{
+   struct gl_program *prog = shProg->last_vert_prog;
+
+   if (!prog) {
+      blob_write_uint32(metadata, ~0u);
+      return;
+   }
+
+   struct gl_transform_feedback_info *ltf = prog->sh.LinkedTransformFeedback;
+
+   blob_write_uint32(metadata, prog->info.stage);
+
+   blob_write_uint32(metadata, ltf->NumOutputs);
+   blob_write_uint32(metadata, ltf->ActiveBuffers);
+   blob_write_uint32(metadata, ltf->NumVarying);
+
+   blob_write_bytes(metadata, ltf->Outputs,
+                    sizeof(struct gl_transform_feedback_output) *
+                       ltf->NumOutputs);
+
+   for (int i = 0; i < ltf->NumVarying; i++) {
+      blob_write_string(metadata, ltf->Varyings[i].Name);
+      blob_write_uint32(metadata, ltf->Varyings[i].Type);
+      blob_write_uint32(metadata, ltf->Varyings[i].BufferIndex);
+      blob_write_uint32(metadata, ltf->Varyings[i].Size);
+      blob_write_uint32(metadata, ltf->Varyings[i].Offset);
+   }
+
+   blob_write_bytes(metadata, ltf->Buffers,
+                    sizeof(struct gl_transform_feedback_buffer) *
+                       MAX_FEEDBACK_BUFFERS);
+}
+
+static void
+read_xfb(struct blob_reader *metadata, struct gl_shader_program *shProg)
+{
+   unsigned xfb_stage = blob_read_uint32(metadata);
+
+   if (xfb_stage == ~0u)
+      return;
+
+   struct gl_program *prog = shProg->_LinkedShaders[xfb_stage]->Program;
+   struct gl_transform_feedback_info *ltf =
+      rzalloc(prog, struct gl_transform_feedback_info);
+
+   prog->sh.LinkedTransformFeedback = ltf;
+   shProg->last_vert_prog = prog;
+
+   ltf->NumOutputs = blob_read_uint32(metadata);
+   ltf->ActiveBuffers = blob_read_uint32(metadata);
+   ltf->NumVarying = blob_read_uint32(metadata);
+
+   ltf->Outputs = rzalloc_array(prog, struct gl_transform_feedback_output,
+                                ltf->NumOutputs);
+
+   blob_copy_bytes(metadata, (uint8_t *) ltf->Outputs,
+                   sizeof(struct gl_transform_feedback_output) *
+                      ltf->NumOutputs);
+
+   ltf->Varyings = rzalloc_array(prog,
+                                 struct gl_transform_feedback_varying_info,
+                                 ltf->NumVarying);
+
+   for (int i = 0; i < ltf->NumVarying; i++) {
+      ltf->Varyings[i].Name = ralloc_strdup(prog, blob_read_string(metadata));
+      ltf->Varyings[i].Type = blob_read_uint32(metadata);
+      ltf->Varyings[i].BufferIndex = blob_read_uint32(metadata);
+      ltf->Varyings[i].Size = blob_read_uint32(metadata);
+      ltf->Varyings[i].Offset = blob_read_uint32(metadata);
+   }
+
+   blob_copy_bytes(metadata, (uint8_t *) ltf->Buffers,
+                   sizeof(struct gl_transform_feedback_buffer) *
+                      MAX_FEEDBACK_BUFFERS);
+}
+
 static void
 write_uniforms(struct blob *metadata, struct gl_shader_program *prog)
 {
@@ -220,11 +568,14 @@ write_uniforms(struct blob *metadata, struct gl_shader_program *prog)
       blob_write_string(metadata, prog->data->UniformStorage[i].name);
       blob_write_uint32(metadata, prog->data->UniformStorage[i].storage -
                                   prog->data->UniformDataSlots);
+      blob_write_uint32(metadata, prog->data->UniformStorage[i].builtin);
       blob_write_uint32(metadata, prog->data->UniformStorage[i].remap_location);
       blob_write_uint32(metadata, prog->data->UniformStorage[i].block_index);
       blob_write_uint32(metadata, prog->data->UniformStorage[i].atomic_buffer_index);
       blob_write_uint32(metadata, prog->data->UniformStorage[i].offset);
       blob_write_uint32(metadata, prog->data->UniformStorage[i].array_stride);
+      blob_write_uint32(metadata, prog->data->UniformStorage[i].hidden);
+      blob_write_uint32(metadata, prog->data->UniformStorage[i].is_shader_storage);
       blob_write_uint32(metadata, prog->data->UniformStorage[i].matrix_stride);
       blob_write_uint32(metadata, prog->data->UniformStorage[i].row_major);
       blob_write_uint32(metadata,
@@ -236,6 +587,24 @@ write_uniforms(struct blob *metadata, struct gl_shader_program *prog)
       blob_write_bytes(metadata, prog->data->UniformStorage[i].opaque,
                        sizeof(prog->data->UniformStorage[i].opaque));
    }
+
+   /* Here we cache all uniform values. We do this to retain values for
+    * uniforms with initialisers and also hidden uniforms that may be lowered
+    * constant arrays. We could possibly just store the values we need but for
+    * now we just store everything.
+    */
+   blob_write_uint32(metadata, prog->data->NumHiddenUniforms);
+   for (unsigned i = 0; i < prog->data->NumUniformStorage; i++) {
+      if (!prog->data->UniformStorage[i].builtin &&
+          !prog->data->UniformStorage[i].is_shader_storage &&
+          prog->data->UniformStorage[i].block_index == -1) {
+         unsigned vec_size =
+            values_for_type(prog->data->UniformStorage[i].type) *
+            MAX2(prog->data->UniformStorage[i].array_elements, 1);
+         blob_write_bytes(metadata, prog->data->UniformStorage[i].storage,
+                          sizeof(union gl_constant_value) * vec_size);
+      }
+   }
 }
 
 static void
@@ -263,11 +632,14 @@ read_uniforms(struct blob_reader *metadata, struct gl_shader_program *prog)
       uniforms[i].array_elements = blob_read_uint32(metadata);
       uniforms[i].name = ralloc_strdup(prog, blob_read_string (metadata));
       uniforms[i].storage = data + blob_read_uint32(metadata);
+      uniforms[i].builtin = blob_read_uint32(metadata);
       uniforms[i].remap_location = blob_read_uint32(metadata);
       uniforms[i].block_index = blob_read_uint32(metadata);
       uniforms[i].atomic_buffer_index = blob_read_uint32(metadata);
       uniforms[i].offset = blob_read_uint32(metadata);
       uniforms[i].array_stride = blob_read_uint32(metadata);
+      uniforms[i].hidden = blob_read_uint32(metadata);
+      uniforms[i].is_shader_storage = blob_read_uint32(metadata);
       uniforms[i].matrix_stride = blob_read_uint32(metadata);
       uniforms[i].row_major = blob_read_uint32(metadata);
       uniforms[i].num_compatible_subroutines = blob_read_uint32(metadata);
@@ -279,6 +651,24 @@ read_uniforms(struct blob_reader *metadata, struct gl_shader_program *prog)
              blob_read_bytes(metadata, sizeof(uniforms[i].opaque)),
              sizeof(uniforms[i].opaque));
    }
+
+   /* Restore uniform values. */
+   prog->data->NumHiddenUniforms = blob_read_uint32(metadata);
+   for (unsigned i = 0; i < prog->data->NumUniformStorage; i++) {
+      if (!prog->data->UniformStorage[i].builtin &&
+          !prog->data->UniformStorage[i].is_shader_storage &&
+          prog->data->UniformStorage[i].block_index == -1) {
+         unsigned vec_size =
+            values_for_type(prog->data->UniformStorage[i].type) *
+            MAX2(prog->data->UniformStorage[i].array_elements, 1);
+         blob_copy_bytes(metadata,
+                         (uint8_t *) prog->data->UniformStorage[i].storage,
+                         sizeof(union gl_constant_value) * vec_size);
+
+        assert(vec_size + prog->data->UniformStorage[i].storage <=
+               data +  prog->data->NumUniformDataSlots);
+      }
+   }
 }
 
 enum uniform_remap_type
@@ -306,8 +696,8 @@ write_uniform_remap_table_entry(struct blob *metadata,
 }
 
 static void
-write_uniform_remap_table(struct blob *metadata,
-                          struct gl_shader_program *prog)
+write_uniform_remap_tables(struct blob *metadata,
+                           struct gl_shader_program *prog)
 {
    blob_write_uint32(metadata, prog->NumUniformRemapTable);
 
@@ -315,6 +705,20 @@ write_uniform_remap_table(struct blob *metadata,
       write_uniform_remap_table_entry(metadata, prog->data->UniformStorage,
                                       prog->UniformRemapTable[i]);
    }
+
+   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+      struct gl_linked_shader *sh = prog->_LinkedShaders[i];
+      if (sh) {
+         struct gl_program *glprog = sh->Program;
+         blob_write_uint32(metadata, glprog->sh.NumSubroutineUniformRemapTable);
+
+         for (unsigned j = 0; j < glprog->sh.NumSubroutineUniformRemapTable; j++) {
+            write_uniform_remap_table_entry(metadata,
+                                            prog->data->UniformStorage,
+                                            glprog->sh.SubroutineUniformRemapTable[j]);
+         }
+      }
+   }
 }
 
 static void
@@ -334,8 +738,8 @@ read_uniform_remap_table_entry(struct blob_reader *metadata,
 }
 
 static void
-read_uniform_remap_table(struct blob_reader *metadata,
-                         struct gl_shader_program *prog)
+read_uniform_remap_tables(struct blob_reader *metadata,
+                          struct gl_shader_program *prog)
 {
    prog->NumUniformRemapTable = blob_read_uint32(metadata);
 
@@ -349,6 +753,28 @@ read_uniform_remap_table(struct blob_reader *metadata,
       read_uniform_remap_table_entry(metadata, prog->data->UniformStorage,
                                      &prog->UniformRemapTable[i], type);
    }
+
+   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+      struct gl_linked_shader *sh = prog->_LinkedShaders[i];
+      if (sh) {
+         struct gl_program *glprog = sh->Program;
+         glprog->sh.NumSubroutineUniformRemapTable = blob_read_uint32(metadata);
+
+         glprog->sh.SubroutineUniformRemapTable =
+            rzalloc_array(glprog, struct gl_uniform_storage *,
+                          glprog->sh.NumSubroutineUniformRemapTable);
+
+         for (unsigned j = 0; j < glprog->sh.NumSubroutineUniformRemapTable; j++) {
+            enum uniform_remap_type type =
+               (enum uniform_remap_type) blob_read_uint32(metadata);
+
+            read_uniform_remap_table_entry(metadata,
+                                           prog->data->UniformStorage,
+                                           &glprog->sh.SubroutineUniformRemapTable[j],
+                                           type);
+         }
+      }
+   }
 }
 
 struct whte_closure
@@ -421,11 +847,29 @@ read_hash_tables(struct blob_reader *metadata, struct gl_shader_program *prog)
    read_hash_table(metadata, prog->FragDataIndexBindings);
 }
 
+static void
+write_shader_subroutine_index(struct blob *metadata,
+                              struct gl_linked_shader *sh,
+                              struct gl_program_resource *res)
+{
+   assert(sh);
+
+   for (unsigned j = 0; j < sh->Program->sh.NumSubroutineFunctions; j++) {
+      if (strcmp(((gl_subroutine_function *)res->Data)->name,
+                 sh->Program->sh.SubroutineFunctions[j].name) == 0) {
+         blob_write_uint32(metadata, j);
+         break;
+      }
+   }
+}
+
 static void
 write_program_resource_data(struct blob *metadata,
                             struct gl_shader_program *prog,
                             struct gl_program_resource *res)
 {
+   struct gl_linked_shader *sh;
+
    switch(res->Type) {
    case GL_PROGRAM_INPUT:
    case GL_PROGRAM_OUTPUT: {
@@ -442,6 +886,24 @@ write_program_resource_data(struct blob *metadata,
       blob_write_string(metadata, var->name);
       break;
    }
+   case GL_UNIFORM_BLOCK:
+      for (unsigned i = 0; i < prog->data->NumUniformBlocks; i++) {
+         if (strcmp(((gl_uniform_block *)res->Data)->Name,
+                    prog->data->UniformBlocks[i].Name) == 0) {
+            blob_write_uint32(metadata, i);
+            break;
+         }
+      }
+      break;
+   case GL_SHADER_STORAGE_BLOCK:
+      for (unsigned i = 0; i < prog->data->NumShaderStorageBlocks; i++) {
+         if (strcmp(((gl_uniform_block *)res->Data)->Name,
+                    prog->data->ShaderStorageBlocks[i].Name) == 0) {
+            blob_write_uint32(metadata, i);
+            break;
+         }
+      }
+      break;
    case GL_BUFFER_VARIABLE:
    case GL_VERTEX_SUBROUTINE_UNIFORM:
    case GL_GEOMETRY_SUBROUTINE_UNIFORM:
@@ -458,6 +920,43 @@ write_program_resource_data(struct blob *metadata,
          }
       }
       break;
+   case GL_ATOMIC_COUNTER_BUFFER:
+      for (unsigned i = 0; i < prog->data->NumAtomicBuffers; i++) {
+         if (((gl_active_atomic_buffer *)res->Data)->Binding ==
+             prog->data->AtomicBuffers[i].Binding) {
+            blob_write_uint32(metadata, i);
+            break;
+         }
+      }
+      break;
+   case GL_TRANSFORM_FEEDBACK_BUFFER:
+      for (unsigned i = 0; i < MAX_FEEDBACK_BUFFERS; i++) {
+         if (((gl_transform_feedback_buffer *)res->Data)->Binding ==
+             prog->last_vert_prog->sh.LinkedTransformFeedback->Buffers[i].Binding) {
+            blob_write_uint32(metadata, i);
+            break;
+         }
+      }
+      break;
+   case GL_TRANSFORM_FEEDBACK_VARYING:
+      for (int i = 0; i < prog->last_vert_prog->sh.LinkedTransformFeedback->NumVarying; i++) {
+         if (strcmp(((gl_transform_feedback_varying_info *)res->Data)->Name,
+                    prog->last_vert_prog->sh.LinkedTransformFeedback->Varyings[i].Name) == 0) {
+            blob_write_uint32(metadata, i);
+            break;
+         }
+      }
+      break;
+   case GL_VERTEX_SUBROUTINE:
+   case GL_TESS_CONTROL_SUBROUTINE:
+   case GL_TESS_EVALUATION_SUBROUTINE:
+   case GL_GEOMETRY_SUBROUTINE:
+   case GL_FRAGMENT_SUBROUTINE:
+   case GL_COMPUTE_SUBROUTINE:
+      sh =
+         prog->_LinkedShaders[_mesa_shader_stage_from_subroutine(res->Type)];
+      write_shader_subroutine_index(metadata, sh, res);
+      break;
    default:
       assert(!"Support for writing resource not yet implemented.");
    }
@@ -468,6 +967,8 @@ read_program_resource_data(struct blob_reader *metadata,
                            struct gl_shader_program *prog,
                            struct gl_program_resource *res)
 {
+   struct gl_linked_shader *sh;
+
    switch(res->Type) {
    case GL_PROGRAM_INPUT:
    case GL_PROGRAM_OUTPUT: {
@@ -487,6 +988,12 @@ read_program_resource_data(struct blob_reader *metadata,
       res->Data = var;
       break;
    }
+   case GL_UNIFORM_BLOCK:
+      res->Data = &prog->data->UniformBlocks[blob_read_uint32(metadata)];
+      break;
+   case GL_SHADER_STORAGE_BLOCK:
+      res->Data = &prog->data->ShaderStorageBlocks[blob_read_uint32(metadata)];
+      break;
    case GL_BUFFER_VARIABLE:
    case GL_VERTEX_SUBROUTINE_UNIFORM:
    case GL_GEOMETRY_SUBROUTINE_UNIFORM:
@@ -497,6 +1004,28 @@ read_program_resource_data(struct blob_reader *metadata,
    case GL_UNIFORM:
       res->Data = &prog->data->UniformStorage[blob_read_uint32(metadata)];
       break;
+   case GL_ATOMIC_COUNTER_BUFFER:
+      res->Data = &prog->data->AtomicBuffers[blob_read_uint32(metadata)];
+      break;
+   case GL_TRANSFORM_FEEDBACK_BUFFER:
+      res->Data = &prog->last_vert_prog->
+         sh.LinkedTransformFeedback->Buffers[blob_read_uint32(metadata)];
+      break;
+   case GL_TRANSFORM_FEEDBACK_VARYING:
+      res->Data = &prog->last_vert_prog->
+         sh.LinkedTransformFeedback->Varyings[blob_read_uint32(metadata)];
+      break;
+   case GL_VERTEX_SUBROUTINE:
+   case GL_TESS_CONTROL_SUBROUTINE:
+   case GL_TESS_EVALUATION_SUBROUTINE:
+   case GL_GEOMETRY_SUBROUTINE:
+   case GL_FRAGMENT_SUBROUTINE:
+   case GL_COMPUTE_SUBROUTINE:
+      sh =
+         prog->_LinkedShaders[_mesa_shader_stage_from_subroutine(res->Type)];
+      res->Data =
+         &sh->Program->sh.SubroutineFunctions[blob_read_uint32(metadata)];
+      break;
    default:
       assert(!"Support for reading resource not yet implemented.");
    }
@@ -572,6 +1101,7 @@ read_shader_parameters(struct blob_reader *metadata,
    uint32_t i = 0;
    uint32_t num_parameters = blob_read_uint32(metadata);
 
+   _mesa_reserve_parameter_storage(params, num_parameters);
    while (i < num_parameters) {
       gl_register_file type = (gl_register_file) blob_read_uint32(metadata);
       const char *name = blob_read_string(metadata);
@@ -608,6 +1138,11 @@ write_shader_metadata(struct blob *metadata, gl_linked_shader *shader)
                     sizeof(glprog->sh.SamplerTargets));
    blob_write_uint32(metadata, glprog->ShadowSamplers);
 
+   blob_write_bytes(metadata, glprog->sh.ImageAccess,
+                    sizeof(glprog->sh.ImageAccess));
+   blob_write_bytes(metadata, glprog->sh.ImageUnits,
+                    sizeof(glprog->sh.ImageUnits));
+
    write_shader_parameters(metadata, glprog->Parameters);
 }
 
@@ -626,6 +1161,11 @@ read_shader_metadata(struct blob_reader *metadata,
                    sizeof(glprog->sh.SamplerTargets));
    glprog->ShadowSamplers = blob_read_uint32(metadata);
 
+   blob_copy_bytes(metadata, (uint8_t *) glprog->sh.ImageAccess,
+                   sizeof(glprog->sh.ImageAccess));
+   blob_copy_bytes(metadata, (uint8_t *) glprog->sh.ImageUnits,
+                   sizeof(glprog->sh.ImageUnits));
+
    glprog->Parameters = _mesa_new_parameter_list();
    read_shader_parameters(metadata, glprog->Parameters);
 }
@@ -684,7 +1224,7 @@ shader_cache_write_program_metadata(struct gl_context *ctx,
    if (*prog->data->sha1 == 0)
       return;
 
-   struct blob *metadata = blob_create(NULL);
+   struct blob *metadata = blob_create();
 
    write_uniforms(metadata, prog);
 
@@ -709,7 +1249,15 @@ shader_cache_write_program_metadata(struct gl_context *ctx,
       }
    }
 
-   write_uniform_remap_table(metadata, prog);
+   write_xfb(metadata, prog);
+
+   write_uniform_remap_tables(metadata, prog);
+
+   write_atomic_buffers(metadata, prog);
+
+   write_buffer_blocks(metadata, prog);
+
+   write_subroutines(metadata, prog);
 
    write_program_resource_list(metadata, prog);
 
@@ -717,18 +1265,18 @@ shader_cache_write_program_metadata(struct gl_context *ctx,
    for (unsigned i = 0; i < prog->NumShaders; i++) {
       disk_cache_put_key(cache, prog->Shaders[i]->sha1);
       if (ctx->_Shader->Flags & GLSL_CACHE_INFO) {
-         fprintf(stderr, "marking shader: %s\n",
-                 _mesa_sha1_format(sha1_buf, prog->Shaders[i]->sha1));
+         _mesa_sha1_format(sha1_buf, prog->Shaders[i]->sha1);
+         fprintf(stderr, "marking shader: %s\n", sha1_buf);
       }
    }
 
    disk_cache_put(cache, prog->data->sha1, metadata->data, metadata->size);
 
-   ralloc_free(metadata);
+   free(metadata);
 
    if (ctx->_Shader->Flags & GLSL_CACHE_INFO) {
-      fprintf(stderr, "putting program metadata in cache: %s\n",
-              _mesa_sha1_format(sha1_buf, prog->data->sha1));
+      _mesa_sha1_format(sha1_buf, prog->data->sha1);
+      fprintf(stderr, "putting program metadata in cache: %s\n", sha1_buf);
    }
 }
 
@@ -743,7 +1291,7 @@ shader_cache_read_program_metadata(struct gl_context *ctx,
       return false;
 
    struct disk_cache *cache = ctx->Cache;
-   if (!cache)
+   if (!cache || prog->data->cache_fallback)
       return false;
 
    /* Include bindings when creating sha1. These bindings change the resulting
@@ -762,14 +1310,28 @@ shader_cache_read_program_metadata(struct gl_context *ctx,
    ralloc_asprintf_append(&buf, "sso: %s\n",
                           prog->SeparateShader ? "T" : "F");
 
+   /* A shader might end up producing different output depending on the glsl
+    * version supported by the compiler. For example a different path might be
+    * taken by the preprocessor, so add the version to the hash input.
+    */
+   ralloc_asprintf_append(&buf, "api: %d glsl: %d fglsl: %d\n",
+                          ctx->API, ctx->Const.GLSLVersion,
+                          ctx->Const.ForceGLSLVersion);
+
+   /* DRI config options may also change the output from the compiler so
+    * include them as an input to sha1 creation.
+    */
    char sha1buf[41];
+   _mesa_sha1_format(sha1buf, ctx->Const.dri_config_options_sha1);
+   ralloc_strcat(&buf, sha1buf);
+
    for (unsigned i = 0; i < prog->NumShaders; i++) {
       struct gl_shader *sh = prog->Shaders[i];
+      _mesa_sha1_format(sha1buf, sh->sha1);
       ralloc_asprintf_append(&buf, "%s: %s\n",
-                             _mesa_shader_stage_to_abbrev(sh->Stage),
-                             _mesa_sha1_format(sha1buf, sh->sha1));
+                             _mesa_shader_stage_to_abbrev(sh->Stage), sha1buf);
    }
-   _mesa_sha1_compute(buf, strlen(buf), prog->data->sha1);
+   disk_cache_compute_key(cache, buf, strlen(buf), prog->data->sha1);
    ralloc_free(buf);
 
    size_t size;
@@ -791,8 +1353,9 @@ shader_cache_read_program_metadata(struct gl_context *ctx,
    }
 
    if (ctx->_Shader->Flags & GLSL_CACHE_INFO) {
+      _mesa_sha1_format(sha1buf, prog->data->sha1);
       fprintf(stderr, "loading shader program meta data from cache: %s\n",
-              _mesa_sha1_format(sha1buf, prog->data->sha1));
+              sha1buf);
    }
 
    struct blob_reader metadata;
@@ -814,7 +1377,15 @@ shader_cache_read_program_metadata(struct gl_context *ctx,
                                        &metadata);
    }
 
-   read_uniform_remap_table(&metadata, prog);
+   read_xfb(&metadata, prog);
+
+   read_uniform_remap_tables(&metadata, prog);
+
+   read_atomic_buffers(&metadata, prog);
+
+   read_buffer_blocks(&metadata, prog);
+
+   read_subroutines(&metadata, prog);
 
    read_program_resource_list(&metadata, prog);