From 95eb5e4eed6ef80e44dc4b15f0b8560857dba263 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Michel=20D=C3=A4nzer?= Date: Fri, 16 Dec 2016 11:17:44 +0900 Subject: [PATCH] cso: Make sanitize_hash safe for samplers MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 --- src/gallium/auxiliary/cso_cache/cso_context.c | 44 ++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c index 6031cfc..469ab9c 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) -- 2.7.4