radeonsi: don't create an infinite number of variants

If a shader has code like this:

   uniform float timestamp;
   ...
   if (timestamp > 0.0)
      do_something()

And timestamp is modified each frame, we'll end up generating a new
variant per frame.

This commit introduces a hard limit on the number of variants we generate
for a single shader.

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/5121
Fixes: b7501184b9 ("radeonsi: implement inlinable uniforms")
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12138>
This commit is contained in:
Pierre-Eric Pelloux-Prayer 2021-07-30 11:48:28 +02:00 committed by Marge Bot
parent 20055a307d
commit 9fe8ae3fcd
2 changed files with 26 additions and 2 deletions

View File

@ -698,6 +698,9 @@ struct si_shader_key {
unsigned inline_uniforms:1;
/* This must be kept last to limit the number of variants
* depending only on the uniform values.
*/
uint32_t inlined_uniform_values[MAX_INLINABLE_UNIFORMS];
} opt;
};

View File

@ -2243,10 +2243,31 @@ current_not_ready:
simple_mtx_lock(&sel->mutex);
/* Compute the size of the key without the uniform values. */
size_t s = (void*)&key->opt.inlined_uniform_values - (void*)key;
int variant_count = 0;
const int max_inline_uniforms_variants = 5;
/* Find the shader variant. */
for (iter = sel->first_variant; iter; iter = iter->next_variant) {
/* Don't check the "current" shader. We checked it above. */
if (current != iter && memcmp(&iter->key, key, sizeof(*key)) == 0) {
if (memcmp(&iter->key, key, s) == 0) {
/* Check the inlined uniform values separatly, and count
* the number of variants based on them.
*/
if (key->opt.inline_uniforms &&
memcmp(iter->key.opt.inlined_uniform_values,
key->opt.inlined_uniform_values,
MAX_INLINABLE_UNIFORMS * 4) != 0) {
if (variant_count++ > max_inline_uniforms_variants) {
/* Too many variants. Disable inlining for this shader. */
key->opt.inline_uniforms = 0;
memset(key->opt.inlined_uniform_values, 0, MAX_INLINABLE_UNIFORMS * 4);
simple_mtx_unlock(&sel->mutex);
goto again;
}
continue;
}
simple_mtx_unlock(&sel->mutex);
if (unlikely(!util_queue_fence_is_signalled(&iter->ready))) {