+ /* Reserve all the explicit locations of the active subroutine uniforms. */
+ for (unsigned i = 0; i < num_uniforms; i++) {
+ if (!uniforms[i].type->is_subroutine())
+ continue;
+
+ if (uniforms[i].remap_location == UNMAPPED_UNIFORM_LOC)
+ continue;
+
+ for (unsigned j = 0; j < MESA_SHADER_STAGES; j++) {
+ struct gl_shader *sh = prog->_LinkedShaders[j];
+ if (!sh)
+ continue;
+
+ if (!uniforms[i].subroutine[j].active)
+ continue;
+
+ /* How many new entries for this uniform? */
+ const unsigned entries = MAX2(1, uniforms[i].array_elements);
+
+ /* Set remap table entries point to correct gl_uniform_storage. */
+ for (unsigned k = 0; k < entries; k++) {
+ unsigned element_loc = uniforms[i].remap_location + k;
+ assert(sh->SubroutineUniformRemapTable[element_loc] ==
+ INACTIVE_UNIFORM_EXPLICIT_LOCATION);
+ sh->SubroutineUniformRemapTable[element_loc] = &uniforms[i];
+ }
+ }
+ }
+
+ /* reserve subroutine locations */
+ for (unsigned i = 0; i < num_uniforms; i++) {
+
+ if (!uniforms[i].type->is_subroutine())
+ continue;
+ const unsigned entries = MAX2(1, uniforms[i].array_elements);
+
+ if (uniforms[i].remap_location != UNMAPPED_UNIFORM_LOC)
+ continue;
+ for (unsigned j = 0; j < MESA_SHADER_STAGES; j++) {
+ struct gl_shader *sh = prog->_LinkedShaders[j];
+ if (!sh)
+ continue;
+
+ if (!uniforms[i].subroutine[j].active)
+ continue;
+
+ sh->SubroutineUniformRemapTable =
+ reralloc(sh,
+ sh->SubroutineUniformRemapTable,
+ gl_uniform_storage *,
+ sh->NumSubroutineUniformRemapTable + entries);
+
+ for (unsigned k = 0; k < entries; k++)
+ sh->SubroutineUniformRemapTable[sh->NumSubroutineUniformRemapTable + k] = &uniforms[i];
+ uniforms[i].remap_location = sh->NumSubroutineUniformRemapTable;
+ sh->NumSubroutineUniformRemapTable += entries;
+ }
+ }
+