From: Stefan Dösinger stefan@codeweavers.com
--- libs/vkd3d/cache.c | 79 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 3 deletions(-)
diff --git a/libs/vkd3d/cache.c b/libs/vkd3d/cache.c index 51be6f265..c82c19090 100644 --- a/libs/vkd3d/cache.c +++ b/libs/vkd3d/cache.c @@ -22,16 +22,89 @@ #include <stdarg.h> #include <stdio.h>
+/* List of open caches. I expect the number to be small. */ +static struct list cache_list = LIST_INIT(cache_list); +static struct vkd3d_mutex cache_list_mutex; +static LONG cache_mutex_initialized; + +struct vkd3d_shader_cache +{ + LONG refcount; + struct vkd3d_shader_cache_desc desc; + struct list cache_list_entry; + char name[1]; +}; + int vkd3d_shader_cache_open(const char *name, const struct vkd3d_shader_cache_desc *desc, struct vkd3d_shader_cache **cache) { - FIXME("%s, %p, %p: stub!\n", debugstr_a(name), desc, cache); - return VKD3D_ERROR_NOT_IMPLEMENTED; + struct vkd3d_shader_cache *object; + size_t size; + + TRACE("%s, %p, %p.\n", debugstr_a(name), desc, cache); + + if (!name || !desc) + { + WARN("No name or description, returning VKD3D_ERROR_INVALID_ARGUMENT.\n"); + return E_INVALIDARG; + } + + /* FIXME: This isn't thread safe and cache_mutex_initialized might overflow. Do we have a + * something like DllMain or a platform-independent InitializeOnce? */ + if (InterlockedIncrement(&cache_mutex_initialized) == 1) + vkd3d_mutex_init(&cache_list_mutex); + + vkd3d_mutex_lock(&cache_list_mutex); + LIST_FOR_EACH_ENTRY(object, &cache_list, struct vkd3d_shader_cache, cache_list_entry) + { + if (!strcmp(object->name, name)) + { + TRACE("found an open cache of name %s.\n", debugstr_a(name)); + if (object->desc.version != desc->version) + { + WARN("Version mismatch: %"PRIu64", %"PRIu64".\n", object->desc.version, desc->version); + vkd3d_mutex_unlock(&cache_list_mutex); + return VKD3D_ERROR_VERSION_MISMATCH; + } + InterlockedIncrement(&object->refcount); + *cache = object; + vkd3d_mutex_unlock(&cache_list_mutex); + return S_OK; + } + } + + size = strlen(name) + 1; + object = vkd3d_calloc(1, offsetof(struct vkd3d_shader_cache, name[size])); + if (!object) + { + vkd3d_mutex_unlock(&cache_list_mutex); + return VKD3D_ERROR_OUT_OF_MEMORY; + } + + object->refcount = 1; + object->desc = *desc; + memcpy(object->name, name, size); + + list_add_head(&cache_list, &object->cache_list_entry); + vkd3d_mutex_unlock(&cache_list_mutex); + + *cache = object; + return S_OK; }
void vkd3d_shader_cache_close(struct vkd3d_shader_cache *cache) { - FIXME("Stub!\n"); + ULONG refcount = InterlockedDecrement(&cache->refcount); + TRACE("cache %s refcount %u.\n", cache->name, refcount); + + if (refcount) + return; + + vkd3d_mutex_lock(&cache_list_mutex); + list_remove(&cache->cache_list_entry); + vkd3d_mutex_unlock(&cache_list_mutex); + + vkd3d_free(cache); }
int vkd3d_shader_cache_put(struct vkd3d_shader_cache *cache,