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