diff options
author | Michel Dänzer <michel.daenzer@amd.com> | 2016-12-16 11:17:44 +0900 |
---|---|---|
committer | Michel Dänzer <michel@daenzer.net> | 2016-12-19 17:51:34 +0900 |
commit | 95eb5e4eed6ef80e44dc4b15f0b8560857dba263 (patch) | |
tree | 8443b910ffc181e20a3234394b93c4b8040afd27 | |
parent | 745e2eaaec1f938184f3e9a2acfacf7e02ce0da8 (diff) |
cso: Make sanitize_hash safe for samplers
Remove currently bound sampler states from the hash table before pruning
entries from the hash table, so they cannot accidentally be deleted by
the pruning.
Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
-rw-r--r-- | src/gallium/auxiliary/cso_cache/cso_context.c | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c index 6031cfc0d2..469ab9cdbc 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.c +++ b/src/gallium/auxiliary/cso_cache/cso_context.c @@ -220,19 +220,61 @@ sanitize_hash(struct cso_hash *hash, enum cso_cache_type type, int hash_size = cso_hash_size(hash); int max_entries = (max_size > hash_size) ? max_size : hash_size; int to_remove = (max_size < max_entries) * max_entries/4; - struct cso_hash_iter iter = cso_hash_first_node(hash); + struct cso_hash_iter iter; + struct cso_sampler **samplers_to_restore = NULL; + unsigned to_restore = 0; + if (hash_size > max_size) to_remove += hash_size - max_size; + + if (to_remove == 0) + return; + + if (type == CSO_SAMPLER) { + int i, j; + + samplers_to_restore = MALLOC(PIPE_SHADER_TYPES * PIPE_MAX_SAMPLERS * + sizeof(*samplers_to_restore)); + + /* Temporarily remove currently bound sampler states from the hash + * table, to prevent them from being deleted + */ + for (i = 0; i < PIPE_SHADER_TYPES; i++) { + for (j = 0; j < ctx->samplers[i].nr_samplers; j++) { + struct cso_sampler *sampler = ctx->samplers[i].cso_samplers[j]; + + if (sampler && cso_hash_take(hash, sampler->hash_key)) + samplers_to_restore[to_restore++] = sampler; + } + } + } + + iter = cso_hash_first_node(hash); while (to_remove) { /*remove elements until we're good */ /*fixme: currently we pick the nodes to remove at random*/ void *cso = cso_hash_iter_data(iter); + + if (!cso) + break; + if (delete_cso(ctx, cso, type)) { iter = cso_hash_erase(hash, iter); --to_remove; } else iter = cso_hash_iter_next(iter); } + + if (type == CSO_SAMPLER) { + /* Put currently bound sampler states back into the hash table */ + while (to_restore--) { + struct cso_sampler *sampler = samplers_to_restore[to_restore]; + + cso_hash_insert(hash, sampler->hash_key, sampler); + } + + FREE(samplers_to_restore); + } } static void cso_init_vbuf(struct cso_context *cso) |