From: Stefan Dösinger stefan@codeweavers.com
--- libs/vkd3d/cache.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
diff --git a/libs/vkd3d/cache.c b/libs/vkd3d/cache.c index 1dce309f9..cddb40eff 100644 --- a/libs/vkd3d/cache.c +++ b/libs/vkd3d/cache.c @@ -27,14 +27,52 @@ static struct list cache_list = LIST_INIT(cache_list); static struct vkd3d_mutex cache_list_mutex; static LONG cache_mutex_initialized;
+/* Data structures used in the serialized files. Changing these will break compatibility with + * existing cache files, so bump the cache version if doing so. + * + * We don't intend these files to be read by third party code, so consider them a vkd3d + * implementation detail. */ +struct vkd3d_cache_object_v1 +{ + uint64_t hash; + uint32_t offset; /* Where key + value are located in the .val file. */ + uint32_t disk_size; /* Size of the entry in the .val file. May be compressed. */ + uint32_t key_size; /* Size of the app provided key. */ + uint32_t value_size; /* Size of the value. key_size + value_size = uncompressed entry size. */ +}; + +/* End disk data structures. */ + struct vkd3d_shader_cache { LONG refcount; struct vkd3d_shader_cache_desc desc; struct list cache_list_entry; + + struct rb_tree tree; + char name[1]; };
+struct shader_cache_entry +{ + struct vkd3d_cache_object_v1 d; + struct rb_entry entry; /* Entry in the hash table. */ + uint8_t *payload; /* App key + value. Separate allocation to allow eviction. */ +}; + +static int vkd3d_shader_cache_compare_key(const void *key, const struct rb_entry *entry) +{ + const uint64_t *k = key; + const struct shader_cache_entry *e = RB_ENTRY_VALUE(entry, struct shader_cache_entry, entry); + + if (*k < e->d.hash) + return -1; + if (*k > e->d.hash) + return 1; + return 0; +} + int vkd3d_shader_cache_open(const char *name, const struct vkd3d_shader_cache_desc *desc, struct vkd3d_shader_cache **cache) { @@ -84,6 +122,7 @@ int vkd3d_shader_cache_open(const char *name, object->refcount = 1; object->desc = *desc; memcpy(object->name, name, size); + rb_init(&object->tree, vkd3d_shader_cache_compare_key);
list_add_head(&cache_list, &object->cache_list_entry); vkd3d_mutex_unlock(&cache_list_mutex); @@ -92,6 +131,12 @@ int vkd3d_shader_cache_open(const char *name, return VKD3D_OK; }
+static void vkd3d_shader_cache_clear(struct rb_entry *entry, void *context) +{ + struct shader_cache_entry *e = RB_ENTRY_VALUE(entry, struct shader_cache_entry, entry); + vkd3d_free(e); +} + void vkd3d_shader_cache_close(struct vkd3d_shader_cache *cache) { ULONG refcount = InterlockedDecrement(&cache->refcount); @@ -104,6 +149,8 @@ void vkd3d_shader_cache_close(struct vkd3d_shader_cache *cache) list_remove(&cache->cache_list_entry); vkd3d_mutex_unlock(&cache_list_mutex);
+ rb_destroy(&cache->tree, vkd3d_shader_cache_clear, NULL); + vkd3d_free(cache); }