brw_state_cache.c revision 97a5f0ff2eb3a6e8b303ce402a4e1d9be7e7b323
165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali/*
265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali Copyright (C) Intel Corp.  2006.  All Rights Reserved.
365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali develop this 3D driver.
565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali Permission is hereby granted, free of charge, to any person obtaining
765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali a copy of this software and associated documentation files (the
865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali "Software"), to deal in the Software without restriction, including
965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali without limitation the rights to use, copy, modify, merge, publish,
1065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali distribute, sublicense, and/or sell copies of the Software, and to
1165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali permit persons to whom the Software is furnished to do so, subject to
1265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali the following conditions:
1365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
1465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali The above copyright notice and this permission notice (including the
1565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali next paragraph) shall be included in all copies or substantial
1665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali portions of the Software.
1765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
1865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
2165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
2265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
2365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
2665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali **********************************************************************/
2765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali /*
2865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali  * Authors:
2965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali  *   Keith Whitwell <keith@tungstengraphics.com>
3065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali  */
3165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
3265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali/** @file brw_state_cache.c
3365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali *
3465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali * This file implements a simple static state cache for 965.  The
3565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali * consumers can query the hash table of state using a cache_id,
3665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali * opaque key data, and receive the corresponding state buffer object
3765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali * of state (plus associated auxiliary data) in return.  Objects in
3865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali * the cache may not have relocations (pointers to other BOs) in them.
3965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali *
4065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali * The inner workings are a simple hash table based on a CRC of the
4165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali * key data.
4265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali *
4365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali * Replacement is not implemented.  Instead, when the cache gets too
4465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali * big we throw out all of the cache data and let it get regenerated.
4565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali */
4665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
4765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali#include "main/imports.h"
4865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali#include "intel_batchbuffer.h"
4965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali#include "brw_state.h"
5065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
5165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali#define FILE_DEBUG_FLAG DEBUG_STATE
5265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
5365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valistatic GLuint
5465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valihash_key(struct brw_cache_item *item)
5565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali{
5665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   GLuint *ikey = (GLuint *)item->key;
5765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   GLuint hash = item->cache_id, i;
5865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
5965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   assert(item->key_size % 4 == 0);
6065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
6165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   /* I'm sure this can be improved on:
6265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali    */
6365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   for (i = 0; i < item->key_size/4; i++) {
6465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      hash ^= ikey[i];
6565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      hash = (hash << 5) | (hash >> 27);
6665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   }
6765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
6865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   return hash;
6965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali}
7065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
7165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valistatic int
7265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valibrw_cache_item_equals(const struct brw_cache_item *a,
7365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali		      const struct brw_cache_item *b)
7465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali{
7565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   return a->cache_id == b->cache_id &&
7665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      a->hash == b->hash &&
7765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      a->key_size == b->key_size &&
7865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      (memcmp(a->key, b->key, a->key_size) == 0);
7965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali}
8065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
8165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valistatic struct brw_cache_item *
8265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valisearch_cache(struct brw_cache *cache, GLuint hash,
8365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali	     struct brw_cache_item *lookup)
8465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali{
8565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   struct brw_cache_item *c;
8665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
8765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali#if 0
8865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   int bucketcount = 0;
8965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
9065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   for (c = cache->items[hash % cache->size]; c; c = c->next)
9165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      bucketcount++;
9265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
9365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   fprintf(stderr, "bucket %d/%d = %d/%d items\n", hash % cache->size,
9465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali	   cache->size, bucketcount, cache->n_items);
9565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali#endif
9665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
9765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   for (c = cache->items[hash % cache->size]; c; c = c->next) {
9865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      if (brw_cache_item_equals(lookup, c))
9965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali	 return c;
10065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   }
10165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
10265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   return NULL;
10365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali}
104651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
10565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
10665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valistatic void
10765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valirehash(struct brw_cache *cache)
108651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines{
10965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   struct brw_cache_item **items;
1106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines   struct brw_cache_item *c, *next;
11165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   GLuint size, i;
11265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
11365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   size = cache->size * 3;
11465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   items = (struct brw_cache_item**) calloc(1, size * sizeof(*items));
11565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
11665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   for (i = 0; i < cache->size; i++)
11765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      for (c = cache->items[i]; c; c = next) {
11865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali	 next = c->next;
1198fe2475a4b4c00475709c13d43eb9a57cce87cbcAlexey Bataev	 c->next = items[c->hash % size];
120651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines	 items[c->hash % size] = c;
1216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      }
12265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
12365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   FREE(cache->items);
12465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   cache->items = items;
12565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   cache->size = size;
12665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali}
12765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
12865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
12965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali/**
13065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali * Returns the buffer object matching cache_id and key, or NULL.
13165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali */
13265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valibool
13365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valibrw_search_cache(struct brw_cache *cache,
13465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali                 enum brw_cache_id cache_id,
13565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali                 const void *key, GLuint key_size,
13665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali                 uint32_t *inout_offset, void *out_aux)
13765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali{
13865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   struct brw_context *brw = cache->brw;
13965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   struct brw_cache_item *item;
14065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   struct brw_cache_item lookup;
14165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   GLuint hash;
14265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
14365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   lookup.cache_id = cache_id;
14465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   lookup.key = key;
14565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   lookup.key_size = key_size;
14665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   hash = hash_key(&lookup);
14765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   lookup.hash = hash;
14865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
14965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   item = search_cache(cache, hash, &lookup);
15065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
15165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   if (item == NULL)
15265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      return false;
15365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
15465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   *(void **)out_aux = ((char *)item->key + item->key_size);
15565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
15665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   if (item->offset != *inout_offset) {
15765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      brw->state.dirty.cache |= (1 << cache_id);
15865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      *inout_offset = item->offset;
15965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   }
16065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
16165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   return true;
16265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali}
16365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
16465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valistatic void
16565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valibrw_cache_new_bo(struct brw_cache *cache, uint32_t new_size)
16665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali{
16765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   struct brw_context *brw = cache->brw;
16865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   struct intel_context *intel = &brw->intel;
16965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   drm_intel_bo *new_bo;
17065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
17165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   new_bo = drm_intel_bo_alloc(intel->bufmgr, "program cache", new_size, 64);
17265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
1736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines   /* Copy any existing data that needs to be saved. */
17465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   if (cache->next_offset != 0) {
17565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      drm_intel_bo_map(cache->bo, false);
17665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      drm_intel_bo_subdata(new_bo, 0, cache->next_offset, cache->bo->virtual);
17765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      drm_intel_bo_unmap(cache->bo);
17865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   }
17965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
18065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   drm_intel_bo_unreference(cache->bo);
18165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   cache->bo = new_bo;
18265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   cache->bo_used_by_gpu = false;
18365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
18465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   /* Since we have a new BO in place, we need to signal the units
18565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali    * that depend on it (state base address on gen5+, or unit state before).
18665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali    */
18765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   brw->state.dirty.brw |= BRW_NEW_PROGRAM_CACHE;
18865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali}
18965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
19065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali/**
19165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali * Attempts to find an item in the cache with identical data and aux
19265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali * data to use
19365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali */
19465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valistatic bool
19565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valibrw_try_upload_using_copy(struct brw_cache *cache,
19665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali			  struct brw_cache_item *result_item,
19765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali			  const void *data,
19865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali			  const void *aux)
19965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali{
20065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   int i;
20165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   struct brw_cache_item *item;
20265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
20365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   for (i = 0; i < cache->size; i++) {
20465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      for (item = cache->items[i]; item; item = item->next) {
20565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali	 const void *item_aux = item->key + item->key_size;
20665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali	 int ret;
20765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
20865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali	 if (item->cache_id != result_item->cache_id ||
20965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali	     item->size != result_item->size ||
21065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali	     item->aux_size != result_item->aux_size) {
21165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali	    continue;
21265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali	 }
21365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
2148fe2475a4b4c00475709c13d43eb9a57cce87cbcAlexey Bataev	 if (memcmp(item_aux, aux, item->aux_size) != 0) {
21565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali	    continue;
21665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali	 }
2176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
21865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali	 drm_intel_bo_map(cache->bo, false);
21965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali	 ret = memcmp(cache->bo->virtual + item->offset, data, item->size);
22065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali	 drm_intel_bo_unmap(cache->bo);
22165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali	 if (ret)
22265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali	    continue;
22365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
22465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali	 result_item->offset = item->offset;
22565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
22665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali	 return true;
22765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      }
22865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   }
22965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
23065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   return false;
23165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali}
23265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
23365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valistatic void
2347c64ef05e179d29646030e9d453081844ecc537aLarisse Voufobrw_upload_item_data(struct brw_cache *cache,
2357c64ef05e179d29646030e9d453081844ecc537aLarisse Voufo		     struct brw_cache_item *item,
2367c64ef05e179d29646030e9d453081844ecc537aLarisse Voufo		     const void *data)
2377c64ef05e179d29646030e9d453081844ecc537aLarisse Voufo{
2387c64ef05e179d29646030e9d453081844ecc537aLarisse Voufo   /* Allocate space in the cache BO for our new program. */
2397c64ef05e179d29646030e9d453081844ecc537aLarisse Voufo   if (cache->next_offset + item->size > cache->bo->size) {
240ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo      uint32_t new_size = cache->bo->size * 2;
241ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo
2427c64ef05e179d29646030e9d453081844ecc537aLarisse Voufo      while (cache->next_offset + item->size > new_size)
2437c64ef05e179d29646030e9d453081844ecc537aLarisse Voufo	 new_size *= 2;
2447c64ef05e179d29646030e9d453081844ecc537aLarisse Voufo
245ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo      brw_cache_new_bo(cache, new_size);
2467c64ef05e179d29646030e9d453081844ecc537aLarisse Voufo   }
247ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo
248ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo   /* If we would block on writing to an in-use program BO, just
2497c64ef05e179d29646030e9d453081844ecc537aLarisse Voufo    * recreate it.
250ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo    */
2514985429d6f0dddbe168ec0ed4de029d56294e644Larisse Voufo   if (cache->bo_used_by_gpu) {
252ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo      brw_cache_new_bo(cache, cache->bo->size);
2536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines   }
2546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
2557c64ef05e179d29646030e9d453081844ecc537aLarisse Voufo   item->offset = cache->next_offset;
256ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo
257ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo   /* Programs are always 64-byte aligned, so set up the next one now */
258ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo   cache->next_offset = ALIGN(item->offset + item->size, 64);
259ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo}
260ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo
2617c64ef05e179d29646030e9d453081844ecc537aLarisse Voufovoid
2627c64ef05e179d29646030e9d453081844ecc537aLarisse Voufobrw_upload_cache(struct brw_cache *cache,
26365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali		 enum brw_cache_id cache_id,
264ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo		 const void *key,
26565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali		 GLuint key_size,
26665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali		 const void *data,
26765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali		 GLuint data_size,
26865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali		 const void *aux,
26965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali		 GLuint aux_size,
27065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali		 uint32_t *out_offset,
27165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali		 void *out_aux)
27265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali{
27365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   struct brw_cache_item *item = CALLOC_STRUCT(brw_cache_item);
2748fe2475a4b4c00475709c13d43eb9a57cce87cbcAlexey Bataev   GLuint hash;
27565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   void *tmp;
27665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
27765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   item->cache_id = cache_id;
27865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   item->size = data_size;
27965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   item->key = key;
28065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   item->key_size = key_size;
28165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   item->aux_size = aux_size;
28265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   hash = hash_key(item);
28365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   item->hash = hash;
28465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
28565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   /* If we can find a matching prog/prog_data combo in the cache
28665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali    * already, then reuse the existing stuff.  This will mean not
28765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali    * flagging CACHE_NEW_* when transitioning between the two
28865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali    * equivalent hash keys.  This is notably useful for programs
28965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali    * generating shaders at runtime, where multiple shaders may
29065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali    * compile to the thing in our backend.
29165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali    */
29265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   if (!brw_try_upload_using_copy(cache, item, data, aux)) {
29365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      brw_upload_item_data(cache, item, data);
29465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   }
29565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
29665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   /* Set up the memory containing the key and aux_data */
29765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   tmp = malloc(key_size + aux_size);
29865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
29965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   memcpy(tmp, key, key_size);
300651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines   memcpy(tmp + key_size, aux, aux_size);
30165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
30265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   item->key = tmp;
30365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
30465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   if (cache->n_items > cache->size * 1.5)
30565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      rehash(cache);
30665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
30765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   hash %= cache->size;
30865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   item->next = cache->items[hash];
30965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   cache->items[hash] = item;
31065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   cache->n_items++;
31165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
31265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   /* Copy data to the buffer */
31365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   drm_intel_bo_subdata(cache->bo, item->offset, data_size, data);
31465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
31565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   *out_offset = item->offset;
31665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   *(void **)out_aux = (void *)((char *)item->key + item->key_size);
31765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   cache->brw->state.dirty.cache |= 1 << cache_id;
31865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali}
319651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
320651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid
32165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valibrw_init_caches(struct brw_context *brw)
32265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali{
32365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   struct intel_context *intel = &brw->intel;
32465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   struct brw_cache *cache = &brw->cache;
32565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
32665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   cache->brw = brw;
32765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
32865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   cache->size = 7;
32965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   cache->n_items = 0;
33065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   cache->items = (struct brw_cache_item **)
33165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      calloc(1, cache->size * sizeof(struct brw_cache_item));
33265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
33365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   cache->bo = drm_intel_bo_alloc(intel->bufmgr,
33465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali				  "program cache",
33565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali				  4096, 64);
33665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali}
33765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
33865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valistatic void
33965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valibrw_clear_cache(struct brw_context *brw, struct brw_cache *cache)
34065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali{
34165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   struct intel_context *intel = &brw->intel;
34265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   struct brw_cache_item *c, *next;
34365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   GLuint i;
3448fe2475a4b4c00475709c13d43eb9a57cce87cbcAlexey Bataev
3458fe2475a4b4c00475709c13d43eb9a57cce87cbcAlexey Bataev   DBG("%s\n", __FUNCTION__);
34665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
34765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   for (i = 0; i < cache->size; i++) {
34865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      for (c = cache->items[i]; c; c = next) {
34965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali	 next = c->next;
35065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali	 free((void *)c->key);
35165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali	 free(c);
35265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      }
35365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      cache->items[i] = NULL;
35465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   }
35565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
35665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   cache->n_items = 0;
35765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
35865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   /* Start putting programs into the start of the BO again, since
3598fe2475a4b4c00475709c13d43eb9a57cce87cbcAlexey Bataev    * we'll never find the old results.
3608fe2475a4b4c00475709c13d43eb9a57cce87cbcAlexey Bataev    */
36165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   cache->next_offset = 0;
36265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
36365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   /* We need to make sure that the programs get regenerated, since
36465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali    * any offsets leftover in brw_context will no longer be valid.
36565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali    */
36665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   brw->state.dirty.mesa |= ~0;
36765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   brw->state.dirty.brw |= ~0;
36865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   brw->state.dirty.cache |= ~0;
36965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   intel_batchbuffer_flush(intel);
37065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali}
37165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
37265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valivoid
37365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valibrw_state_cache_check_size(struct brw_context *brw)
37465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali{
37565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   /* un-tuned guess.  Each object is generally a page, so 1000 of them is 4 MB of
37665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali    * state cache.
37765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali    */
37865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   if (brw->cache.n_items > 1000) {
37965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      perf_debug("Exceeded state cache size limit.  Clearing the set "
38065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali                 "of compiled programs, which will trigger recompiles\n");
38165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali      brw_clear_cache(brw, &brw->cache);
38265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   }
38365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali}
38465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
38565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
38665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valistatic void
38765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valibrw_destroy_cache(struct brw_context *brw, struct brw_cache *cache)
38865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali{
38965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
39065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   DBG("%s\n", __FUNCTION__);
39165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
39265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   drm_intel_bo_unreference(cache->bo);
39365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   cache->bo = NULL;
39465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   brw_clear_cache(brw, cache);
39565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   free(cache->items);
39665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   cache->items = NULL;
39765efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   cache->size = 0;
39865efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali}
39965efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
40065efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali
40165efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valivoid
40265efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Valibrw_destroy_caches(struct brw_context *brw)
40365efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali{
40465efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali   brw_destroy_cache(brw, &brw->cache);
40565efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali}
40665efd10a5f54e4ffa23996d3779fd9318f01c4b7Faisal Vali