summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <michel.daenzer@amd.com>2016-12-16 11:17:44 +0900
committerMichel Dänzer <michel@daenzer.net>2016-12-19 17:51:34 +0900
commit95eb5e4eed6ef80e44dc4b15f0b8560857dba263 (patch)
tree8443b910ffc181e20a3234394b93c4b8040afd27
parent745e2eaaec1f938184f3e9a2acfacf7e02ce0da8 (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.c44
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)