Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/auxiliary/cso_cache/cso_cache.c
4565 views
1
/**************************************************************************
2
*
3
* Copyright 2007 VMware, Inc.
4
* All Rights Reserved.
5
*
6
* Permission is hereby granted, free of charge, to any person obtaining a
7
* copy of this software and associated documentation files (the
8
* "Software"), to deal in the Software without restriction, including
9
* without limitation the rights to use, copy, modify, merge, publish,
10
* distribute, sub license, and/or sell copies of the Software, and to
11
* permit persons to whom the Software is furnished to do so, subject to
12
* the following conditions:
13
*
14
* The above copyright notice and this permission notice (including the
15
* next paragraph) shall be included in all copies or substantial portions
16
* of the Software.
17
*
18
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
*
26
**************************************************************************/
27
28
/* Authors: Zack Rusin <[email protected]>
29
*/
30
31
#include "util/u_debug.h"
32
33
#include "util/u_memory.h"
34
35
#include "cso_cache.h"
36
#include "cso_hash.h"
37
38
39
static inline struct cso_hash *_cso_hash_for_type(struct cso_cache *sc, enum cso_cache_type type)
40
{
41
return &sc->hashes[type];
42
}
43
44
/* Default delete callback. It can also be used by custom callbacks. */
45
void cso_delete_state(struct pipe_context *pipe, void *state,
46
enum cso_cache_type type)
47
{
48
switch (type) {
49
case CSO_BLEND:
50
pipe->delete_blend_state(pipe, ((struct cso_blend*)state)->data);
51
break;
52
case CSO_SAMPLER:
53
pipe->delete_sampler_state(pipe, ((struct cso_sampler*)state)->data);
54
break;
55
case CSO_DEPTH_STENCIL_ALPHA:
56
pipe->delete_depth_stencil_alpha_state(pipe,
57
((struct cso_depth_stencil_alpha*)state)->data);
58
break;
59
case CSO_RASTERIZER:
60
pipe->delete_rasterizer_state(pipe, ((struct cso_rasterizer*)state)->data);
61
break;
62
case CSO_VELEMENTS:
63
pipe->delete_vertex_elements_state(pipe, ((struct cso_velements*)state)->data);
64
break;
65
default:
66
assert(0);
67
}
68
69
FREE(state);
70
}
71
72
73
static inline void sanitize_hash(struct cso_cache *sc,
74
struct cso_hash *hash,
75
enum cso_cache_type type,
76
int max_size)
77
{
78
if (sc->sanitize_cb)
79
sc->sanitize_cb(hash, type, max_size, sc->sanitize_data);
80
}
81
82
83
static inline void sanitize_cb(struct cso_hash *hash, enum cso_cache_type type,
84
int max_size, void *user_data)
85
{
86
struct cso_cache *cache = (struct cso_cache *)user_data;
87
88
/* if we're approach the maximum size, remove fourth of the entries
89
* otherwise every subsequent call will go through the same */
90
int hash_size = cso_hash_size(hash);
91
int max_entries = (max_size > hash_size) ? max_size : hash_size;
92
int to_remove = (max_size < max_entries) * max_entries/4;
93
if (hash_size > max_size)
94
to_remove += hash_size - max_size;
95
while (to_remove) {
96
/*remove elements until we're good */
97
/*fixme: currently we pick the nodes to remove at random*/
98
struct cso_hash_iter iter = cso_hash_first_node(hash);
99
void *cso = cso_hash_take(hash, cso_hash_iter_key(iter));
100
cache->delete_cso(cache->delete_cso_ctx, cso, type);
101
--to_remove;
102
}
103
}
104
105
struct cso_hash_iter
106
cso_insert_state(struct cso_cache *sc,
107
unsigned hash_key, enum cso_cache_type type,
108
void *state)
109
{
110
struct cso_hash *hash = _cso_hash_for_type(sc, type);
111
sanitize_hash(sc, hash, type, sc->max_size);
112
113
return cso_hash_insert(hash, hash_key, state);
114
}
115
116
struct cso_hash_iter
117
cso_find_state(struct cso_cache *sc,
118
unsigned hash_key, enum cso_cache_type type)
119
{
120
struct cso_hash *hash = _cso_hash_for_type(sc, type);
121
122
return cso_hash_find(hash, hash_key);
123
}
124
125
126
void *cso_hash_find_data_from_template( struct cso_hash *hash,
127
unsigned hash_key,
128
void *templ,
129
int size )
130
{
131
struct cso_hash_iter iter = cso_hash_find(hash, hash_key);
132
while (!cso_hash_iter_is_null(iter)) {
133
void *iter_data = cso_hash_iter_data(iter);
134
if (!memcmp(iter_data, templ, size)) {
135
/* We found a match
136
*/
137
return iter_data;
138
}
139
iter = cso_hash_iter_next(iter);
140
}
141
return NULL;
142
}
143
144
145
struct cso_hash_iter cso_find_state_template(struct cso_cache *sc,
146
unsigned hash_key, enum cso_cache_type type,
147
void *templ, unsigned size)
148
{
149
struct cso_hash_iter iter = cso_find_state(sc, hash_key, type);
150
while (!cso_hash_iter_is_null(iter)) {
151
void *iter_data = cso_hash_iter_data(iter);
152
if (!memcmp(iter_data, templ, size))
153
return iter;
154
iter = cso_hash_iter_next(iter);
155
}
156
return iter;
157
}
158
159
void cso_cache_init(struct cso_cache *sc, struct pipe_context *pipe)
160
{
161
memset(sc, 0, sizeof(*sc));
162
163
sc->max_size = 4096;
164
for (int i = 0; i < CSO_CACHE_MAX; i++)
165
cso_hash_init(&sc->hashes[i]);
166
167
sc->sanitize_cb = sanitize_cb;
168
sc->sanitize_data = sc;
169
sc->delete_cso = (cso_delete_cso_callback)cso_delete_state;
170
sc->delete_cso_ctx = pipe;
171
}
172
173
static void cso_delete_all(struct cso_cache *sc, enum cso_cache_type type)
174
{
175
struct cso_hash *hash = _cso_hash_for_type(sc, type);
176
struct cso_hash_iter iter;
177
178
iter = cso_hash_first_node(hash);
179
while (!cso_hash_iter_is_null(iter)) {
180
void *state = cso_hash_iter_data(iter);
181
iter = cso_hash_iter_next(iter);
182
if (state) {
183
sc->delete_cso(sc->delete_cso_ctx, state, type);
184
}
185
}
186
}
187
188
void cso_cache_delete(struct cso_cache *sc)
189
{
190
int i;
191
192
/* delete driver data */
193
cso_delete_all(sc, CSO_BLEND);
194
cso_delete_all(sc, CSO_DEPTH_STENCIL_ALPHA);
195
cso_delete_all(sc, CSO_RASTERIZER);
196
cso_delete_all(sc, CSO_SAMPLER);
197
cso_delete_all(sc, CSO_VELEMENTS);
198
199
for (i = 0; i < CSO_CACHE_MAX; i++)
200
cso_hash_deinit(&sc->hashes[i]);
201
}
202
203
void cso_set_maximum_cache_size(struct cso_cache *sc, int number)
204
{
205
int i;
206
207
sc->max_size = number;
208
209
for (i = 0; i < CSO_CACHE_MAX; i++)
210
sanitize_hash(sc, &sc->hashes[i], i, sc->max_size);
211
}
212
213
void cso_cache_set_sanitize_callback(struct cso_cache *sc,
214
cso_sanitize_callback cb,
215
void *user_data)
216
{
217
sc->sanitize_cb = cb;
218
sc->sanitize_data = user_data;
219
}
220
221
void cso_cache_set_delete_cso_callback(struct cso_cache *sc,
222
cso_delete_cso_callback delete_cso,
223
void *ctx)
224
{
225
sc->delete_cso = delete_cso;
226
sc->delete_cso_ctx = ctx;
227
}
228
229