* consumers use structured keys).
*
* Replacement is not implemented. Instead, when the cache gets too big, at
- * a safe point (unlock) we throw out all of the cache data let it regenerate
- * it for the next rendering operation.
+ * a safe point (unlock) we throw out all of the cache data and let it
+ * regenerate for the next rendering operation.
*
* The reloc_buf pointers need to be included as key data, otherwise the
* non-unique values stuffed in the offset in key data through
#include "brw_state.h"
#include "intel_batchbuffer.h"
-#include "imports.h"
+#include "main/imports.h"
/* XXX: Fixme - have to include these to get the sizes of the prog_key
* structs:
#include "brw_sf.h"
#include "brw_gs.h"
-static GLuint hash_key( const void *key, GLuint key_size )
+static GLuint hash_key( const void *key, GLuint key_size,
+ dri_bo **reloc_bufs, GLuint nr_reloc_bufs)
{
GLuint *ikey = (GLuint *)key;
GLuint hash = 0, i;
/* I'm sure this can be improved on:
*/
- for (i = 0; i < key_size/4; i++)
+ for (i = 0; i < key_size/4; i++) {
hash ^= ikey[i];
+ hash = (hash << 5) | (hash >> 27);
+ }
+
+ /* Include the BO pointers as key data as well */
+ ikey = (GLuint *)reloc_bufs;
+ key_size = nr_reloc_bufs * sizeof(dri_bo *);
+ for (i = 0; i < key_size/4; i++) {
+ hash ^= ikey[i];
+ hash = (hash << 5) | (hash >> 27);
+ }
return hash;
}
update_cache_last(struct brw_cache *cache, enum brw_cache_id cache_id,
dri_bo *bo)
{
+ if (bo == cache->last_bo[cache_id])
+ return; /* no change */
+
dri_bo_unreference(cache->last_bo[cache_id]);
cache->last_bo[cache_id] = bo;
dri_bo_reference(cache->last_bo[cache_id]);
{
struct brw_cache_item *c;
+#if 0
+ int bucketcount = 0;
+
+ for (c = cache->items[hash % cache->size]; c; c = c->next)
+ bucketcount++;
+
+ fprintf(stderr, "bucket %d/%d = %d/%d items\n", hash % cache->size,
+ cache->size, bucketcount, cache->n_items);
+#endif
+
for (c = cache->items[hash % cache->size]; c; c = c->next) {
if (c->cache_id == cache_id &&
c->hash == hash &&
void *aux_return )
{
struct brw_cache_item *item;
- GLuint hash = hash_key(key, key_size);
+ GLuint hash = hash_key(key, key_size, reloc_bufs, nr_reloc_bufs);
item = search_cache(cache, cache_id, hash, key, key_size,
reloc_bufs, nr_reloc_bufs);
void *aux_return )
{
struct brw_cache_item *item = CALLOC_STRUCT(brw_cache_item);
- GLuint hash = hash_key(key, key_size);
+ GLuint hash = hash_key(key, key_size, reloc_bufs, nr_reloc_bufs);
GLuint relocs_size = nr_reloc_bufs * sizeof(dri_bo *);
GLuint aux_size = cache->aux_size[cache_id];
void *tmp;
/* Create the buffer object to contain the data */
bo = dri_bo_alloc(cache->brw->intel.bufmgr,
- cache->name[cache_id], data_size, 1 << 6,
- DRM_BO_FLAG_MEM_LOCAL |
- DRM_BO_FLAG_CACHED |
- DRM_BO_FLAG_CACHED_MAPPED);
+ cache->name[cache_id], data_size, 1 << 6);
/* Set up the memory containing the key, aux_data, and reloc_bufs */
if (INTEL_DEBUG & DEBUG_STATE)
_mesa_printf("upload %s: %d bytes to cache id %d\n",
cache->name[cache_id],
- data_size);
+ data_size, cache_id);
/* Copy data to the buffer */
dri_bo_subdata(bo, 0, data_size, data);
{
dri_bo *bo;
struct brw_cache_item *item;
- GLuint hash = hash_key(data, data_size);
+ GLuint hash = hash_key(data, data_size, reloc_bufs, nr_reloc_bufs);
item = search_cache(cache, cache_id, hash, data, data_size,
reloc_bufs, nr_reloc_bufs);
if (item) {
+ update_cache_last(cache, cache_id, item->bo);
dri_bo_reference(item->bo);
return item->bo;
}
0);
}
-
-/* When we lose hardware context, need to invalidate the surface cache
- * as these structs must be explicitly re-uploaded. They are subject
- * to fixup by the memory manager as they contain absolute agp
- * offsets, so we need to ensure there is a fresh version of the
- * struct available to receive the fixup.
- *
- * XXX: Need to ensure that there aren't two versions of a surface or
- * bufferobj with different backing data active in the same buffer at
- * once? Otherwise the cache could confuse them. Maybe better not to
- * cache at all?
- *
- * --> Isn't this the same as saying need to ensure batch is flushed
- * before new data is uploaded to an existing buffer? We
- * already try to make sure of that.
- */
-static void clear_cache( struct brw_cache *cache )
+static void
+brw_clear_cache( struct brw_context *brw )
{
struct brw_cache_item *c, *next;
GLuint i;
- for (i = 0; i < cache->size; i++) {
- for (c = cache->items[i]; c; c = next) {
+ if (INTEL_DEBUG & DEBUG_STATE)
+ _mesa_printf("%s\n", __FUNCTION__);
+
+ for (i = 0; i < brw->cache.size; i++) {
+ for (c = brw->cache.items[i]; c; c = next) {
int j;
next = c->next;
free((void *)c->key);
free(c);
}
- cache->items[i] = NULL;
+ brw->cache.items[i] = NULL;
}
- cache->n_items = 0;
-}
-
-void brw_clear_cache( struct brw_context *brw )
-{
- if (INTEL_DEBUG & DEBUG_STATE)
- _mesa_printf("%s\n", __FUNCTION__);
-
- clear_cache(&brw->cache);
+ brw->cache.n_items = 0;
if (brw->curbe.last_buf) {
_mesa_free(brw->curbe.last_buf);
{
GLuint i;
- clear_cache(&brw->cache);
- for (i = 0; i < BRW_MAX_CACHE; i++)
+ brw_clear_cache(brw);
+ for (i = 0; i < BRW_MAX_CACHE; i++) {
+ dri_bo_unreference(brw->cache.last_bo[i]);
free(brw->cache.name[i]);
-
+ }
free(brw->cache.items);
brw->cache.items = NULL;
brw->cache.size = 0;