ReactOS 0.4.17-dev-934-g091855f
cache.c
Go to the documentation of this file.
1/*
2 * Copyright 2024 Stefan Dösinger for CodeWeavers
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19#include "vkd3d_private.h"
20
22{
26};
27
29{
30 unsigned int refcount;
32
33 struct rb_tree tree;
34};
35
37{
41};
42
44{
46 const void *key;
48};
49
50static int vkd3d_shader_cache_compare_key(const void *key, const struct rb_entry *entry)
51{
53 const struct shader_cache_key *k = key;
54 int ret;
55
56 if ((ret = vkd3d_u64_compare(k->hash, e->h.hash)))
57 return ret;
58 if ((ret = vkd3d_u64_compare(k->key_size, e->h.key_size)))
59 return ret;
60
61 /* Until now we have not seen an actual hash collision. If the key didn't match it was always
62 * due to a bug in the serialization code or memory corruption. If you see this FIXME please
63 * investigate. */
64 if ((ret = memcmp(k->key, e->payload, k->key_size)))
65 FIXME("Actual case of a hash collision found.\n");
66 return ret;
67}
68
70 struct shader_cache_entry *e)
71{
72 const struct shader_cache_key k =
73 {
74 .hash = e->h.hash,
75 .key_size = e->h.key_size,
76 .key = e->payload
77 };
78
79 rb_put(&cache->tree, &k, &e->entry);
80}
81
83{
85
86 TRACE("%p.\n", cache);
87
88 object = vkd3d_malloc(sizeof(*object));
89 if (!object)
91
92 object->refcount = 1;
95
96 *cache = object;
97
98 return VKD3D_OK;
99}
100
102{
103 unsigned int refcount = vkd3d_atomic_increment_u32(&cache->refcount);
104 TRACE("cache %p refcount %u.\n", cache, refcount);
105 return refcount;
106}
107
109{
111 vkd3d_free(e->payload);
112 vkd3d_free(e);
113}
114
116{
117 unsigned int refcount = vkd3d_atomic_decrement_u32(&cache->refcount);
118 TRACE("cache %p refcount %u.\n", cache, refcount);
119
120 if (refcount)
121 return refcount;
122
125
127 return 0;
128}
129
130static uint64_t vkd3d_shader_cache_hash_key(const void *key, size_t size)
131{
132 static const uint64_t fnv_prime = 0x00000100000001b3;
133 uint64_t hash = 0xcbf29ce484222325;
134 const uint8_t *k = key;
135 size_t i;
136
137 for (i = 0; i < size; ++i)
138 hash = (hash ^ k[i]) * fnv_prime;
139
140 return hash;
141}
142
144{
146}
147
149{
151}
152
154 const void *key, size_t key_size, const void *value, size_t value_size)
155{
156 struct shader_cache_entry *e;
157 struct shader_cache_key k;
158 struct rb_entry *entry;
159 enum vkd3d_result ret;
160
161 TRACE("%p, %p, %#zx, %p, %#zx.\n", cache, key, key_size, value, value_size);
162
163 k.hash = vkd3d_shader_cache_hash_key(key, key_size);
164 k.key = key;
165 k.key_size = key_size;
166
168
169 entry = rb_get(&cache->tree, &k);
171
172 if (e)
173 {
174 WARN("Key already exists, returning VKD3D_ERROR_KEY_ALREADY_EXISTS.\n");
176 goto done;
177 }
178
179 e = vkd3d_malloc(sizeof(*e));
180 if (!e)
181 {
183 goto done;
184 }
185 e->payload = vkd3d_malloc(key_size + value_size);
186 if (!e->payload)
187 {
188 vkd3d_free(e);
190 goto done;
191 }
192
193 e->h.key_size = key_size;
194 e->h.value_size = value_size;
195 e->h.hash = k.hash;
196 memcpy(e->payload, key, key_size);
197 memcpy(e->payload + key_size, value, value_size);
198
200 TRACE("Cache entry %#"PRIx64" stored.\n", k.hash);
201 ret = VKD3D_OK;
202
203done:
205 return ret;
206}
207
209 const void *key, size_t key_size, void *value, size_t *value_size)
210{
211 struct shader_cache_entry *e;
212 struct shader_cache_key k;
213 struct rb_entry *entry;
214 enum vkd3d_result ret;
215 size_t size_in;
216
217 TRACE("%p, %p, %#zx, %p, %p.\n", cache, key, key_size, value, value_size);
218
219 size_in = *value_size;
220
221 k.hash = vkd3d_shader_cache_hash_key(key, key_size);
222 k.key = key;
223 k.key_size = key_size;
224
226
227 entry = rb_get(&cache->tree, &k);
228 if (!entry)
229 {
230 WARN("Entry not found.\n");
232 goto done;
233 }
234
236
237 *value_size = e->h.value_size;
238 if (!value)
239 {
240 TRACE("Found item %#"PRIx64", returning needed size %#"PRIx64".\n",
241 e->h.hash, e->h.value_size);
242 ret = VKD3D_OK;
243 goto done;
244 }
245
246 if (size_in < e->h.value_size)
247 {
248 WARN("Output buffer is too small for item %#"PRIx64", got %#zx want %#"PRIx64".\n",
249 e->h.hash, size_in, e->h.value_size);
251 goto done;
252 }
253
254 memcpy(value, e->payload + e->h.key_size, e->h.value_size);
255 ret = VKD3D_OK;
256 TRACE("Returning cached item %#"PRIx64".\n", e->h.hash);
257
258done:
260 return ret;
261}
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define NULL
Definition: types.h:112
UINT64 uint64_t
Definition: types.h:77
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2807
#define PRIx64
Definition: inttypes.h:29
unsigned char uint8_t
Definition: stdint.h:33
return ret
Definition: mutex.c:147
GLsizeiptr size
Definition: glext.h:5919
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
uint32_t entry
Definition: isohybrid.c:63
#define e
Definition: ke_i.h:82
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
int k
Definition: mpi.c:3369
#define RB_ENTRY_VALUE(element, type, field)
Definition: rbtree.h:26
static void rb_destroy(struct rb_tree *tree, rb_traverse_func_t *callback, void *context)
Definition: rbtree.h:185
static int rb_put(struct rb_tree *tree, const void *key, struct rb_entry *entry)
Definition: rbtree.h:204
static struct rb_entry * rb_get(const struct rb_tree *tree, const void *key)
Definition: rbtree.h:192
static void rb_init(struct rb_tree *tree, rb_compare_func_t compare)
Definition: rbtree.h:173
static void vkd3d_shader_cache_add_entry(struct vkd3d_shader_cache *cache, struct shader_cache_entry *e)
Definition: cache.c:69
static void vkd3d_shader_cache_destroy_entry(struct rb_entry *entry, void *context)
Definition: cache.c:108
static uint64_t vkd3d_shader_cache_hash_key(const void *key, size_t size)
Definition: cache.c:130
static void vkd3d_shader_cache_lock(struct vkd3d_shader_cache *cache)
Definition: cache.c:143
static int vkd3d_shader_cache_compare_key(const void *key, const struct rb_entry *entry)
Definition: cache.c:50
static void vkd3d_shader_cache_unlock(struct vkd3d_shader_cache *cache)
Definition: cache.c:148
int vkd3d_shader_cache_put(struct vkd3d_shader_cache *cache, const void *key, size_t key_size, const void *value, size_t value_size)
Definition: cache.c:153
int vkd3d_shader_cache_get(struct vkd3d_shader_cache *cache, const void *key, size_t key_size, void *value, size_t *value_size)
Definition: cache.c:208
unsigned int vkd3d_shader_cache_incref(struct vkd3d_shader_cache *cache)
Definition: cache.c:101
unsigned int vkd3d_shader_cache_decref(struct vkd3d_shader_cache *cache)
Definition: cache.c:115
int vkd3d_shader_open_cache(struct vkd3d_shader_cache **cache)
Definition: cache.c:82
#define TRACE(s)
Definition: solgame.cpp:4
Definition: cache.c:41
HANDLE lock
Definition: cache.c:44
Definition: http.c:7252
struct list entry
Definition: wpp.c:51
Definition: copy.c:22
Definition: rbtree.h:30
Definition: rbtree.h:40
Definition: cache.c:37
uint8_t * payload
Definition: cache.c:40
struct rb_entry entry
Definition: cache.c:39
uint64_t hash
Definition: cache.c:45
const void * key
Definition: cache.c:46
uint64_t key_size
Definition: cache.c:47
Definition: cache.c:22
uint64_t hash
Definition: cache.c:23
uint64_t key_size
Definition: cache.c:24
uint64_t value_size
Definition: cache.c:25
struct vkd3d_mutex lock
Definition: cache.c:31
unsigned int refcount
Definition: cache.c:30
Definition: pdh_main.c:64
static void vkd3d_mutex_init(struct vkd3d_mutex *lock)
Definition: vkd3d_common.h:560
static void vkd3d_mutex_unlock(struct vkd3d_mutex *lock)
Definition: vkd3d_common.h:584
static void vkd3d_mutex_lock(struct vkd3d_mutex *lock)
Definition: vkd3d_common.h:572
static void vkd3d_mutex_destroy(struct vkd3d_mutex *lock)
Definition: vkd3d_common.h:596
static uint32_t vkd3d_atomic_decrement_u32(uint32_t volatile *x)
Definition: vkd3d_common.h:477
static int vkd3d_u64_compare(uint64_t x, uint64_t y)
Definition: vkd3d_common.h:391
static uint32_t vkd3d_atomic_increment_u32(uint32_t volatile *x)
Definition: vkd3d_common.h:482
static void vkd3d_free(void *ptr)
Definition: vkd3d_memory.h:52
static void * vkd3d_malloc(size_t size)
Definition: vkd3d_memory.h:28
vkd3d_result
Definition: vkd3d_types.h:41
@ VKD3D_ERROR_KEY_ALREADY_EXISTS
Definition: vkd3d_types.h:57
@ VKD3D_ERROR_MORE_DATA
Definition: vkd3d_types.h:61
@ VKD3D_OK
Definition: vkd3d_types.h:43
@ VKD3D_ERROR_OUT_OF_MEMORY
Definition: vkd3d_types.h:49
@ VKD3D_ERROR_NOT_FOUND
Definition: vkd3d_types.h:59