uniform_size->map->put(hidden_uniform_start + hidden_id, name);
}
+/**
+ * Search UniformRemapTable for empty block big enough to hold given uniform.
+ * TODO Optimize this algorithm later if it turns out to be a major bottleneck.
+ */
+static int
+find_empty_block(struct gl_shader_program *prog,
+ struct gl_uniform_storage *uniform)
+{
+ const unsigned entries = MAX2(1, uniform->array_elements);
+ for (unsigned i = 0, j; i < prog->NumUniformRemapTable; i++) {
+ /* We found empty space in UniformRemapTable. */
+ if (prog->UniformRemapTable[i] == NULL) {
+ for (j = i; j < entries && j < prog->NumUniformRemapTable; j++) {
+ if (prog->UniformRemapTable[j] != NULL) {
+ /* Entries do not fit in this space, continue searching
+ * after this location.
+ */
+ i = j + 1;
+ break;
+ }
+ }
+ /* Entries fit, we can return this location. */
+ if (i != j + 1) {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
void
link_assign_uniform_locations(struct gl_shader_program *prog,
- unsigned int boolean_true)
+ unsigned int boolean_true,
+ unsigned int max_locations)
{
ralloc_free(prog->UniformStorage);
prog->UniformStorage = NULL;
parcel_out_uniform_storage parcel(prog->UniformHash, uniforms, data);
+ unsigned total_entries = 0;
+
+ /* Calculate amount of 'holes' left after explicit locations were
+ * reserved from UniformRemapTable.
+ */
+ unsigned empty_locs = 0;
+ for (unsigned i = 0; i < prog->NumUniformRemapTable; i++)
+ if (prog->UniformRemapTable[i] == NULL)
+ empty_locs++;
+
+ /* Add all the reserved explicit locations - empty locations in remap table. */
+ if (prog->NumUniformRemapTable)
+ total_entries = (prog->NumUniformRemapTable - 1) - empty_locs;
+
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
if (prog->_LinkedShaders[i] == NULL)
continue;
/* how many new entries for this uniform? */
const unsigned entries = MAX2(1, uniforms[i].array_elements);
- /* resize remap table to fit new entries */
- prog->UniformRemapTable =
- reralloc(prog,
- prog->UniformRemapTable,
- gl_uniform_storage *,
- prog->NumUniformRemapTable + entries);
+ /* Find UniformRemapTable for empty blocks where we can fit this uniform. */
+ int chosen_location = -1;
+
+ if (empty_locs)
+ chosen_location = find_empty_block(prog, &uniforms[i]);
+
+ if (chosen_location != -1) {
+ empty_locs -= entries;
+ } else {
+ chosen_location = prog->NumUniformRemapTable;
+
+ /* Add new entries to the total amount of entries. */
+ total_entries += entries;
+
+ /* resize remap table to fit new entries */
+ prog->UniformRemapTable =
+ reralloc(prog,
+ prog->UniformRemapTable,
+ gl_uniform_storage *,
+ prog->NumUniformRemapTable + entries);
+ prog->NumUniformRemapTable += entries;
+ }
/* set pointers for this uniform */
for (unsigned j = 0; j < entries; j++)
- prog->UniformRemapTable[prog->NumUniformRemapTable+j] = &uniforms[i];
+ prog->UniformRemapTable[chosen_location + j] = &uniforms[i];
/* set the base location in remap table for the uniform */
- uniforms[i].remap_location = prog->NumUniformRemapTable;
+ uniforms[i].remap_location = chosen_location;
+ }
- prog->NumUniformRemapTable += entries;
+ /* Verify that total amount of entries for explicit and implicit locations
+ * is less than MAX_UNIFORM_LOCATIONS.
+ */
+ if (total_entries >= max_locations) {
+ linker_error(prog, "count of uniform locations >= MAX_UNIFORM_LOCATIONS"
+ "(%u >= %u)", total_entries, max_locations);
}
/* Reserve all the explicit locations of the active subroutine uniforms. */
return;
}
- unsigned entries_total = 0;
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
struct gl_shader *sh = prog->_LinkedShaders[i];
if (!var || var->data.mode != ir_var_uniform)
continue;
- entries_total += var->type->uniform_locations();
-
if (var->data.explicit_location) {
bool ret;
if (var->type->without_array()->is_subroutine())
}
}
}
-
- /* Verify that total amount of entries for explicit and implicit locations
- * is less than MAX_UNIFORM_LOCATIONS.
- */
- if (entries_total >= ctx->Const.MaxUserAssignableUniformLocations) {
- linker_error(prog, "count of uniform locations >= MAX_UNIFORM_LOCATIONS"
- "(%u >= %u)", entries_total,
- ctx->Const.MaxUserAssignableUniformLocations);
- }
delete uniform_map;
}
goto done;
update_array_sizes(prog);
- link_assign_uniform_locations(prog, ctx->Const.UniformBooleanTrue);
+ link_assign_uniform_locations(prog, ctx->Const.UniformBooleanTrue,
+ ctx->Const.MaxUserAssignableUniformLocations);
+
+ if (!prog->LinkStatus)
+ goto done;
+
link_assign_atomic_counter_resources(ctx, prog);
store_fragdepth_layout(prog);