i965: Stop aux data compare preventing program binary re-use

Items in the program cache consist of three things: key, the data
representing the instructions and auxiliary data representing
uniform storage. The data consisting of instructions is stored into
a drm buffer object while the key and the auxiliary data reside in
malloced section. Now the cache uploading is equipped with a check
that iterates over existing items and seeks to find a another item
using identical instruction data than the one being just uploaded.
If such is found there is no need to add another section into the
drm buffer object holding identical copy of the existing one. The
item just being uploaded should instead simply point to the same
offset in the underlying drm buffer object.

Unfortunately the check for the matching instruction data is
coupled with a check for matching auxiliary data also. This
effectively prevents the cache from ever containing two items
that could share a section in the drm buffer object.

The constraint for the instruction data and auxiliary data to
match is, fortunately, unnecessary strong. When items are stored
into the cache they will anyway contain their own copy of the
auxiliary data (even if they matched - which they in real world
never will). The only thing the items would be sharing is the
instruction data and hence we should only check for that to match
and nothing else.

No piglit regression in jenkins.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Signed-off-by: Topi Pohjolainen <topi.pohjolainen@intel.com>
This commit is contained in:
Topi Pohjolainen 2015-06-25 14:00:41 +03:00
parent 12a66d91f6
commit 1bba29ed40
1 changed files with 20 additions and 32 deletions

View File

@ -200,36 +200,23 @@ brw_cache_new_bo(struct brw_cache *cache, uint32_t new_size)
} }
/** /**
* Attempts to find an item in the cache with identical data and aux * Attempts to find an item in the cache with identical data.
* data to use
*/ */
static bool static const struct brw_cache_item *
brw_try_upload_using_copy(struct brw_cache *cache, brw_lookup_prog(const struct brw_cache *cache,
struct brw_cache_item *result_item, enum brw_cache_id cache_id,
const void *data, const void *data, unsigned data_size)
const void *aux)
{ {
struct brw_context *brw = cache->brw; const struct brw_context *brw = cache->brw;
int i; int i;
struct brw_cache_item *item; const struct brw_cache_item *item;
for (i = 0; i < cache->size; i++) { for (i = 0; i < cache->size; i++) {
for (item = cache->items[i]; item; item = item->next) { for (item = cache->items[i]; item; item = item->next) {
const void *item_aux = item->key + item->key_size;
int ret; int ret;
if (item->cache_id != result_item->cache_id || if (item->cache_id != cache_id || item->size != data_size)
item->size != result_item->size ||
item->aux_size != result_item->aux_size) {
continue; continue;
}
if (cache->aux_compare[result_item->cache_id]) {
if (!cache->aux_compare[result_item->cache_id](item_aux, aux))
continue;
} else if (memcmp(item_aux, aux, item->aux_size) != 0) {
continue;
}
if (!brw->has_llc) if (!brw->has_llc)
drm_intel_bo_map(cache->bo, false); drm_intel_bo_map(cache->bo, false);
@ -239,13 +226,11 @@ brw_try_upload_using_copy(struct brw_cache *cache,
if (ret) if (ret)
continue; continue;
result_item->offset = item->offset; return item;
return true;
} }
} }
return false; return NULL;
} }
static uint32_t static uint32_t
@ -294,6 +279,8 @@ brw_upload_cache(struct brw_cache *cache,
{ {
struct brw_context *brw = cache->brw; struct brw_context *brw = cache->brw;
struct brw_cache_item *item = CALLOC_STRUCT(brw_cache_item); struct brw_cache_item *item = CALLOC_STRUCT(brw_cache_item);
const struct brw_cache_item *matching_data =
brw_lookup_prog(cache, cache_id, data, data_size);
GLuint hash; GLuint hash;
void *tmp; void *tmp;
@ -305,14 +292,15 @@ brw_upload_cache(struct brw_cache *cache,
hash = hash_key(item); hash = hash_key(item);
item->hash = hash; item->hash = hash;
/* If we can find a matching prog/prog_data combo in the cache /* If we can find a matching prog in the cache already, then reuse the
* already, then reuse the existing stuff. This will mean not * existing stuff without creating new copy into the underlying buffer
* flagging CACHE_NEW_* when transitioning between the two * object. This is notably useful for programs generating shaders at
* equivalent hash keys. This is notably useful for programs * runtime, where multiple shaders may compile to the same thing in our
* generating shaders at runtime, where multiple shaders may * backend.
* compile to the thing in our backend.
*/ */
if (!brw_try_upload_using_copy(cache, item, data, aux)) { if (matching_data) {
item->offset = matching_data->offset;
} else {
item->offset = brw_alloc_item_data(cache, data_size); item->offset = brw_alloc_item_data(cache, data_size);
/* Copy data to the buffer */ /* Copy data to the buffer */