00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "pipe/p_debug.h"
00032
00033 #include "util/u_memory.h"
00034
00035 #include "cso_cache.h"
00036 #include "cso_hash.h"
00037
00038
00039 struct cso_cache {
00040 struct cso_hash *blend_hash;
00041 struct cso_hash *depth_stencil_hash;
00042 struct cso_hash *fs_hash;
00043 struct cso_hash *vs_hash;
00044 struct cso_hash *rasterizer_hash;
00045 struct cso_hash *sampler_hash;
00046 int max_size;
00047
00048 cso_sanitize_callback sanitize_cb;
00049 void *sanitize_data;
00050 };
00051
00052 #if 1
00053 static unsigned hash_key(const void *key, unsigned key_size)
00054 {
00055 unsigned *ikey = (unsigned *)key;
00056 unsigned hash = 0, i;
00057
00058 assert(key_size % 4 == 0);
00059
00060
00061
00062 for (i = 0; i < key_size/4; i++)
00063 hash ^= ikey[i];
00064
00065 return hash;
00066 }
00067 #else
00068 static unsigned hash_key(const unsigned char *p, int n)
00069 {
00070 unsigned h = 0;
00071 unsigned g;
00072
00073 while (n--) {
00074 h = (h << 4) + *p++;
00075 if ((g = (h & 0xf0000000)) != 0)
00076 h ^= g >> 23;
00077 h &= ~g;
00078 }
00079 return h;
00080 }
00081 #endif
00082
00083 unsigned cso_construct_key(void *item, int item_size)
00084 {
00085 return hash_key((item), item_size);
00086 }
00087
00088 static struct cso_hash *_cso_hash_for_type(struct cso_cache *sc, enum cso_cache_type type)
00089 {
00090 struct cso_hash *hash = 0;
00091
00092 switch(type) {
00093 case CSO_BLEND:
00094 hash = sc->blend_hash;
00095 break;
00096 case CSO_SAMPLER:
00097 hash = sc->sampler_hash;
00098 break;
00099 case CSO_DEPTH_STENCIL_ALPHA:
00100 hash = sc->depth_stencil_hash;
00101 break;
00102 case CSO_RASTERIZER:
00103 hash = sc->rasterizer_hash;
00104 break;
00105 case CSO_FRAGMENT_SHADER:
00106 hash = sc->fs_hash;
00107 break;
00108 case CSO_VERTEX_SHADER:
00109 hash = sc->vs_hash;
00110 break;
00111 }
00112
00113 return hash;
00114 }
00115
00116 static int _cso_size_for_type(enum cso_cache_type type)
00117 {
00118 switch(type) {
00119 case CSO_BLEND:
00120 return sizeof(struct pipe_blend_state);
00121 case CSO_SAMPLER:
00122 return sizeof(struct pipe_sampler_state);
00123 case CSO_DEPTH_STENCIL_ALPHA:
00124 return sizeof(struct pipe_depth_stencil_alpha_state);
00125 case CSO_RASTERIZER:
00126 return sizeof(struct pipe_rasterizer_state);
00127 case CSO_FRAGMENT_SHADER:
00128 return sizeof(struct pipe_shader_state);
00129 case CSO_VERTEX_SHADER:
00130 return sizeof(struct pipe_shader_state);
00131 }
00132 return 0;
00133 }
00134
00135
00136 static void delete_blend_state(void *state, void *data)
00137 {
00138 struct cso_blend *cso = (struct cso_blend *)state;
00139 if (cso->delete_state)
00140 cso->delete_state(cso->context, cso->data);
00141 FREE(state);
00142 }
00143
00144 static void delete_depth_stencil_state(void *state, void *data)
00145 {
00146 struct cso_depth_stencil_alpha *cso = (struct cso_depth_stencil_alpha *)state;
00147 if (cso->delete_state)
00148 cso->delete_state(cso->context, cso->data);
00149 FREE(state);
00150 }
00151
00152 static void delete_sampler_state(void *state, void *data)
00153 {
00154 struct cso_sampler *cso = (struct cso_sampler *)state;
00155 if (cso->delete_state)
00156 cso->delete_state(cso->context, cso->data);
00157 FREE(state);
00158 }
00159
00160 static void delete_rasterizer_state(void *state, void *data)
00161 {
00162 struct cso_rasterizer *cso = (struct cso_rasterizer *)state;
00163 if (cso->delete_state)
00164 cso->delete_state(cso->context, cso->data);
00165 FREE(state);
00166 }
00167
00168 static void delete_fs_state(void *state, void *data)
00169 {
00170 struct cso_fragment_shader *cso = (struct cso_fragment_shader *)state;
00171 if (cso->delete_state)
00172 cso->delete_state(cso->context, cso->data);
00173 FREE(state);
00174 }
00175
00176 static void delete_vs_state(void *state, void *data)
00177 {
00178 struct cso_vertex_shader *cso = (struct cso_vertex_shader *)state;
00179 if (cso->delete_state)
00180 cso->delete_state(cso->context, cso->data);
00181 FREE(state);
00182 }
00183
00184
00185 static INLINE void delete_cso(void *state, enum cso_cache_type type)
00186 {
00187 switch (type) {
00188 case CSO_BLEND:
00189 delete_blend_state(state, 0);
00190 break;
00191 case CSO_SAMPLER:
00192 delete_sampler_state(state, 0);
00193 break;
00194 case CSO_DEPTH_STENCIL_ALPHA:
00195 delete_depth_stencil_state(state, 0);
00196 break;
00197 case CSO_RASTERIZER:
00198 delete_rasterizer_state(state, 0);
00199 break;
00200 case CSO_FRAGMENT_SHADER:
00201 delete_fs_state(state, 0);
00202 break;
00203 case CSO_VERTEX_SHADER:
00204 delete_vs_state(state, 0);
00205 break;
00206 default:
00207 assert(0);
00208 FREE(state);
00209 }
00210 }
00211
00212
00213 static INLINE void sanitize_hash(struct cso_cache *sc,
00214 struct cso_hash *hash,
00215 enum cso_cache_type type,
00216 int max_size)
00217 {
00218 if (sc->sanitize_cb)
00219 sc->sanitize_cb(hash, type, max_size, sc->sanitize_data);
00220 }
00221
00222
00223 static INLINE void sanitize_cb(struct cso_hash *hash, enum cso_cache_type type,
00224 int max_size, void *user_data)
00225 {
00226
00227
00228 int hash_size = cso_hash_size(hash);
00229 int max_entries = (max_size > hash_size) ? max_size : hash_size;
00230 int to_remove = (max_size < max_entries) * max_entries/4;
00231 if (hash_size > max_size)
00232 to_remove += hash_size - max_size;
00233 while (to_remove) {
00234
00235
00236 struct cso_hash_iter iter = cso_hash_first_node(hash);
00237 void *cso = cso_hash_take(hash, cso_hash_iter_key(iter));
00238 delete_cso(cso, type);
00239 --to_remove;
00240 }
00241 }
00242
00243 struct cso_hash_iter
00244 cso_insert_state(struct cso_cache *sc,
00245 unsigned hash_key, enum cso_cache_type type,
00246 void *state)
00247 {
00248 struct cso_hash *hash = _cso_hash_for_type(sc, type);
00249 sanitize_hash(sc, hash, type, sc->max_size);
00250
00251 return cso_hash_insert(hash, hash_key, state);
00252 }
00253
00254 struct cso_hash_iter
00255 cso_find_state(struct cso_cache *sc,
00256 unsigned hash_key, enum cso_cache_type type)
00257 {
00258 struct cso_hash *hash = _cso_hash_for_type(sc, type);
00259
00260 return cso_hash_find(hash, hash_key);
00261 }
00262
00263
00264 void *cso_hash_find_data_from_template( struct cso_hash *hash,
00265 unsigned hash_key,
00266 void *templ,
00267 int size )
00268 {
00269 struct cso_hash_iter iter = cso_hash_find(hash, hash_key);
00270 while (!cso_hash_iter_is_null(iter)) {
00271 void *iter_data = cso_hash_iter_data(iter);
00272 if (!memcmp(iter_data, templ, size)) {
00273
00274
00275 return iter_data;
00276 }
00277 iter = cso_hash_iter_next(iter);
00278 }
00279 return NULL;
00280 }
00281
00282
00283 struct cso_hash_iter cso_find_state_template(struct cso_cache *sc,
00284 unsigned hash_key, enum cso_cache_type type,
00285 void *templ)
00286 {
00287 struct cso_hash_iter iter = cso_find_state(sc, hash_key, type);
00288 int size = _cso_size_for_type(type);
00289 while (!cso_hash_iter_is_null(iter)) {
00290 void *iter_data = cso_hash_iter_data(iter);
00291 if (!memcmp(iter_data, templ, size))
00292 return iter;
00293 iter = cso_hash_iter_next(iter);
00294 }
00295 return iter;
00296 }
00297
00298 void * cso_take_state(struct cso_cache *sc,
00299 unsigned hash_key, enum cso_cache_type type)
00300 {
00301 struct cso_hash *hash = _cso_hash_for_type(sc, type);
00302 return cso_hash_take(hash, hash_key);
00303 }
00304
00305 struct cso_cache *cso_cache_create(void)
00306 {
00307 struct cso_cache *sc = MALLOC_STRUCT(cso_cache);
00308 if (sc == NULL)
00309 return NULL;
00310
00311 sc->max_size = 4096;
00312 sc->blend_hash = cso_hash_create();
00313 sc->sampler_hash = cso_hash_create();
00314 sc->depth_stencil_hash = cso_hash_create();
00315 sc->rasterizer_hash = cso_hash_create();
00316 sc->fs_hash = cso_hash_create();
00317 sc->vs_hash = cso_hash_create();
00318 sc->sanitize_cb = sanitize_cb;
00319 sc->sanitize_data = 0;
00320
00321 return sc;
00322 }
00323
00324 void cso_for_each_state(struct cso_cache *sc, enum cso_cache_type type,
00325 cso_state_callback func, void *user_data)
00326 {
00327 struct cso_hash *hash = 0;
00328 struct cso_hash_iter iter;
00329
00330 switch (type) {
00331 case CSO_BLEND:
00332 hash = sc->blend_hash;
00333 break;
00334 case CSO_SAMPLER:
00335 hash = sc->sampler_hash;
00336 break;
00337 case CSO_DEPTH_STENCIL_ALPHA:
00338 hash = sc->depth_stencil_hash;
00339 break;
00340 case CSO_RASTERIZER:
00341 hash = sc->rasterizer_hash;
00342 break;
00343 case CSO_FRAGMENT_SHADER:
00344 hash = sc->fs_hash;
00345 break;
00346 case CSO_VERTEX_SHADER:
00347 hash = sc->vs_hash;
00348 break;
00349 }
00350
00351 iter = cso_hash_first_node(hash);
00352 while (!cso_hash_iter_is_null(iter)) {
00353 void *state = cso_hash_iter_data(iter);
00354 iter = cso_hash_iter_next(iter);
00355 if (state) {
00356 func(state, user_data);
00357 }
00358 }
00359 }
00360
00361 void cso_cache_delete(struct cso_cache *sc)
00362 {
00363 assert(sc);
00364
00365 cso_for_each_state(sc, CSO_BLEND, delete_blend_state, 0);
00366 cso_for_each_state(sc, CSO_DEPTH_STENCIL_ALPHA, delete_depth_stencil_state, 0);
00367 cso_for_each_state(sc, CSO_FRAGMENT_SHADER, delete_fs_state, 0);
00368 cso_for_each_state(sc, CSO_VERTEX_SHADER, delete_vs_state, 0);
00369 cso_for_each_state(sc, CSO_RASTERIZER, delete_rasterizer_state, 0);
00370 cso_for_each_state(sc, CSO_SAMPLER, delete_sampler_state, 0);
00371
00372 cso_hash_delete(sc->blend_hash);
00373 cso_hash_delete(sc->sampler_hash);
00374 cso_hash_delete(sc->depth_stencil_hash);
00375 cso_hash_delete(sc->rasterizer_hash);
00376 cso_hash_delete(sc->fs_hash);
00377 cso_hash_delete(sc->vs_hash);
00378 FREE(sc);
00379 }
00380
00381 void cso_set_maximum_cache_size(struct cso_cache *sc, int number)
00382 {
00383 sc->max_size = number;
00384
00385 sanitize_hash(sc, sc->blend_hash, CSO_BLEND, sc->max_size);
00386 sanitize_hash(sc, sc->depth_stencil_hash, CSO_DEPTH_STENCIL_ALPHA,
00387 sc->max_size);
00388 sanitize_hash(sc, sc->fs_hash, CSO_FRAGMENT_SHADER, sc->max_size);
00389 sanitize_hash(sc, sc->vs_hash, CSO_VERTEX_SHADER, sc->max_size);
00390 sanitize_hash(sc, sc->rasterizer_hash, CSO_RASTERIZER, sc->max_size);
00391 sanitize_hash(sc, sc->sampler_hash, CSO_SAMPLER, sc->max_size);
00392 }
00393
00394 int cso_maximum_cache_size(const struct cso_cache *sc)
00395 {
00396 return sc->max_size;
00397 }
00398
00399 void cso_cache_set_sanitize_callback(struct cso_cache *sc,
00400 cso_sanitize_callback cb,
00401 void *user_data)
00402 {
00403 sc->sanitize_cb = cb;
00404 sc->sanitize_data = user_data;
00405 }
00406