Path: blob/21.2-virgl/src/gallium/auxiliary/cso_cache/cso_cache.c
4565 views
/**************************************************************************1*2* Copyright 2007 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/2627/* Authors: Zack Rusin <[email protected]>28*/2930#include "util/u_debug.h"3132#include "util/u_memory.h"3334#include "cso_cache.h"35#include "cso_hash.h"363738static inline struct cso_hash *_cso_hash_for_type(struct cso_cache *sc, enum cso_cache_type type)39{40return &sc->hashes[type];41}4243/* Default delete callback. It can also be used by custom callbacks. */44void cso_delete_state(struct pipe_context *pipe, void *state,45enum cso_cache_type type)46{47switch (type) {48case CSO_BLEND:49pipe->delete_blend_state(pipe, ((struct cso_blend*)state)->data);50break;51case CSO_SAMPLER:52pipe->delete_sampler_state(pipe, ((struct cso_sampler*)state)->data);53break;54case CSO_DEPTH_STENCIL_ALPHA:55pipe->delete_depth_stencil_alpha_state(pipe,56((struct cso_depth_stencil_alpha*)state)->data);57break;58case CSO_RASTERIZER:59pipe->delete_rasterizer_state(pipe, ((struct cso_rasterizer*)state)->data);60break;61case CSO_VELEMENTS:62pipe->delete_vertex_elements_state(pipe, ((struct cso_velements*)state)->data);63break;64default:65assert(0);66}6768FREE(state);69}707172static inline void sanitize_hash(struct cso_cache *sc,73struct cso_hash *hash,74enum cso_cache_type type,75int max_size)76{77if (sc->sanitize_cb)78sc->sanitize_cb(hash, type, max_size, sc->sanitize_data);79}808182static inline void sanitize_cb(struct cso_hash *hash, enum cso_cache_type type,83int max_size, void *user_data)84{85struct cso_cache *cache = (struct cso_cache *)user_data;8687/* if we're approach the maximum size, remove fourth of the entries88* otherwise every subsequent call will go through the same */89int hash_size = cso_hash_size(hash);90int max_entries = (max_size > hash_size) ? max_size : hash_size;91int to_remove = (max_size < max_entries) * max_entries/4;92if (hash_size > max_size)93to_remove += hash_size - max_size;94while (to_remove) {95/*remove elements until we're good */96/*fixme: currently we pick the nodes to remove at random*/97struct cso_hash_iter iter = cso_hash_first_node(hash);98void *cso = cso_hash_take(hash, cso_hash_iter_key(iter));99cache->delete_cso(cache->delete_cso_ctx, cso, type);100--to_remove;101}102}103104struct cso_hash_iter105cso_insert_state(struct cso_cache *sc,106unsigned hash_key, enum cso_cache_type type,107void *state)108{109struct cso_hash *hash = _cso_hash_for_type(sc, type);110sanitize_hash(sc, hash, type, sc->max_size);111112return cso_hash_insert(hash, hash_key, state);113}114115struct cso_hash_iter116cso_find_state(struct cso_cache *sc,117unsigned hash_key, enum cso_cache_type type)118{119struct cso_hash *hash = _cso_hash_for_type(sc, type);120121return cso_hash_find(hash, hash_key);122}123124125void *cso_hash_find_data_from_template( struct cso_hash *hash,126unsigned hash_key,127void *templ,128int size )129{130struct cso_hash_iter iter = cso_hash_find(hash, hash_key);131while (!cso_hash_iter_is_null(iter)) {132void *iter_data = cso_hash_iter_data(iter);133if (!memcmp(iter_data, templ, size)) {134/* We found a match135*/136return iter_data;137}138iter = cso_hash_iter_next(iter);139}140return NULL;141}142143144struct cso_hash_iter cso_find_state_template(struct cso_cache *sc,145unsigned hash_key, enum cso_cache_type type,146void *templ, unsigned size)147{148struct cso_hash_iter iter = cso_find_state(sc, hash_key, type);149while (!cso_hash_iter_is_null(iter)) {150void *iter_data = cso_hash_iter_data(iter);151if (!memcmp(iter_data, templ, size))152return iter;153iter = cso_hash_iter_next(iter);154}155return iter;156}157158void cso_cache_init(struct cso_cache *sc, struct pipe_context *pipe)159{160memset(sc, 0, sizeof(*sc));161162sc->max_size = 4096;163for (int i = 0; i < CSO_CACHE_MAX; i++)164cso_hash_init(&sc->hashes[i]);165166sc->sanitize_cb = sanitize_cb;167sc->sanitize_data = sc;168sc->delete_cso = (cso_delete_cso_callback)cso_delete_state;169sc->delete_cso_ctx = pipe;170}171172static void cso_delete_all(struct cso_cache *sc, enum cso_cache_type type)173{174struct cso_hash *hash = _cso_hash_for_type(sc, type);175struct cso_hash_iter iter;176177iter = cso_hash_first_node(hash);178while (!cso_hash_iter_is_null(iter)) {179void *state = cso_hash_iter_data(iter);180iter = cso_hash_iter_next(iter);181if (state) {182sc->delete_cso(sc->delete_cso_ctx, state, type);183}184}185}186187void cso_cache_delete(struct cso_cache *sc)188{189int i;190191/* delete driver data */192cso_delete_all(sc, CSO_BLEND);193cso_delete_all(sc, CSO_DEPTH_STENCIL_ALPHA);194cso_delete_all(sc, CSO_RASTERIZER);195cso_delete_all(sc, CSO_SAMPLER);196cso_delete_all(sc, CSO_VELEMENTS);197198for (i = 0; i < CSO_CACHE_MAX; i++)199cso_hash_deinit(&sc->hashes[i]);200}201202void cso_set_maximum_cache_size(struct cso_cache *sc, int number)203{204int i;205206sc->max_size = number;207208for (i = 0; i < CSO_CACHE_MAX; i++)209sanitize_hash(sc, &sc->hashes[i], i, sc->max_size);210}211212void cso_cache_set_sanitize_callback(struct cso_cache *sc,213cso_sanitize_callback cb,214void *user_data)215{216sc->sanitize_cb = cb;217sc->sanitize_data = user_data;218}219220void cso_cache_set_delete_cso_callback(struct cso_cache *sc,221cso_delete_cso_callback delete_cso,222void *ctx)223{224sc->delete_cso = delete_cso;225sc->delete_cso_ctx = ctx;226}227228229