galahad: do map/unmap counting for resources
[mesa.git] / src / gallium / drivers / i965 / brw_state_cache.c
index 97f88b3ab3929e9b228d3eeee6bc3fb6255b67d2..c911f3997d18fc47c688ca2ca33a2e9c93f76bac 100644 (file)
@@ -47,7 +47,7 @@
  * 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
+ * The reloc structs need to be included as key data, otherwise the
  * non-unique values stuffed in the offset in key data through
  * brw_cache_data() may result in successful probe for state buffers
  * even when the buffer being referenced doesn't match.  The result would be
  * only one of the two buffers referenced gets put into the offset, and the
  * incorrect program is run for the other instance.
  */
+#include "util/u_memory.h"
 
+#include "brw_debug.h"
 #include "brw_state.h"
-#include "brw_batchbuffer.h"
 
 /* XXX: Fixme - have to include these to get the sizes of the prog_key
  * structs:
@@ -71,7 +72,7 @@
 
 static GLuint
 hash_key(const void *key, GLuint key_size,
-         struct brw_winsys_buffer **reloc_bufs, GLuint nr_reloc_bufs)
+         struct brw_winsys_reloc *relocs, GLuint nr_relocs)
 {
    GLuint *ikey = (GLuint *)key;
    GLuint hash = 0, i;
@@ -86,8 +87,8 @@ hash_key(const void *key, GLuint key_size,
    }
 
    /* Include the BO pointers as key data as well */
-   ikey = (GLuint *)reloc_bufs;
-   key_size = nr_reloc_bufs * sizeof(struct brw_winsys_buffer *);
+   ikey = (GLuint *)relocs;
+   key_size = nr_relocs * sizeof(struct brw_winsys_reloc);
    for (i = 0; i < key_size/4; i++) {
       hash ^= ikey[i];
       hash = (hash << 5) | (hash >> 27);
@@ -107,9 +108,8 @@ update_cache_last(struct brw_cache *cache, enum brw_cache_id cache_id,
    if (bo == cache->last_bo[cache_id])
       return; /* no change */
 
-   brw->sws->bo_unreference(cache->last_bo[cache_id]);
-   cache->last_bo[cache_id] = bo;
-   brw->sws->bo_reference(cache->last_bo[cache_id]);
+   bo_reference( &cache->last_bo[cache_id],  bo );
+
    cache->brw->state.dirty.cache |= 1 << cache_id;
 }
 
@@ -117,7 +117,7 @@ update_cache_last(struct brw_cache *cache, enum brw_cache_id cache_id,
 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,
-            struct brw_winsys_buffer **reloc_bufs, GLuint nr_reloc_bufs)
+            struct brw_winsys_reloc *relocs, GLuint nr_relocs)
 {
    struct brw_cache_item *c;
 
@@ -127,7 +127,7 @@ search_cache(struct brw_cache *cache, enum brw_cache_id cache_id,
    for (c = cache->items[hash % cache->size]; c; c = c->next)
       bucketcount++;
 
-   fprintf(stderr, "bucket %d/%d = %d/%d items\n", hash % cache->size,
+   debug_printf("bucket %d/%d = %d/%d items\n", hash % cache->size,
           cache->size, bucketcount, cache->n_items);
 #endif
 
@@ -136,9 +136,8 @@ search_cache(struct brw_cache *cache, enum brw_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(struct brw_winsys_buffer *)) == 0)
+         c->nr_relocs == nr_relocs &&
+         memcmp(c->relocs, relocs, nr_relocs * sizeof *relocs) == 0)
         return c;
    }
 
@@ -154,7 +153,7 @@ rehash(struct brw_cache *cache)
    GLuint size, i;
 
    size = cache->size * 3;
-   items = (struct brw_cache_item**) _mesa_calloc(size * sizeof(*items));
+   items = (struct brw_cache_item**) CALLOC(size, sizeof(*items));
 
    for (i = 0; i < cache->size; i++)
       for (c = cache->items[i]; c; c = next) {
@@ -172,78 +171,87 @@ rehash(struct brw_cache *cache)
 /**
  * Returns the buffer object matching cache_id and key, or NULL.
  */
-struct brw_winsys_buffer *
+boolean
 brw_search_cache(struct brw_cache *cache,
                  enum brw_cache_id cache_id,
                  const void *key,
                  GLuint key_size,
-                 struct brw_winsys_buffer **reloc_bufs, GLuint nr_reloc_bufs,
-                 void *aux_return)
+                 struct brw_winsys_reloc *relocs, 
+                GLuint nr_relocs,
+                 void *aux_return,
+                 struct brw_winsys_buffer **bo_out)
 {
    struct brw_cache_item *item;
-   GLuint hash = hash_key(key, key_size, reloc_bufs, nr_reloc_bufs);
+   GLuint hash = hash_key(key, key_size, relocs, nr_relocs);
 
    item = search_cache(cache, cache_id, hash, key, key_size,
-                      reloc_bufs, nr_reloc_bufs);
-
-   if (item == NULL)
-      return NULL;
-
-   if (aux_return)
-      *(void **)aux_return = (void *)((char *)item->key + item->key_size);
-
-   update_cache_last(cache, cache_id, item->bo);
+                      relocs, nr_relocs);
 
-   brw->sws->bo_reference(item->bo);
-   return item->bo;
+   if (item) {
+      if (aux_return)
+         *(void **)aux_return = (void *)((char *)item->key + item->key_size);
+      
+      update_cache_last(cache, cache_id, item->bo);
+      bo_reference(bo_out, item->bo);
+      return TRUE;
+   }
+   
+   return FALSE;      
 }
 
 
-struct brw_winsys_buffer *
+enum pipe_error
 brw_upload_cache( struct brw_cache *cache,
                  enum brw_cache_id cache_id,
                  const void *key,
                  GLuint key_size,
-                 struct brw_winsys_buffer **reloc_bufs,
-                 GLuint nr_reloc_bufs,
+                 struct brw_winsys_reloc *relocs,
+                 GLuint nr_relocs,
                  const void *data,
                  GLuint data_size,
                  const void *aux,
-                 void *aux_return )
+                 void *aux_return,
+                  struct brw_winsys_buffer **bo_out)
 {
-   struct brw_cache_item *item = CALLOC_STRUCT(brw_cache_item);
-   GLuint hash = hash_key(key, key_size, reloc_bufs, nr_reloc_bufs);
-   GLuint relocs_size = nr_reloc_bufs * sizeof(struct brw_winsys_buffer *);
+   struct brw_cache_item *item;
+   GLuint hash = hash_key(key, key_size, relocs, nr_relocs);
+   GLuint relocs_size = nr_relocs * sizeof relocs[0];
    GLuint aux_size = cache->aux_size[cache_id];
+   enum pipe_error ret;
    void *tmp;
-   struct brw_winsys_buffer *bo;
    int i;
 
-   /* Create the buffer object to contain the data */
-   bo = brw->sws->bo_alloc(cache->sws,
-                          cache->buffer_type[cache_id], data_size, 1 << 6);
+   /* Create the buffer object to contain the data.  For now, use a
+    * single buffer type to describe all cached state atoms.  Later,
+    * may want to take advantage of hardware distinctions between
+    * these various entities.
+    */
+   ret = cache->sws->bo_alloc(cache->sws,
+                              cache->buffer_type,
+                              data_size, 1 << 6, 
+                              bo_out);
+   if (ret)
+      return ret;
 
+   item = CALLOC_STRUCT(brw_cache_item);
 
-   /* Set up the memory containing the key, aux_data, and reloc_bufs */
-   tmp = _mesa_malloc(key_size + aux_size + relocs_size);
+   /* Set up the memory containing the key, aux_data, and relocs */
+   tmp = 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_size, reloc_bufs, relocs_size);
-   for (i = 0; i < nr_reloc_bufs; i++) {
-      if (reloc_bufs[i] != NULL)
-        brw->sws->bo_reference(reloc_bufs[i]);
+   memcpy((char *)tmp + key_size, aux, cache->aux_size[cache_id]);
+   memcpy((char *)tmp + key_size + aux_size, relocs, relocs_size);
+   for (i = 0; i < nr_relocs; i++) {
+      p_atomic_inc(&relocs[i].bo->reference.count);
    }
 
    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;
-   brw->sws->bo_reference(bo);
+   item->relocs = (struct brw_winsys_reloc *)((char *)tmp + key_size + aux_size);
+   item->nr_relocs = nr_relocs;
+   bo_reference( &item->bo, *bo_out );
    item->data_size = data_size;
 
    if (cache->n_items > cache->size * 1.5)
@@ -259,76 +267,79 @@ brw_upload_cache( struct brw_cache *cache,
       *(void **)aux_return = (void *)((char *)item->key + item->key_size);
    }
 
-   if (INTEL_DEBUG & DEBUG_STATE)
-      _mesa_printf("upload %s: %d bytes to cache id %d\n",
+   if (BRW_DEBUG & DEBUG_STATE)
+      debug_printf("upload %s: %d bytes to cache id %d\n",
                   cache->name[cache_id],
                   data_size, cache_id);
 
    /* Copy data to the buffer */
-   dri_bo_subdata(bo, 0, data_size, data);
+   ret = cache->sws->bo_subdata(item->bo, 
+                                cache_id,
+                                0, data_size, data,
+                                relocs, nr_relocs);
+   if (ret)
+      return ret;
 
-   update_cache_last(cache, cache_id, bo);
+   update_cache_last(cache, cache_id, item->bo);
 
-   return bo;
+   return PIPE_OK;
 }
 
 
 /**
  * This doesn't really work with aux data.  Use search/upload instead
  */
-struct brw_winsys_buffer *
+enum pipe_error
 brw_cache_data_sz(struct brw_cache *cache,
                  enum brw_cache_id cache_id,
                  const void *data,
                  GLuint data_size,
-                 struct brw_winsys_buffer **reloc_bufs,
-                 GLuint nr_reloc_bufs)
+                 struct brw_winsys_reloc *relocs,
+                 GLuint nr_relocs,
+                  struct brw_winsys_buffer **bo_out)
 {
-   struct brw_winsys_buffer *bo;
    struct brw_cache_item *item;
-   GLuint hash = hash_key(data, data_size, reloc_bufs, nr_reloc_bufs);
+   GLuint hash = hash_key(data, data_size, relocs, nr_relocs);
 
    item = search_cache(cache, cache_id, hash, data, data_size,
-                      reloc_bufs, nr_reloc_bufs);
+                      relocs, nr_relocs);
    if (item) {
       update_cache_last(cache, cache_id, item->bo);
-      brw->sws->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);
+      bo_reference(bo_out, item->bo);
+      return PIPE_OK;
+   }
 
-   return bo;
+   return brw_upload_cache(cache, cache_id,
+                           data, data_size,
+                           relocs, nr_relocs,
+                           data, data_size,
+                           NULL, NULL,
+                           bo_out);
 }
 
 
 /**
  * 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
+ * If nr_relocs 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.
+ * 
+ * XXX: above is no longer true -- can we remove some code?
  */
-struct brw_winsys_buffer *
+enum pipe_error
 brw_cache_data(struct brw_cache *cache,
               enum brw_cache_id cache_id,
               const void *data,
-              struct brw_winsys_buffer **reloc_bufs,
-              GLuint nr_reloc_bufs)
+              struct brw_winsys_reloc *relocs,
+              GLuint nr_relocs,
+               struct brw_winsys_buffer **bo_out)
 {
    return brw_cache_data_sz(cache, cache_id, data, cache->key_size[cache_id],
-                           reloc_bufs, nr_reloc_bufs);
+                           relocs, nr_relocs, bo_out);
 }
 
-enum pool_type {
-   DW_SURFACE_STATE,
-   DW_GENERAL_STATE
-};
-
 
 static void
 brw_init_cache_id(struct brw_cache *cache,
@@ -344,16 +355,19 @@ brw_init_cache_id(struct brw_cache *cache,
 
 
 static void
-brw_init_non_surface_cache(struct brw_context *brw)
+brw_init_general_state_cache(struct brw_context *brw)
 {
    struct brw_cache *cache = &brw->cache;
 
    cache->brw = brw;
+   cache->sws = brw->sws;
+
+   cache->buffer_type = BRW_BUFFER_TYPE_GENERAL_STATE;
 
    cache->size = 7;
    cache->n_items = 0;
    cache->items = (struct brw_cache_item **)
-      _mesa_calloc(cache->size * sizeof(struct brw_cache_item));
+      CALLOC(cache->size, sizeof(struct brw_cache_item));
 
    brw_init_cache_id(cache,
                     "CC_VP",
@@ -448,16 +462,19 @@ brw_init_non_surface_cache(struct brw_context *brw)
 
 
 static void
-brw_init_surface_cache(struct brw_context *brw)
+brw_init_surface_state_cache(struct brw_context *brw)
 {
    struct brw_cache *cache = &brw->surface_cache;
 
    cache->brw = brw;
+   cache->sws = brw->sws;
+
+   cache->buffer_type = BRW_BUFFER_TYPE_SURFACE_STATE;
 
    cache->size = 7;
    cache->n_items = 0;
    cache->items = (struct brw_cache_item **)
-      _mesa_calloc(cache->size * sizeof(struct brw_cache_item));
+      CALLOC(cache->size, sizeof(struct brw_cache_item));
 
    brw_init_cache_id(cache,
                     "SS_SURFACE",
@@ -476,8 +493,8 @@ brw_init_surface_cache(struct brw_context *brw)
 void
 brw_init_caches(struct brw_context *brw)
 {
-   brw_init_non_surface_cache(brw);
-   brw_init_surface_cache(brw);
+   brw_init_general_state_cache(brw);
+   brw_init_surface_state_cache(brw);
 }
 
 
@@ -487,19 +504,21 @@ brw_clear_cache(struct brw_context *brw, struct brw_cache *cache)
    struct brw_cache_item *c, *next;
    GLuint i;
 
-   if (INTEL_DEBUG & DEBUG_STATE)
-      _mesa_printf("%s\n", __FUNCTION__);
+   if (BRW_DEBUG & DEBUG_STATE)
+      debug_printf("%s\n", __FUNCTION__);
 
    for (i = 0; i < cache->size; i++) {
       for (c = cache->items[i]; c; c = next) {
         int j;
 
         next = c->next;
-        for (j = 0; j < c->nr_reloc_bufs; j++)
-           brw->sws->bo_unreference(c->reloc_bufs[j]);
-        brw->sws->bo_unreference(c->bo);
-        free((void *)c->key);
-        free(c);
+
+        for (j = 0; j < c->nr_relocs; j++)
+           bo_reference(&c->relocs[j].bo, NULL);
+
+        bo_reference(&c->bo, NULL);
+        FREE((void *)c->key);
+        FREE(c);
       }
       cache->items[i] = NULL;
    }
@@ -507,7 +526,7 @@ brw_clear_cache(struct brw_context *brw, struct brw_cache *cache)
    cache->n_items = 0;
 
    if (brw->curbe.last_buf) {
-      _mesa_free(brw->curbe.last_buf);
+      FREE(brw->curbe.last_buf);
       brw->curbe.last_buf = NULL;
    }
 
@@ -527,8 +546,8 @@ brw_state_cache_bo_delete(struct brw_cache *cache, struct brw_winsys_buffer *bo)
    struct brw_cache_item **prev;
    GLuint i;
 
-   if (INTEL_DEBUG & DEBUG_STATE)
-      _mesa_printf("%s\n", __FUNCTION__);
+   if (BRW_DEBUG & DEBUG_STATE)
+      debug_printf("%s\n", __FUNCTION__);
 
    for (i = 0; i < cache->size; i++) {
       for (prev = &cache->items[i]; *prev;) {
@@ -539,11 +558,13 @@ brw_state_cache_bo_delete(struct brw_cache *cache, struct brw_winsys_buffer *bo)
 
            *prev = c->next;
 
-           for (j = 0; j < c->nr_reloc_bufs; j++)
-              brw->sws->bo_unreference(c->reloc_bufs[j]);
-           brw->sws->bo_unreference(c->bo);
-           free((void *)c->key);
-           free(c);
+           for (j = 0; j < c->nr_relocs; j++)
+              bo_reference(&c->relocs[j].bo, NULL);
+
+           bo_reference(&c->bo, NULL);
+
+           FREE((void *)c->key);
+           FREE(c);
            cache->n_items--;
         } else {
            prev = &c->next;
@@ -555,8 +576,8 @@ brw_state_cache_bo_delete(struct brw_cache *cache, struct brw_winsys_buffer *bo)
 void
 brw_state_cache_check_size(struct brw_context *brw)
 {
-   if (INTEL_DEBUG & DEBUG_STATE)
-      _mesa_printf("%s (n_items=%d)\n", __FUNCTION__, brw->cache.n_items);
+   if (BRW_DEBUG & DEBUG_STATE)
+      debug_printf("%s (n_items=%d)\n", __FUNCTION__, brw->cache.n_items);
 
    /* un-tuned guess.  We've got around 20 state objects for a total of around
     * 32k, so 1000 of them is around 1.5MB.
@@ -574,15 +595,15 @@ brw_destroy_cache(struct brw_context *brw, struct brw_cache *cache)
 {
    GLuint i;
 
-   if (INTEL_DEBUG & DEBUG_STATE)
-      _mesa_printf("%s\n", __FUNCTION__);
+   if (BRW_DEBUG & DEBUG_STATE)
+      debug_printf("%s\n", __FUNCTION__);
 
    brw_clear_cache(brw, cache);
    for (i = 0; i < BRW_MAX_CACHE; i++) {
-      brw->sws->bo_unreference(cache->last_bo[i]);
-      free(cache->name[i]);
+      bo_reference(&cache->last_bo[i], NULL);
+      FREE(cache->name[i]);
    }
-   free(cache->items);
+   FREE(cache->items);
    cache->items = NULL;
    cache->size = 0;
 }