summaryrefslogtreecommitdiffstats
path: root/src/mesa
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa')
-rw-r--r--src/mesa/main/mtypes.h2
-rw-r--r--src/mesa/vbo/vbo_minmax_index.c34
2 files changed, 34 insertions, 2 deletions
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 6099ae1c463..58064aac1cd 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -1286,6 +1286,8 @@ struct gl_buffer_object
/** Memoization of min/max index computations for static index buffers */
struct hash_table *MinMaxCache;
+ unsigned MinMaxCacheHitIndices;
+ unsigned MinMaxCacheMissIndices;
bool MinMaxCacheDirty;
};
diff --git a/src/mesa/vbo/vbo_minmax_index.c b/src/mesa/vbo/vbo_minmax_index.c
index 47b0d9cf2a3..0f75a87f3f3 100644
--- a/src/mesa/vbo/vbo_minmax_index.c
+++ b/src/mesa/vbo/vbo_minmax_index.c
@@ -117,9 +117,24 @@ vbo_get_minmax_cached(struct gl_buffer_object *bufferObj,
mtx_lock(&bufferObj->Mutex);
if (bufferObj->MinMaxCacheDirty) {
+ /* Disable the cache permanently for this BO if the number of hits
+ * is asymptotically less than the number of misses. This happens when
+ * applications use the BO for streaming.
+ *
+ * However, some initial optimism allows applications that interleave
+ * draw calls with glBufferSubData during warmup.
+ */
+ unsigned optimism = bufferObj->Size;
+ if (bufferObj->MinMaxCacheMissIndices > optimism &&
+ bufferObj->MinMaxCacheHitIndices < bufferObj->MinMaxCacheMissIndices - optimism) {
+ bufferObj->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE;
+ vbo_delete_minmax_cache(bufferObj);
+ goto out_disable;
+ }
+
_mesa_hash_table_clear(bufferObj->MinMaxCache, vbo_minmax_cache_delete_entry);
bufferObj->MinMaxCacheDirty = false;
- goto out;
+ goto out_invalidate;
}
key.type = type;
@@ -134,7 +149,22 @@ vbo_get_minmax_cached(struct gl_buffer_object *bufferObj,
found = GL_TRUE;
}
-out:
+out_invalidate:
+ if (found) {
+ /* The hit counter saturates so that we don't accidently disable the
+ * cache in a long-running program.
+ */
+ unsigned new_hit_count = bufferObj->MinMaxCacheHitIndices + count;
+
+ if (new_hit_count >= bufferObj->MinMaxCacheHitIndices)
+ bufferObj->MinMaxCacheHitIndices = new_hit_count;
+ else
+ bufferObj->MinMaxCacheHitIndices = ~(unsigned)0;
+ } else {
+ bufferObj->MinMaxCacheMissIndices += count;
+ }
+
+out_disable:
mtx_unlock(&bufferObj->Mutex);
return found;
}