From: Stefan Dösinger stefan@codeweavers.com
---
The is no VKD3D_SHADER_CACHE_FLAGS_NO_SERIALIZE flag for now because we don't have internal use for it yet. I think we should add it before making the API public. --- include/private/vkd3d_common.h | 16 ++++++++++++++++ include/vkd3d_types.h | 2 ++ libs/vkd3d/cache.c | 28 ++++++++++++++++++++++++++++ libs/vkd3d/device.c | 11 +++++++++-- 4 files changed, 55 insertions(+), 2 deletions(-)
diff --git a/include/private/vkd3d_common.h b/include/private/vkd3d_common.h index 10e2afd5d..4b339cd4a 100644 --- a/include/private/vkd3d_common.h +++ b/include/private/vkd3d_common.h @@ -32,6 +32,7 @@ #include <stdlib.h> #ifndef _WIN32 #include <pthread.h> +#include <errno.h> #endif
#ifdef _MSC_VER @@ -468,6 +469,21 @@ static inline void vkd3d_mutex_lock(struct vkd3d_mutex *lock) #endif }
+static inline bool vkd3d_mutex_trylock(struct vkd3d_mutex *lock) +{ +#ifdef _WIN32 + return TryEnterCriticalSection(&lock->lock); +#else + int ret; + + ret = pthread_mutex_trylock(&lock->lock); + if (ret && errno != EBUSY) + ERR("Could not lock the mutex, error %d.\n", ret); + + return !ret; +#endif +} + static inline void vkd3d_mutex_unlock(struct vkd3d_mutex *lock) { #ifdef _WIN32 diff --git a/include/vkd3d_types.h b/include/vkd3d_types.h index 2bab30fc8..de9248a67 100644 --- a/include/vkd3d_types.h +++ b/include/vkd3d_types.h @@ -59,6 +59,8 @@ enum vkd3d_result VKD3D_ERROR_NOT_FOUND = -7, /** The requested shader cache value was bigger than the passed buffer. */ VKD3D_ERROR_MORE_DATA = -8, + /** The cache lock is contended. */ + VKD3D_ERROR_LOCK_NOT_AVAILABLE = -9,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_RESULT), }; diff --git a/libs/vkd3d/cache.c b/libs/vkd3d/cache.c index 458067d0f..5c1e9e658 100644 --- a/libs/vkd3d/cache.c +++ b/libs/vkd3d/cache.c @@ -28,6 +28,8 @@ struct vkd3d_cache_entry_header struct vkd3d_shader_cache { unsigned int refcount; + struct vkd3d_mutex lock; + struct rb_tree tree; };
@@ -88,6 +90,7 @@ int vkd3d_shader_open_cache(struct vkd3d_shader_cache **cache)
object->refcount = 1; rb_init(&object->tree, vkd3d_shader_cache_compare_key); + vkd3d_mutex_init(&object->lock);
*cache = object;
@@ -117,6 +120,7 @@ unsigned int vkd3d_shader_cache_decref(struct vkd3d_shader_cache *cache) return refcount;
rb_destroy(&cache->tree, vkd3d_shader_cache_clear, NULL); + vkd3d_mutex_destroy(&cache->lock);
vkd3d_free(cache); return 0; @@ -151,6 +155,16 @@ static uint64_t vkd3d_shader_cache_hash_key(const void *key, size_t size) return ret; }
+static bool vkd3d_shader_cache_trylock(struct vkd3d_shader_cache *cache) +{ + return vkd3d_mutex_trylock(&cache->lock); +} + +static void vkd3d_shader_cache_unlock(struct vkd3d_shader_cache *cache) +{ + vkd3d_mutex_unlock(&cache->lock); +} + int vkd3d_shader_cache_put(struct vkd3d_shader_cache *cache, const void *key, size_t key_size, const void *value, size_t value_size) { @@ -161,6 +175,12 @@ int vkd3d_shader_cache_put(struct vkd3d_shader_cache *cache,
TRACE("%p, %p, %#zx, %p, %#zx.\n", cache, key, key_size, value, value_size);
+ if (!vkd3d_shader_cache_trylock(cache)) + { + WARN("Cache lock not available.\n"); + return VKD3D_ERROR_LOCK_NOT_AVAILABLE; + } + k.hash = vkd3d_shader_cache_hash_key(key, key_size); k.key = key; k.key_size = key_size; @@ -199,6 +219,7 @@ int vkd3d_shader_cache_put(struct vkd3d_shader_cache *cache, ret = VKD3D_OK;
done: + vkd3d_shader_cache_unlock(cache); return ret; }
@@ -213,6 +234,12 @@ int vkd3d_shader_cache_get(struct vkd3d_shader_cache *cache,
TRACE("%p, %p, %#zx, %p, %p.\n", cache, key, key_size, value, value_size);
+ if (!vkd3d_shader_cache_trylock(cache)) + { + WARN("Cache lock not available.\n"); + return VKD3D_ERROR_LOCK_NOT_AVAILABLE; + } + size_in = *value_size;
k.hash = vkd3d_shader_cache_hash_key(key, key_size); @@ -250,5 +277,6 @@ int vkd3d_shader_cache_get(struct vkd3d_shader_cache *cache, TRACE("Returning cached item %#"PRIx64".\n", e->h.hash);
done: + vkd3d_shader_cache_unlock(cache); return ret; } diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 6e8836eee..ba210b372 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -2679,7 +2679,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_cache_session_FindValue(ID3D12ShaderCache }
size = *value_size; - ret = vkd3d_shader_cache_get(session->cache, key, key_size, value, &size); + do + { + ret = vkd3d_shader_cache_get(session->cache, key, key_size, value, &size); + } while (ret == VKD3D_ERROR_LOCK_NOT_AVAILABLE); *value_size = size;
return hresult_from_vkd3d_result(ret); @@ -2700,7 +2703,11 @@ static HRESULT STDMETHODCALLTYPE d3d12_cache_session_StoreValue(ID3D12ShaderCach return E_INVALIDARG; }
- ret = vkd3d_shader_cache_put(session->cache, key, key_size, value, value_size); + do + { + ret = vkd3d_shader_cache_put(session->cache, key, key_size, value, value_size); + } while (ret == VKD3D_ERROR_LOCK_NOT_AVAILABLE); + return hresult_from_vkd3d_result(ret); }