i965: Improve the hashing of brw_state_cache keys to include the cache_id.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_state_cache.c
index f8e46aacf710251f058417008828670ef1a26dfd..5fc47b0420a0eb59ede42fa6ea1870b0ee5f10b8 100644 (file)
 
 
 static GLuint
-hash_key(const void *key, GLuint key_size,
-         dri_bo **reloc_bufs, GLuint nr_reloc_bufs)
+hash_key(struct brw_cache_item *item)
 {
-   GLuint *ikey = (GLuint *)key;
-   GLuint hash = 0, i;
+   GLuint *ikey = (GLuint *)item->key;
+   GLuint hash = item->cache_id, i;
 
-   assert(key_size % 4 == 0);
+   assert(item->key_size % 4 == 0);
 
    /* I'm sure this can be improved on:
     */
-   for (i = 0; i < key_size/4; i++) {
+   for (i = 0; i < item->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++) {
+   ikey = (GLuint *)item->reloc_bufs;
+   for (i = 0; i < item->nr_reloc_bufs * sizeof(drm_intel_bo *) / 4; i++) {
       hash ^= ikey[i];
       hash = (hash << 5) | (hash >> 27);
    }
@@ -114,11 +112,22 @@ update_cache_last(struct brw_cache *cache, enum brw_cache_id cache_id,
    cache->brw->state.dirty.cache |= 1 << cache_id;
 }
 
+static int
+brw_cache_item_equals(const struct brw_cache_item *a,
+                     const struct brw_cache_item *b)
+{
+   return a->cache_id == b->cache_id &&
+      a->hash == b->hash &&
+      a->key_size == b->key_size &&
+      (memcmp(a->key, b->key, a->key_size) == 0) &&
+      a->nr_reloc_bufs == b->nr_reloc_bufs &&
+      (memcmp(a->reloc_bufs, b->reloc_bufs,
+             a->nr_reloc_bufs * sizeof(dri_bo *)) == 0);
+}
 
 static struct brw_cache_item *
-search_cache(struct brw_cache *cache, enum brw_cache_id cache_id,
-            GLuint hash, const void *key, GLuint key_size,
-            dri_bo **reloc_bufs, GLuint nr_reloc_bufs)
+search_cache(struct brw_cache *cache, GLuint hash,
+            struct brw_cache_item *lookup)
 {
    struct brw_cache_item *c;
 
@@ -133,13 +142,7 @@ search_cache(struct brw_cache *cache, enum brw_cache_id cache_id,
 #endif
 
    for (c = cache->items[hash % cache->size]; c; c = c->next) {
-      if (c->cache_id == cache_id &&
-         c->hash == hash &&
-         c->key_size == key_size &&
-         memcmp(c->key, key, key_size) == 0 &&
-         c->nr_reloc_bufs == nr_reloc_bufs &&
-         memcmp(c->reloc_bufs, reloc_bufs,
-                nr_reloc_bufs * sizeof(dri_bo *)) == 0)
+      if (brw_cache_item_equals(lookup, c))
         return c;
    }
 
@@ -182,10 +185,18 @@ brw_search_cache(struct brw_cache *cache,
                  void *aux_return)
 {
    struct brw_cache_item *item;
-   GLuint hash = hash_key(key, key_size, reloc_bufs, nr_reloc_bufs);
+   struct brw_cache_item lookup;
+   GLuint hash;
 
-   item = search_cache(cache, cache_id, hash, key, key_size,
-                      reloc_bufs, nr_reloc_bufs);
+   lookup.cache_id = cache_id;
+   lookup.key = key;
+   lookup.key_size = key_size;
+   lookup.reloc_bufs = reloc_bufs;
+   lookup.nr_reloc_bufs = nr_reloc_bufs;
+   hash = hash_key(&lookup);
+   lookup.hash = hash;
+
+   item = search_cache(cache, hash, &lookup);
 
    if (item == NULL)
       return NULL;
@@ -200,26 +211,34 @@ brw_search_cache(struct brw_cache *cache,
 }
 
 
-dri_bo *
-brw_upload_cache( struct brw_cache *cache,
-                 enum brw_cache_id cache_id,
-                 const void *key,
-                 GLuint key_size,
-                 dri_bo **reloc_bufs,
-                 GLuint nr_reloc_bufs,
-                 const void *data,
-                 GLuint data_size,
-                 const void *aux,
-                 void *aux_return )
+drm_intel_bo *
+brw_upload_cache_with_auxdata(struct brw_cache *cache,
+                             enum brw_cache_id cache_id,
+                             const void *key,
+                             GLuint key_size,
+                             dri_bo **reloc_bufs,
+                             GLuint nr_reloc_bufs,
+                             const void *data,
+                             GLuint data_size,
+                             const void *aux,
+                             GLuint aux_size,
+                             void *aux_return)
 {
    struct brw_cache_item *item = CALLOC_STRUCT(brw_cache_item);
-   GLuint hash = hash_key(key, key_size, reloc_bufs, nr_reloc_bufs);
+   GLuint hash;
    GLuint relocs_size = nr_reloc_bufs * sizeof(dri_bo *);
-   GLuint aux_size = cache->aux_size[cache_id];
    void *tmp;
    dri_bo *bo;
    int i;
 
+   item->cache_id = cache_id;
+   item->key = key;
+   item->key_size = key_size;
+   item->reloc_bufs = reloc_bufs;
+   item->nr_reloc_bufs = nr_reloc_bufs;
+   hash = hash_key(item);
+   item->hash = hash;
+
    /* Create the buffer object to contain the data */
    bo = dri_bo_alloc(cache->brw->intel.bufmgr,
                     cache->name[cache_id], data_size, 1 << 6);
@@ -229,23 +248,18 @@ brw_upload_cache( struct brw_cache *cache,
    tmp = _mesa_malloc(key_size + aux_size + relocs_size);
 
    memcpy(tmp, key, key_size);
-   memcpy(tmp + key_size, aux, cache->aux_size[cache_id]);
+   memcpy(tmp + key_size, aux, aux_size);
    memcpy(tmp + key_size + aux_size, reloc_bufs, relocs_size);
    for (i = 0; i < nr_reloc_bufs; i++) {
       if (reloc_bufs[i] != NULL)
         dri_bo_reference(reloc_bufs[i]);
    }
 
-   item->cache_id = cache_id;
    item->key = tmp;
-   item->hash = hash;
-   item->key_size = key_size;
    item->reloc_bufs = tmp + key_size + aux_size;
-   item->nr_reloc_bufs = nr_reloc_bufs;
 
    item->bo = bo;
    dri_bo_reference(bo);
-   item->data_size = data_size;
 
    if (cache->n_items > cache->size * 1.5)
       rehash(cache);
@@ -256,7 +270,6 @@ brw_upload_cache( struct brw_cache *cache,
    cache->n_items++;
 
    if (aux_return) {
-      assert(cache->aux_size[cache_id]);
       *(void **)aux_return = (void *)((char *)item->key + item->key_size);
    }
 
@@ -273,56 +286,67 @@ brw_upload_cache( struct brw_cache *cache,
    return bo;
 }
 
-
-/**
- * This doesn't really work with aux data.  Use search/upload instead
- */
-dri_bo *
-brw_cache_data_sz(struct brw_cache *cache,
-                 enum brw_cache_id cache_id,
-                 const void *data,
-                 GLuint data_size,
-                 dri_bo **reloc_bufs,
-                 GLuint nr_reloc_bufs)
+drm_intel_bo *
+brw_upload_cache(struct brw_cache *cache,
+                enum brw_cache_id cache_id,
+                const void *key,
+                GLuint key_size,
+                dri_bo **reloc_bufs,
+                GLuint nr_reloc_bufs,
+                const void *data,
+                GLuint data_size)
 {
-   dri_bo *bo;
-   struct brw_cache_item *item;
-   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;
-   }
-
-   bo = brw_upload_cache(cache, cache_id,
-                        data, data_size,
-                        reloc_bufs, nr_reloc_bufs,
-                        data, data_size,
-                        NULL, NULL);
-
-   return bo;
+   return brw_upload_cache_with_auxdata(cache, cache_id,
+                                       key, key_size,
+                                       reloc_bufs, nr_reloc_bufs,
+                                       data, data_size,
+                                       NULL, 0,
+                                       NULL);
 }
 
-
 /**
  * Wrapper around brw_cache_data_sz using the cache_id's canonical key size.
  *
  * If nr_reloc_bufs is nonzero, brw_search_cache()/brw_upload_cache() would be
  * better to use, as the potentially changing offsets in the data-used-as-key
  * will result in excessive cache misses.
+ *
+ * If aux data is involved, use search/upload instead.
+
  */
 dri_bo *
 brw_cache_data(struct brw_cache *cache,
               enum brw_cache_id cache_id,
               const void *data,
+              GLuint data_size,
               dri_bo **reloc_bufs,
               GLuint nr_reloc_bufs)
 {
-   return brw_cache_data_sz(cache, cache_id, data, cache->key_size[cache_id],
-                           reloc_bufs, nr_reloc_bufs);
+   dri_bo *bo;
+   struct brw_cache_item *item, lookup;
+   GLuint hash;
+
+   lookup.cache_id = cache_id;
+   lookup.key = data;
+   lookup.key_size = data_size;
+   lookup.reloc_bufs = reloc_bufs;
+   lookup.nr_reloc_bufs = nr_reloc_bufs;
+   hash = hash_key(&lookup);
+   lookup.hash = hash;
+
+   item = search_cache(cache, hash, &lookup);
+   if (item) {
+      update_cache_last(cache, cache_id, item->bo);
+      dri_bo_reference(item->bo);
+      return item->bo;
+   }
+
+   bo = brw_upload_cache(cache, cache_id,
+                        data, data_size,
+                        reloc_bufs, nr_reloc_bufs,
+                        data, data_size);
+
+   return bo;
 }
 
 enum pool_type {
@@ -334,13 +358,9 @@ enum pool_type {
 static void
 brw_init_cache_id(struct brw_cache *cache,
                   const char *name,
-                  enum brw_cache_id id,
-                  GLuint key_size,
-                  GLuint aux_size)
+                  enum brw_cache_id id)
 {
    cache->name[id] = strdup(name);
-   cache->key_size[id] = key_size;
-   cache->aux_size[id] = aux_size;
 }
 
 
@@ -356,95 +376,28 @@ brw_init_non_surface_cache(struct brw_context *brw)
    cache->items = (struct brw_cache_item **)
       _mesa_calloc(cache->size * sizeof(struct brw_cache_item));
 
-   brw_init_cache_id(cache,
-                    "CC_VP",
-                    BRW_CC_VP,
-                    sizeof(struct brw_cc_viewport),
-                    0);
-
-   brw_init_cache_id(cache,
-                    "CC_UNIT",
-                    BRW_CC_UNIT,
-                    sizeof(struct brw_cc_unit_state),
-                    0);
-
-   brw_init_cache_id(cache,
-                    "WM_PROG",
-                    BRW_WM_PROG,
-                    sizeof(struct brw_wm_prog_key),
-                    sizeof(struct brw_wm_prog_data));
-
-   brw_init_cache_id(cache,
-                    "SAMPLER_DEFAULT_COLOR",
-                    BRW_SAMPLER_DEFAULT_COLOR,
-                    sizeof(struct brw_sampler_default_color),
-                    0);
-
-   brw_init_cache_id(cache,
-                    "SAMPLER",
-                    BRW_SAMPLER,
-                    0,         /* variable key/data size */
-                    0);
-
-   brw_init_cache_id(cache,
-                    "WM_UNIT",
-                    BRW_WM_UNIT,
-                    sizeof(struct brw_wm_unit_state),
-                    0);
-
-   brw_init_cache_id(cache,
-                    "SF_PROG",
-                    BRW_SF_PROG,
-                    sizeof(struct brw_sf_prog_key),
-                    sizeof(struct brw_sf_prog_data));
-
-   brw_init_cache_id(cache,
-                    "SF_VP",
-                    BRW_SF_VP,
-                    sizeof(struct brw_sf_viewport),
-                    0);
-
-   brw_init_cache_id(cache,
-                    "SF_UNIT",
-                    BRW_SF_UNIT,
-                    sizeof(struct brw_sf_unit_state),
-                    0);
-
-   brw_init_cache_id(cache,
-                    "VS_UNIT",
-                    BRW_VS_UNIT,
-                    sizeof(struct brw_vs_unit_state),
-                    0);
-
-   brw_init_cache_id(cache,
-                    "VS_PROG",
-                    BRW_VS_PROG,
-                    sizeof(struct brw_vs_prog_key),
-                    sizeof(struct brw_vs_prog_data));
-
-   brw_init_cache_id(cache,
-                    "CLIP_UNIT",
-                    BRW_CLIP_UNIT,
-                    sizeof(struct brw_clip_unit_state),
-                    0);
-
-   brw_init_cache_id(cache,
-                    "CLIP_PROG",
-                    BRW_CLIP_PROG,
-                    sizeof(struct brw_clip_prog_key),
-                    sizeof(struct brw_clip_prog_data));
-
-   brw_init_cache_id(cache,
-                    "GS_UNIT",
-                    BRW_GS_UNIT,
-                    sizeof(struct brw_gs_unit_state),
-                    0);
-
-   brw_init_cache_id(cache,
-                    "GS_PROG",
-                    BRW_GS_PROG,
-                    sizeof(struct brw_gs_prog_key),
-                    sizeof(struct brw_gs_prog_data));
+   brw_init_cache_id(cache, "CC_VP", BRW_CC_VP);
+   brw_init_cache_id(cache, "CC_UNIT", BRW_CC_UNIT);
+   brw_init_cache_id(cache, "WM_PROG", BRW_WM_PROG);
+   brw_init_cache_id(cache, "SAMPLER_DEFAULT_COLOR", BRW_SAMPLER_DEFAULT_COLOR);
+   brw_init_cache_id(cache, "SAMPLER", BRW_SAMPLER);
+   brw_init_cache_id(cache, "WM_UNIT", BRW_WM_UNIT);
+   brw_init_cache_id(cache, "SF_PROG", BRW_SF_PROG);
+   brw_init_cache_id(cache, "SF_VP", BRW_SF_VP);
+
+   brw_init_cache_id(cache, "SF_UNIT", BRW_SF_UNIT);
+
+   brw_init_cache_id(cache, "VS_UNIT", BRW_VS_UNIT);
+
+   brw_init_cache_id(cache, "VS_PROG", BRW_VS_PROG);
+
+   brw_init_cache_id(cache, "CLIP_UNIT", BRW_CLIP_UNIT);
+
+   brw_init_cache_id(cache, "CLIP_PROG", BRW_CLIP_PROG);
+
+   brw_init_cache_id(cache, "GS_UNIT", BRW_GS_UNIT);
+
+   brw_init_cache_id(cache, "GS_PROG", BRW_GS_PROG);
 }
 
 
@@ -460,17 +413,8 @@ brw_init_surface_cache(struct brw_context *brw)
    cache->items = (struct brw_cache_item **)
       _mesa_calloc(cache->size * sizeof(struct brw_cache_item));
 
-   brw_init_cache_id(cache,
-                    "SS_SURFACE",
-                    BRW_SS_SURFACE,
-                    sizeof(struct brw_surface_state),
-                    0);
-
-   brw_init_cache_id(cache,
-                    "SS_SURF_BIND",
-                    BRW_SS_SURF_BIND,
-                    0,
-                    0);
+   brw_init_cache_id(cache, "SS_SURFACE", BRW_SS_SURFACE);
+   brw_init_cache_id(cache, "SS_SURF_BIND", BRW_SS_SURF_BIND);
 }
 
 
@@ -534,14 +478,9 @@ brw_state_cache_bo_delete(struct brw_cache *cache, dri_bo *bo)
    for (i = 0; i < cache->size; i++) {
       for (prev = &cache->items[i]; *prev;) {
         struct brw_cache_item *c = *prev;
-        int j;
 
-        for (j = 0; j < c->nr_reloc_bufs; j++) {
-           if (c->reloc_bufs[j] == bo)
-              break;
-        }
-
-        if (j != c->nr_reloc_bufs) {
+        if (drm_intel_bo_references(c->bo, bo)) {
+           int j;
 
            *prev = c->next;
 
@@ -551,17 +490,8 @@ brw_state_cache_bo_delete(struct brw_cache *cache, dri_bo *bo)
            free((void *)c->key);
            free(c);
            cache->n_items--;
-
-           /* Delete up the tree.  Notably we're trying to get from
-            * a request to delete the surface, to deleting the surface state
-            * object, to deleting the binding table.  We're slack and restart
-            * the deletion process when we do this because the other delete
-            * may kill our *prev.
-            */
-           brw_state_cache_bo_delete(cache, c->bo);
-           prev = &cache->items[i];
         } else {
-           prev = &(*prev)->next;
+           prev = &c->next;
         }
       }
    }