summaryrefslogtreecommitdiffstats
path: root/src/intel/vulkan/anv_pipeline_cache.c
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2018-10-12 17:40:21 -0500
committerJason Ekstrand <[email protected]>2019-01-10 19:15:27 -0600
commitf6aa9f71851614b06c11221f01e78493551ed68b (patch)
tree90340db667081705532670586c431ad1cf6d3995 /src/intel/vulkan/anv_pipeline_cache.c
parent8dfda5ebbe58e2c00043bd0fe9d249e57f3c4bd1 (diff)
anv/pipeline_cache: Add support for caching NIR
Reviewed-by: Lionel Landwerlin <[email protected]>
Diffstat (limited to 'src/intel/vulkan/anv_pipeline_cache.c')
-rw-r--r--src/intel/vulkan/anv_pipeline_cache.c100
1 files changed, 100 insertions, 0 deletions
diff --git a/src/intel/vulkan/anv_pipeline_cache.c b/src/intel/vulkan/anv_pipeline_cache.c
index eac058fb47f..18f310b06ee 100644
--- a/src/intel/vulkan/anv_pipeline_cache.c
+++ b/src/intel/vulkan/anv_pipeline_cache.c
@@ -26,6 +26,7 @@
#include "util/debug.h"
#include "util/disk_cache.h"
#include "util/mesa-sha1.h"
+#include "nir/nir_serialize.h"
#include "anv_private.h"
struct anv_shader_bin *
@@ -211,6 +212,18 @@ shader_bin_key_compare_func(const void *void_a, const void *void_b)
return memcmp(a->data, b->data, a->size) == 0;
}
+static uint32_t
+sha1_hash_func(const void *sha1)
+{
+ return _mesa_hash_data(sha1, 20);
+}
+
+static bool
+sha1_compare_func(const void *sha1_a, const void *sha1_b)
+{
+ return memcmp(sha1_a, sha1_b, 20) == 0;
+}
+
void
anv_pipeline_cache_init(struct anv_pipeline_cache *cache,
struct anv_device *device,
@@ -222,6 +235,8 @@ anv_pipeline_cache_init(struct anv_pipeline_cache *cache,
if (cache_enabled) {
cache->cache = _mesa_hash_table_create(NULL, shader_bin_key_hash_func,
shader_bin_key_compare_func);
+ cache->nir_cache = _mesa_hash_table_create(NULL, sha1_hash_func,
+ sha1_compare_func);
} else {
cache->cache = NULL;
}
@@ -641,3 +656,88 @@ anv_device_upload_kernel(struct anv_device *device,
return bin;
}
+
+struct serialized_nir {
+ unsigned char sha1_key[20];
+ size_t size;
+ char data[0];
+};
+
+struct nir_shader *
+anv_device_search_for_nir(struct anv_device *device,
+ struct anv_pipeline_cache *cache,
+ const nir_shader_compiler_options *nir_options,
+ unsigned char sha1_key[20],
+ void *mem_ctx)
+{
+ if (cache) {
+ const struct serialized_nir *snir = NULL;
+
+ pthread_mutex_lock(&cache->mutex);
+ struct hash_entry *entry =
+ _mesa_hash_table_search(cache->nir_cache, sha1_key);
+ if (entry)
+ snir = entry->data;
+ pthread_mutex_unlock(&cache->mutex);
+
+ if (snir) {
+ struct blob_reader blob;
+ blob_reader_init(&blob, snir->data, snir->size);
+
+ nir_shader *nir = nir_deserialize(mem_ctx, nir_options, &blob);
+ if (blob.overrun) {
+ ralloc_free(nir);
+ } else {
+ return nir;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+void
+anv_device_upload_nir(struct anv_device *device,
+ struct anv_pipeline_cache *cache,
+ const struct nir_shader *nir,
+ unsigned char sha1_key[20])
+{
+ if (cache) {
+ pthread_mutex_lock(&cache->mutex);
+ struct hash_entry *entry =
+ _mesa_hash_table_search(cache->nir_cache, sha1_key);
+ pthread_mutex_unlock(&cache->mutex);
+ if (entry)
+ return;
+
+ struct blob blob;
+ blob_init(&blob);
+
+ nir_serialize(&blob, nir);
+ if (blob.out_of_memory) {
+ blob_finish(&blob);
+ return;
+ }
+
+ pthread_mutex_lock(&cache->mutex);
+ /* Because ralloc isn't thread-safe, we have to do all this inside the
+ * lock. We could unlock for the big memcpy but it's probably not worth
+ * the hassle.
+ */
+ entry = _mesa_hash_table_search(cache->nir_cache, sha1_key);
+ if (entry) {
+ pthread_mutex_unlock(&cache->mutex);
+ return;
+ }
+
+ struct serialized_nir *snir =
+ ralloc_size(cache->nir_cache, sizeof(*snir) + blob.size);
+ memcpy(snir->sha1_key, sha1_key, 20);
+ snir->size = blob.size;
+ memcpy(snir->data, blob.data, blob.size);
+
+ _mesa_hash_table_insert(cache->nir_cache, snir->sha1_key, snir);
+
+ pthread_mutex_unlock(&cache->mutex);
+ }
+}