summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGregory Hainaut <[email protected]>2016-06-24 10:07:02 +0200
committerTimothy Arceri <[email protected]>2016-07-05 16:44:31 +1000
commit6a524c76f502fe15bb3612065a23ece693aed237 (patch)
tree3ca20d9043342502b503abc81b44d489870215db
parentcb728df9670d8399479db8502145bbc6f653cfb3 (diff)
mesa: faster validation of sampler unit mapping for SSO
Code was inspired from _mesa_update_shader_textures_used However unlike _mesa_update_shader_textures_used that only check for a single stage, it will check all stages. It avoids to loop on all uniforms, only active samplers are checked. For my use case: high FS frequency switches with few samplers. Perf event (relative to nouveau_dri.so) goes from 5.01% to 1.68% for the _mesa_sampler_uniforms_pipeline_are_valid function. Signed-off-by: Gregory Hainaut <[email protected]> Reviewed-by: Timothy Arceri <[email protected]>
-rw-r--r--src/mesa/main/uniform_query.cpp69
1 files changed, 31 insertions, 38 deletions
diff --git a/src/mesa/main/uniform_query.cpp b/src/mesa/main/uniform_query.cpp
index 67375a17f48..ebe52253d58 100644
--- a/src/mesa/main/uniform_query.cpp
+++ b/src/mesa/main/uniform_query.cpp
@@ -1068,58 +1068,51 @@ _mesa_sampler_uniforms_pipeline_are_valid(struct gl_pipeline_object *pipeline)
* - The number of active samplers in the program exceeds the
* maximum number of texture image units allowed."
*/
+
+ GLbitfield mask;
+ GLbitfield TexturesUsed[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
+ struct gl_shader *shader;
unsigned active_samplers = 0;
const struct gl_shader_program **shProg =
(const struct gl_shader_program **) pipeline->CurrentProgram;
- const glsl_type *unit_types[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
- memset(unit_types, 0, sizeof(unit_types));
+
+ memset(TexturesUsed, 0, sizeof(TexturesUsed));
for (unsigned idx = 0; idx < ARRAY_SIZE(pipeline->CurrentProgram); idx++) {
if (!shProg[idx])
continue;
- for (unsigned i = 0; i < shProg[idx]->NumUniformStorage; i++) {
- const struct gl_uniform_storage *const storage =
- &shProg[idx]->UniformStorage[i];
+ shader = shProg[idx]->_LinkedShaders[idx];
+ if (!shader || !shader->Program)
+ continue;
- if (!storage->type->is_sampler())
+ mask = shader->Program->SamplersUsed;
+ while (mask) {
+ const int s = u_bit_scan(&mask);
+ GLuint unit = shader->SamplerUnits[s];
+ GLuint tgt = shader->SamplerTargets[s];
+
+ /* FIXME: Samplers are initialized to 0 and Mesa doesn't do a
+ * great job of eliminating unused uniforms currently so for now
+ * don't throw an error if two sampler types both point to 0.
+ */
+ if (unit == 0)
continue;
- active_samplers++;
-
- const unsigned count = MAX2(1, storage->array_elements);
- for (unsigned j = 0; j < count; j++) {
- const unsigned unit = storage->storage[j].i;
-
- /* FIXME: Samplers are initialized to 0 and Mesa doesn't do a
- * great job of eliminating unused uniforms currently so for now
- * don't throw an error if two sampler types both point to 0.
- */
- if (unit == 0)
- continue;
-
- /* The types of the samplers associated with a particular texture
- * unit must be an exact match. Page 74 (page 89 of the PDF) of
- * the OpenGL 3.3 core spec says:
- *
- * "It is not allowed to have variables of different sampler
- * types pointing to the same texture image unit within a
- * program object."
- */
- if (unit_types[unit] == NULL) {
- unit_types[unit] = storage->type;
- } else if (unit_types[unit] != storage->type) {
- pipeline->InfoLog =
- ralloc_asprintf(pipeline,
- "Texture unit %d is accessed both as %s "
- "and %s",
- unit, unit_types[unit]->name,
- storage->type->name);
- return false;
- }
+ if (TexturesUsed[unit] & ~(1 << tgt)) {
+ pipeline->InfoLog =
+ ralloc_asprintf(pipeline,
+ "Program %d: "
+ "Texture unit %d is accessed with 2 different types",
+ shProg[idx]->Name, unit);
+ return false;
}
+
+ TexturesUsed[unit] |= (1 << tgt);
}
+
+ active_samplers += shader->num_samplers;
}
if (active_samplers > MAX_COMBINED_TEXTURE_IMAGE_UNITS) {