try to fix the deleting of the bound cso during cleanup of the hash
authorZack Rusin <zack@tungstengraphics.com>
Wed, 30 Apr 2008 06:04:28 +0000 (02:04 -0400)
committerZack Rusin <zack@tungstengraphics.com>
Wed, 30 Apr 2008 19:04:58 +0000 (15:04 -0400)
src/gallium/auxiliary/cso_cache/cso_cache.c
src/gallium/auxiliary/cso_cache/cso_cache.h
src/gallium/auxiliary/cso_cache/cso_context.c

index 096875807bed8384ee185fa831a659f794b6b3f4..36dc46ff8090019c9f9d52cff3fb2a53232b9841 100644 (file)
@@ -43,6 +43,9 @@ struct cso_cache {
    struct cso_hash *rasterizer_hash;
    struct cso_hash *sampler_hash;
    int    max_size;
+
+   cso_sanitize_callback sanitize_cb;
+   void                 *sanitize_data;
 };
 
 #if 1
@@ -205,8 +208,19 @@ static INLINE void delete_cso(void *state, enum cso_cache_type type)
    }
 }
 
-static INLINE void sanitize_hash(struct cso_hash *hash, enum cso_cache_type type,
+
+static INLINE void sanitize_hash(struct cso_cache *sc,
+                                 struct cso_hash *hash,
+                                 enum cso_cache_type type,
                                  int max_size)
+{
+   if (sc->sanitize_cb)
+      sc->sanitize_cb(hash, type, max_size, sc->sanitize_data);
+}
+
+
+static INLINE void sanitize_cb(struct cso_hash *hash, enum cso_cache_type type,
+                               int max_size, void *user_data)
 {
    /* if we're approach the maximum size, remove fourth of the entries
     * otherwise every subsequent call will go through the same */
@@ -231,7 +245,7 @@ cso_insert_state(struct cso_cache *sc,
                  void *state)
 {
    struct cso_hash *hash = _cso_hash_for_type(sc, type);
-   sanitize_hash(hash, type, sc->max_size);
+   sanitize_hash(sc, hash, type, sc->max_size);
 
    return cso_hash_insert(hash, hash_key, state);
 }
@@ -300,6 +314,8 @@ struct cso_cache *cso_cache_create(void)
    sc->rasterizer_hash    = cso_hash_create();
    sc->fs_hash            = cso_hash_create();
    sc->vs_hash            = cso_hash_create();
+   sc->sanitize_cb        = sanitize_cb;
+   sc->sanitize_data      = 0;
 
    return sc;
 }
@@ -365,13 +381,13 @@ void cso_set_maximum_cache_size(struct cso_cache *sc, int number)
 {
    sc->max_size = number;
 
-   sanitize_hash(sc->blend_hash, CSO_BLEND, sc->max_size);
-   sanitize_hash(sc->depth_stencil_hash, CSO_DEPTH_STENCIL_ALPHA,
+   sanitize_hash(sc, sc->blend_hash, CSO_BLEND, sc->max_size);
+   sanitize_hash(sc, sc->depth_stencil_hash, CSO_DEPTH_STENCIL_ALPHA,
                  sc->max_size);
-   sanitize_hash(sc->fs_hash, CSO_FRAGMENT_SHADER, sc->max_size);
-   sanitize_hash(sc->vs_hash, CSO_VERTEX_SHADER, sc->max_size);
-   sanitize_hash(sc->rasterizer_hash, CSO_RASTERIZER, sc->max_size);
-   sanitize_hash(sc->sampler_hash, CSO_SAMPLER, sc->max_size);
+   sanitize_hash(sc, sc->fs_hash, CSO_FRAGMENT_SHADER, sc->max_size);
+   sanitize_hash(sc, sc->vs_hash, CSO_VERTEX_SHADER, sc->max_size);
+   sanitize_hash(sc, sc->rasterizer_hash, CSO_RASTERIZER, sc->max_size);
+   sanitize_hash(sc, sc->sampler_hash, CSO_SAMPLER, sc->max_size);
 }
 
 int cso_maximum_cache_size(const struct cso_cache *sc)
@@ -379,3 +395,11 @@ int cso_maximum_cache_size(const struct cso_cache *sc)
    return sc->max_size;
 }
 
+void cso_cache_set_sanitize_callback(struct cso_cache *sc,
+                                     cso_sanitize_callback cb,
+                                     void *user_data)
+{
+   sc->sanitize_cb   = cb;
+   sc->sanitize_data = user_data;
+}
+
index e5edbbb5566a3371fdfe51f25baef36b8607e45b..6b5c230e8f22a15bdaebb2514f8b8baa4676d95e 100644 (file)
 extern "C" {
 #endif
 
+enum cso_cache_type {
+   CSO_BLEND,
+   CSO_SAMPLER,
+   CSO_DEPTH_STENCIL_ALPHA,
+   CSO_RASTERIZER,
+   CSO_FRAGMENT_SHADER,
+   CSO_VERTEX_SHADER
+};
+
 typedef void (*cso_state_callback)(void *ctx, void *obj);
 
+typedef void (*cso_sanitize_callback)(struct cso_hash *hash,
+                                      enum cso_cache_type type,
+                                      int max_size,
+                                      void *user_data);
+
 struct cso_cache;
 
 struct cso_blend {
@@ -130,21 +144,15 @@ struct cso_sampler {
    struct pipe_context *context;
 };
 
-
-enum cso_cache_type {
-   CSO_BLEND,
-   CSO_SAMPLER,
-   CSO_DEPTH_STENCIL_ALPHA,
-   CSO_RASTERIZER,
-   CSO_FRAGMENT_SHADER,
-   CSO_VERTEX_SHADER
-};
-
 unsigned cso_construct_key(void *item, int item_size);
 
 struct cso_cache *cso_cache_create(void);
 void cso_cache_delete(struct cso_cache *sc);
 
+void cso_cache_set_sanitize_callback(struct cso_cache *sc,
+                                     cso_sanitize_callback cb,
+                                     void *user_data);
+
 struct cso_hash_iter cso_insert_state(struct cso_cache *sc,
                                       unsigned hash_key, enum cso_cache_type type,
                                       void *state);
index b4609e999bbaf7aa31ff7e881c53a13f1d796084..eef898f4865d6779cc10881be7081a35dbfc8456 100644 (file)
@@ -80,6 +80,131 @@ struct cso_context {
 };
 
 
+static boolean delete_blend_state(struct cso_context *ctx, void *state)
+{
+   struct cso_blend *cso = (struct cso_blend *)state;
+
+   if (ctx->blend == state)
+      return FALSE;
+
+   if (cso->delete_state)
+      cso->delete_state(cso->context, cso->data);
+   FREE(state);
+   return TRUE;
+}
+
+static boolean delete_depth_stencil_state(struct cso_context *ctx, void *state)
+{
+   struct cso_depth_stencil_alpha *cso = (struct cso_depth_stencil_alpha *)state;
+
+   if (ctx->depth_stencil == cso->data)
+      return FALSE;
+
+   if (cso->delete_state)
+      cso->delete_state(cso->context, cso->data);
+   FREE(state);
+
+   return TRUE;
+}
+
+static boolean delete_sampler_state(struct cso_context *ctx, void *state)
+{
+   struct cso_sampler *cso = (struct cso_sampler *)state;
+   if (cso->delete_state)
+      cso->delete_state(cso->context, cso->data);
+   FREE(state);
+   return TRUE;
+}
+
+static boolean delete_rasterizer_state(struct cso_context *ctx, void *state)
+{
+   struct cso_rasterizer *cso = (struct cso_rasterizer *)state;
+
+   if (ctx->rasterizer == cso->data)
+      return FALSE;
+   if (cso->delete_state)
+      cso->delete_state(cso->context, cso->data);
+   FREE(state);
+   return TRUE;
+}
+
+static boolean delete_fs_state(struct cso_context *ctx, void *state)
+{
+   struct cso_fragment_shader *cso = (struct cso_fragment_shader *)state;
+   if (ctx->fragment_shader == cso->data)
+      return FALSE;
+   if (cso->delete_state)
+      cso->delete_state(cso->context, cso->data);
+   FREE(state);
+   return TRUE;
+}
+
+static boolean delete_vs_state(struct cso_context *ctx, void *state)
+{
+   struct cso_vertex_shader *cso = (struct cso_vertex_shader *)state;
+   if (ctx->vertex_shader == cso->data)
+      return TRUE;
+   if (cso->delete_state)
+      cso->delete_state(cso->context, cso->data);
+   FREE(state);
+   return FALSE;
+}
+
+
+static INLINE boolean delete_cso(struct cso_context *ctx,
+                                 void *state, enum cso_cache_type type)
+{
+   switch (type) {
+   case CSO_BLEND:
+      return delete_blend_state(ctx, state);
+      break;
+   case CSO_SAMPLER:
+      return delete_sampler_state(ctx, state);
+      break;
+   case CSO_DEPTH_STENCIL_ALPHA:
+      return delete_depth_stencil_state(ctx, state);
+      break;
+   case CSO_RASTERIZER:
+      return delete_rasterizer_state(ctx, state);
+      break;
+   case CSO_FRAGMENT_SHADER:
+      return delete_fs_state(ctx, state);
+      break;
+   case CSO_VERTEX_SHADER:
+      return delete_vs_state(ctx, state);
+      break;
+   default:
+      assert(0);
+      FREE(state);
+   }
+   return FALSE;
+}
+
+static INLINE void sanitize_hash(struct cso_hash *hash, enum cso_cache_type type,
+                                 int max_size, void *user_data)
+{
+   struct cso_context *ctx = (struct cso_context *)user_data;
+   /* if we're approach the maximum size, remove fourth of the entries
+    * otherwise every subsequent call will go through the same */
+   int hash_size = cso_hash_size(hash);
+   int max_entries = (max_size > hash_size) ? max_size : hash_size;
+   int to_remove =  (max_size < max_entries) * max_entries/4;
+   struct cso_hash_iter iter = cso_hash_first_node(hash);
+   if (hash_size > max_size)
+      to_remove += hash_size - max_size;
+   while (to_remove) {
+      /*remove elements until we're good */
+      /*fixme: currently we pick the nodes to remove at random*/
+      void *cso = cso_hash_iter_data(iter);
+      if (delete_cso(ctx, cso, type)) {
+         iter = cso_hash_erase(hash, iter);
+         --to_remove;
+      } else
+         iter = cso_hash_iter_next(iter);
+   }
+}
+
+
 struct cso_context *cso_create_context( struct pipe_context *pipe )
 {
    struct cso_context *ctx = CALLOC_STRUCT(cso_context);
@@ -89,6 +214,9 @@ struct cso_context *cso_create_context( struct pipe_context *pipe )
    ctx->cache = cso_cache_create();
    if (ctx->cache == NULL)
       goto out;
+   cso_cache_set_sanitize_callback(ctx->cache,
+                                   sanitize_hash,
+                                   ctx);
 
    ctx->pipe = pipe;