i965: store workaround_bo offset
[mesa.git] / src / mesa / drivers / dri / i965 / brw_program_cache.c
index 907150f507eb4f67a1066a7dc29bde827e778177..c1bdaab591c669174a0c0a1c611fa543a9a4693f 100644 (file)
  *  data) in return.  Objects in the cache may not have relocations
  * (pointers to other BOs) in them.
  *
- * The inner workings are a simple hash table based on a CRC of the
+ * The inner workings are a simple hash table based on a FNV-1a of the
  * key data.
  *
  * Replacement is not implemented.  Instead, when the cache gets too
  * big we throw out all of the cache data and let it get regenerated.
  */
 
-#include "main/imports.h"
 #include "main/streaming-load-memcpy.h"
 #include "x86/common_x86_asm.h"
 #include "intel_batchbuffer.h"
@@ -54,6 +53,7 @@
 #include "brw_cs.h"
 #include "brw_program.h"
 #include "compiler/brw_eu.h"
+#include "util/u_memory.h"
 
 #define FILE_DEBUG_FLAG DEBUG_STATE
 
@@ -69,8 +69,8 @@ struct brw_cache_item {
 
    /** for variable-sized keys */
    GLuint key_size;
-   GLuint aux_size;
-   const void *key;
+   GLuint prog_data_size;
+   const struct brw_base_prog_key *key;
 
    uint32_t offset;
    uint32_t size;
@@ -78,41 +78,27 @@ struct brw_cache_item {
    struct brw_cache_item *next;
 };
 
-static unsigned
-get_program_string_id(enum brw_cache_id cache_id, const void *key)
+enum brw_cache_id
+brw_stage_cache_id(gl_shader_stage stage)
 {
-   switch (cache_id) {
-   case BRW_CACHE_VS_PROG:
-      return ((struct brw_vs_prog_key *) key)->program_string_id;
-   case BRW_CACHE_TCS_PROG:
-      return ((struct brw_tcs_prog_key *) key)->program_string_id;
-   case BRW_CACHE_TES_PROG:
-      return ((struct brw_tes_prog_key *) key)->program_string_id;
-   case BRW_CACHE_GS_PROG:
-      return ((struct brw_gs_prog_key *) key)->program_string_id;
-   case BRW_CACHE_CS_PROG:
-      return ((struct brw_cs_prog_key *) key)->program_string_id;
-   case BRW_CACHE_FS_PROG:
-      return ((struct brw_wm_prog_key *) key)->program_string_id;
-   default:
-      unreachable("no program string id for this kind of program");
-   }
+   static const enum brw_cache_id stage_ids[] = {
+      BRW_CACHE_VS_PROG,
+      BRW_CACHE_TCS_PROG,
+      BRW_CACHE_TES_PROG,
+      BRW_CACHE_GS_PROG,
+      BRW_CACHE_FS_PROG,
+      BRW_CACHE_CS_PROG,
+   };
+   assert((int)stage >= 0 && stage < ARRAY_SIZE(stage_ids));
+   return stage_ids[stage];
 }
 
 static GLuint
 hash_key(struct brw_cache_item *item)
 {
-   GLuint *ikey = (GLuint *)item->key;
-   GLuint hash = item->cache_id, i;
-
-   assert(item->key_size % 4 == 0);
-
-   /* I'm sure this can be improved on:
-    */
-   for (i = 0; i < item->key_size/4; i++) {
-      hash ^= ikey[i];
-      hash = (hash << 5) | (hash >> 27);
-   }
+    uint32_t hash = _mesa_fnv32_1a_offset_bias;
+    hash = _mesa_fnv32_1a_accumulate(hash, item->cache_id);
+    hash = _mesa_fnv32_1a_accumulate_block(hash, item->key, item->key_size);
 
    return hash;
 }
@@ -179,12 +165,10 @@ rehash(struct brw_cache *cache)
  * Returns the buffer object matching cache_id and key, or NULL.
  */
 bool
-brw_search_cache(struct brw_cache *cache,
-                 enum brw_cache_id cache_id,
-                 const void *key, GLuint key_size,
-                 uint32_t *inout_offset, void *inout_aux)
+brw_search_cache(struct brw_cache *cache, enum brw_cache_id cache_id,
+                 const void *key, GLuint key_size, uint32_t *inout_offset,
+                 void *inout_prog_data, bool flag_state)
 {
-   struct brw_context *brw = cache->brw;
    struct brw_cache_item *item;
    struct brw_cache_item lookup;
    GLuint hash;
@@ -200,12 +184,14 @@ brw_search_cache(struct brw_cache *cache,
    if (item == NULL)
       return false;
 
-   void *aux = ((char *) item->key) + item->key_size;
+   void *prog_data = ((char *) item->key) + item->key_size;
 
-   if (item->offset != *inout_offset || aux != *((void **) inout_aux)) {
-      brw->ctx.NewDriverState |= (1 << cache_id);
+   if (item->offset != *inout_offset ||
+       prog_data != *((void **) inout_prog_data)) {
+      if (likely(flag_state))
+         cache->brw->ctx.NewDriverState |= (1 << cache_id);
       *inout_offset = item->offset;
-      *((void **) inout_aux) = aux;
+      *((void **) inout_prog_data) = prog_data;
    }
 
    return true;
@@ -220,9 +206,10 @@ brw_cache_new_bo(struct brw_cache *cache, uint32_t new_size)
    perf_debug("Copying to larger program cache: %u kB -> %u kB\n",
               (unsigned) cache->bo->size / 1024, new_size / 1024);
 
-   new_bo = brw_bo_alloc(brw->bufmgr, "program cache", new_size, 64);
+   new_bo = brw_bo_alloc(brw->bufmgr, "program cache", new_size,
+                         BRW_MEMZONE_SHADER);
    if (can_do_exec_capture(brw->screen))
-      new_bo->kflags = EXEC_OBJECT_CAPTURE;
+      new_bo->kflags |= EXEC_OBJECT_CAPTURE;
 
    void *map = brw_bo_map(brw, new_bo, MAP_READ | MAP_WRITE |
                                        MAP_ASYNC | MAP_PERSISTENT);
@@ -304,7 +291,7 @@ brw_find_previous_compile(struct brw_cache *cache,
    for (unsigned i = 0; i < cache->size; i++) {
       for (struct brw_cache_item *c = cache->items[i]; c; c = c->next) {
          if (c->cache_id == cache_id &&
-             get_program_string_id(cache_id, c->key) == program_string_id) {
+             c->key->program_string_id == program_string_id) {
             return c->key;
          }
       }
@@ -320,10 +307,10 @@ brw_upload_cache(struct brw_cache *cache,
                  GLuint key_size,
                  const void *data,
                  GLuint data_size,
-                 const void *aux,
-                 GLuint aux_size,
+                 const void *prog_data,
+                 GLuint prog_data_size,
                  uint32_t *out_offset,
-                 void *out_aux)
+                 void *out_prog_data)
 {
    struct brw_cache_item *item = CALLOC_STRUCT(brw_cache_item);
    const struct brw_cache_item *matching_data =
@@ -335,7 +322,7 @@ brw_upload_cache(struct brw_cache *cache,
    item->size = data_size;
    item->key = key;
    item->key_size = key_size;
-   item->aux_size = aux_size;
+   item->prog_data_size = prog_data_size;
    hash = hash_key(item);
    item->hash = hash;
 
@@ -354,11 +341,11 @@ brw_upload_cache(struct brw_cache *cache,
       memcpy(cache->map + item->offset, data, data_size);
    }
 
-   /* Set up the memory containing the key and aux_data */
-   tmp = malloc(key_size + aux_size);
+   /* Set up the memory containing the key and prog_data */
+   tmp = malloc(key_size + prog_data_size);
 
    memcpy(tmp, key, key_size);
-   memcpy(tmp + key_size, aux, aux_size);
+   memcpy(tmp + key_size, prog_data, prog_data_size);
 
    item->key = tmp;
 
@@ -371,7 +358,7 @@ brw_upload_cache(struct brw_cache *cache,
    cache->n_items++;
 
    *out_offset = item->offset;
-   *(void **)out_aux = (void *)((char *)item->key + item->key_size);
+   *(void **)out_prog_data = (void *)((char *)item->key + item->key_size);
    cache->brw->ctx.NewDriverState |= 1 << cache_id;
 }
 
@@ -387,9 +374,10 @@ brw_init_caches(struct brw_context *brw)
    cache->items =
       calloc(cache->size, sizeof(struct brw_cache_item *));
 
-   cache->bo = brw_bo_alloc(brw->bufmgr, "program cache",  4096, 64);
+   cache->bo = brw_bo_alloc(brw->bufmgr, "program cache", 16384,
+                            BRW_MEMZONE_SHADER);
    if (can_do_exec_capture(brw->screen))
-      cache->bo->kflags = EXEC_OBJECT_CAPTURE;
+      cache->bo->kflags |= EXEC_OBJECT_CAPTURE;
 
    cache->map = brw_bo_map(brw, cache->bo, MAP_READ | MAP_WRITE |
                                            MAP_ASYNC | MAP_PERSISTENT);
@@ -412,8 +400,8 @@ brw_clear_cache(struct brw_context *brw, struct brw_cache *cache)
              c->cache_id == BRW_CACHE_GS_PROG ||
              c->cache_id == BRW_CACHE_FS_PROG ||
              c->cache_id == BRW_CACHE_CS_PROG) {
-            const void *item_aux = c->key + c->key_size;
-            brw_stage_prog_data_free(item_aux);
+            const void *item_prog_data = ((char *)c->key) + c->key_size;
+            brw_stage_prog_data_free(item_prog_data);
          }
          free((void *)c->key);
          free(c);
@@ -459,6 +447,7 @@ brw_program_cache_check_size(struct brw_context *brw)
       perf_debug("Exceeded state cache size limit.  Clearing the set "
                  "of compiled programs, which will trigger recompiles\n");
       brw_clear_cache(brw, &brw->cache);
+      brw_cache_new_bo(&brw->cache, brw->cache.bo->size);
    }
 }