summaryrefslogtreecommitdiffstats
path: root/src/compiler/glsl/link_uniforms.cpp
diff options
context:
space:
mode:
authorPlamena Manolova <[email protected]>2016-02-11 15:00:02 +0200
committerTapani Pälli <[email protected]>2016-02-18 11:53:35 +0200
commit65dfb3048e8291675ca33581aeff8921f7ea509d (patch)
tree8a2aba1e5b5460df1eff630bfcda3ba0b4524d88 /src/compiler/glsl/link_uniforms.cpp
parentd335b6abc0eaa7506203df7c99898645214b4c72 (diff)
compiler/glsl: Fix uniform location counting.
This patch moves the calculation of current uniforms to link_uniforms, which makes use of UniformRemapTable which stores all the reserved uniform locations. Location assignment for implicit uniforms now tries to use any gaps left in the table after the location assignment for explicit uniforms. This gives us more space to store more uniforms. Patch is based on earlier patch with following changes/additions: 1: Move the counting of explicit locations to check_explicit_uniform_locations and then pass the number to link_assign_uniform_locations. 2: Count the number of empty slots in UniformRemapTable and store them in a list_head. 3: Try to find an empty slot for implicit locations from the list, if that fails resize UniformRemapTable. Fixes following CTS tests: ES31-CTS.explicit_uniform_location.uniform-loc-mix-with-implicit-max ES31-CTS.explicit_uniform_location.uniform-loc-mix-with-implicit-max-array Signed-off-by: Tapani Pälli <[email protected]> Signed-off-by: Plamena Manolova <[email protected]> Reviewed-by: Ilia Mirkin <[email protected]> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=93696
Diffstat (limited to 'src/compiler/glsl/link_uniforms.cpp')
-rw-r--r--src/compiler/glsl/link_uniforms.cpp80
1 files changed, 70 insertions, 10 deletions
diff --git a/src/compiler/glsl/link_uniforms.cpp b/src/compiler/glsl/link_uniforms.cpp
index d18a2f2a1bc..deaba94df1c 100644
--- a/src/compiler/glsl/link_uniforms.cpp
+++ b/src/compiler/glsl/link_uniforms.cpp
@@ -1038,9 +1038,43 @@ assign_hidden_uniform_slot_id(const char *name, unsigned hidden_id,
uniform_size->map->put(hidden_uniform_start + hidden_id, name);
}
+/**
+ * Search through the list of empty blocks to find one that fits the current
+ * uniform.
+ */
+static int
+find_empty_block(struct gl_shader_program *prog,
+ struct gl_uniform_storage *uniform)
+{
+ const unsigned entries = MAX2(1, uniform->array_elements);
+
+ foreach_list_typed(struct empty_uniform_block, block, link,
+ &prog->EmptyUniformLocations) {
+ /* Found a block with enough slots to fit the uniform */
+ if (block->slots == entries) {
+ unsigned start = block->start;
+ exec_node_remove(&block->link);
+ ralloc_free(block);
+
+ return start;
+ /* Found a block with more slots than needed. It can still be used. */
+ } else if (block->slots > entries) {
+ unsigned start = block->start;
+ block->start += entries;
+ block->slots -= entries;
+
+ return start;
+ }
+ }
+
+ return -1;
+}
+
void
link_assign_uniform_locations(struct gl_shader_program *prog,
- unsigned int boolean_true)
+ unsigned int boolean_true,
+ unsigned int num_explicit_uniform_locs,
+ unsigned int max_uniform_locs)
{
ralloc_free(prog->UniformStorage);
prog->UniformStorage = NULL;
@@ -1131,6 +1165,9 @@ link_assign_uniform_locations(struct gl_shader_program *prog,
parcel_out_uniform_storage parcel(prog, prog->UniformHash, uniforms, data);
+ unsigned total_entries = num_explicit_uniform_locs;
+ unsigned empty_locs = prog->NumUniformRemapTable - num_explicit_uniform_locs;
+
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
if (prog->_LinkedShaders[i] == NULL)
continue;
@@ -1194,21 +1231,44 @@ link_assign_uniform_locations(struct gl_shader_program *prog,
/* 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]);
+
+ /* Add new entries to the total amount of entries. */
+ total_entries += entries;
+
+ if (chosen_location != -1) {
+ empty_locs -= entries;
+ } else {
+ chosen_location = prog->NumUniformRemapTable;
+
+ /* 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;
+ }
+
+ /* Verify that total amount of entries for explicit and implicit locations
+ * is less than MAX_UNIFORM_LOCATIONS.
+ */
- prog->NumUniformRemapTable += entries;
+ if (total_entries > max_uniform_locs) {
+ linker_error(prog, "count of uniform locations > MAX_UNIFORM_LOCATIONS"
+ "(%u > %u)", total_entries, max_uniform_locs);
}
/* Reserve all the explicit locations of the active subroutine uniforms. */