diff --git a/include/vkd3d_types.h b/include/vkd3d_types.h index 18aa118f..420dd787 100644 --- a/include/vkd3d_types.h +++ b/include/vkd3d_types.h @@ -55,6 +55,10 @@ enum vkd3d_result VKD3D_ERROR_NOT_IMPLEMENTED = -5, /** The object or entry already exists. \since 1.12 */ VKD3D_ERROR_KEY_ALREADY_EXISTS = -6, + /** The requested object was not found. \since 1.12 */ + VKD3D_ERROR_NOT_FOUND = -7, + /** The output buffer is larger than the requested object \since 1.12. */ + VKD3D_ERROR_MORE_DATA = -8, VKD3D_FORCE_32_BIT_ENUM(VKD3D_RESULT), }; diff --git a/libs/vkd3d-common/error.c b/libs/vkd3d-common/error.c index a6efedde..2f978c49 100644 --- a/libs/vkd3d-common/error.c +++ b/libs/vkd3d-common/error.c @@ -37,6 +37,10 @@ HRESULT hresult_from_vkd3d_result(int vkd3d_result) return E_NOTIMPL; case VKD3D_ERROR_KEY_ALREADY_EXISTS: return DXGI_ERROR_ALREADY_EXISTS; + case VKD3D_ERROR_NOT_FOUND: + return DXGI_ERROR_NOT_FOUND; + case VKD3D_ERROR_MORE_DATA: + return DXGI_ERROR_MORE_DATA; default: FIXME("Unhandled vkd3d result %d.\n", vkd3d_result); return E_FAIL; diff --git a/libs/vkd3d/cache.c b/libs/vkd3d/cache.c index 05b717ba..448dfc6d 100644 --- a/libs/vkd3d/cache.c +++ b/libs/vkd3d/cache.c @@ -179,3 +179,54 @@ int vkd3d_shader_cache_put(struct vkd3d_shader_cache *cache, done: return ret; } + +int vkd3d_shader_cache_get(struct vkd3d_shader_cache *cache, + const void *key, size_t key_size, void *value, size_t *value_size) +{ + struct shader_cache_entry *e; + struct shader_cache_key k; + struct rb_entry *entry; + enum vkd3d_result ret; + size_t size_in; + + TRACE("%p, %p, %#zx, %p, %p.\n", cache, key, key_size, value, value_size); + + size_in = *value_size; + + k.hash = vkd3d_shader_cache_hash_key(key, key_size); + k.key = key; + k.key_size = key_size; + entry = rb_get(&cache->tree, &k); + if (!entry) + { + WARN("Entry not found.\n"); + ret = VKD3D_ERROR_NOT_FOUND; + goto done; + } + + e = RB_ENTRY_VALUE(entry, struct shader_cache_entry, entry); + + *value_size = e->h.value_size; + if (!value) + { + TRACE("Found item %#"PRIx64", returning needed size %#"PRIx64".\n", + e->h.hash, e->h.value_size); + ret = VKD3D_OK; + goto done; + } + + if (size_in < e->h.value_size) + { + WARN("Output buffer is too small for item %#"PRIx64", got %#zx want %#"PRIx64".\n", + e->h.hash, size_in, e->h.value_size); + ret = VKD3D_ERROR_MORE_DATA; + goto done; + } + + memcpy(value, e->payload + e->h.key_size, e->h.value_size); + ret = VKD3D_OK; + TRACE("Returning cached item %#"PRIx64".\n", e->h.hash); + +done: + return ret; +} diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index fe2669b2..cb2b6ad0 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -2685,10 +2685,24 @@ static HRESULT STDMETHODCALLTYPE d3d12_cache_session_GetDevice(ID3D12ShaderCache static HRESULT STDMETHODCALLTYPE d3d12_cache_session_FindValue(ID3D12ShaderCacheSession *iface, const void *key, UINT key_size, void *value, UINT *value_size) { - FIXME("iface %p, key %p, key_size %#x, value %p, value_size %p stub!\n", + struct d3d12_cache_session *session = impl_from_ID3D12ShaderCacheSession(iface); + enum vkd3d_result ret; + size_t size; + + TRACE("iface %p, key %p, key_size %#x, value %p, value_size %p.\n", iface, key, key_size, value, value_size); - return DXGI_ERROR_NOT_FOUND; + if (!value_size) + { + WARN("value_size is NULL, returning E_INVALIDARG.\n"); + return E_INVALIDARG; + } + + size = *value_size; + ret = vkd3d_shader_cache_get(session->cache, key, key_size, value, &size); + *value_size = size; + + return hresult_from_vkd3d_result(ret); } static HRESULT STDMETHODCALLTYPE d3d12_cache_session_StoreValue(ID3D12ShaderCacheSession *iface, diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 63bfce7d..84bdee92 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -1778,5 +1778,7 @@ unsigned int vkd3d_shader_cache_incref(struct vkd3d_shader_cache *cache); unsigned int vkd3d_shader_cache_decref(struct vkd3d_shader_cache *cache); int vkd3d_shader_cache_put(struct vkd3d_shader_cache *cache, const void *key, size_t key_size, const void *value, size_t value_size); +int vkd3d_shader_cache_get(struct vkd3d_shader_cache *cache, + const void *key, size_t key_size, void *value, size_t *value_size); #endif /* __VKD3D_PRIVATE_H */