cso_cache.c revision 6c597238b2e168b63738ac8cc9167c1d09185aad
19780327c5d95586a88fce94d7b47342355ead118Zack Rusin/**************************************************************************
29780327c5d95586a88fce94d7b47342355ead118Zack Rusin *
39780327c5d95586a88fce94d7b47342355ead118Zack Rusin * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
49780327c5d95586a88fce94d7b47342355ead118Zack Rusin * All Rights Reserved.
59780327c5d95586a88fce94d7b47342355ead118Zack Rusin *
69780327c5d95586a88fce94d7b47342355ead118Zack Rusin * Permission is hereby granted, free of charge, to any person obtaining a
79780327c5d95586a88fce94d7b47342355ead118Zack Rusin * copy of this software and associated documentation files (the
89780327c5d95586a88fce94d7b47342355ead118Zack Rusin * "Software"), to deal in the Software without restriction, including
99780327c5d95586a88fce94d7b47342355ead118Zack Rusin * without limitation the rights to use, copy, modify, merge, publish,
109780327c5d95586a88fce94d7b47342355ead118Zack Rusin * distribute, sub license, and/or sell copies of the Software, and to
119780327c5d95586a88fce94d7b47342355ead118Zack Rusin * permit persons to whom the Software is furnished to do so, subject to
129780327c5d95586a88fce94d7b47342355ead118Zack Rusin * the following conditions:
139780327c5d95586a88fce94d7b47342355ead118Zack Rusin *
149780327c5d95586a88fce94d7b47342355ead118Zack Rusin * The above copyright notice and this permission notice (including the
159780327c5d95586a88fce94d7b47342355ead118Zack Rusin * next paragraph) shall be included in all copies or substantial portions
169780327c5d95586a88fce94d7b47342355ead118Zack Rusin * of the Software.
179780327c5d95586a88fce94d7b47342355ead118Zack Rusin *
189780327c5d95586a88fce94d7b47342355ead118Zack Rusin * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
199780327c5d95586a88fce94d7b47342355ead118Zack Rusin * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
209780327c5d95586a88fce94d7b47342355ead118Zack Rusin * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
219780327c5d95586a88fce94d7b47342355ead118Zack Rusin * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
229780327c5d95586a88fce94d7b47342355ead118Zack Rusin * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
239780327c5d95586a88fce94d7b47342355ead118Zack Rusin * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
249780327c5d95586a88fce94d7b47342355ead118Zack Rusin * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
259780327c5d95586a88fce94d7b47342355ead118Zack Rusin *
269780327c5d95586a88fce94d7b47342355ead118Zack Rusin **************************************************************************/
279780327c5d95586a88fce94d7b47342355ead118Zack Rusin
289780327c5d95586a88fce94d7b47342355ead118Zack Rusin/* Authors:  Zack Rusin <zack@tungstengraphics.com>
299780327c5d95586a88fce94d7b47342355ead118Zack Rusin */
309780327c5d95586a88fce94d7b47342355ead118Zack Rusin
319780327c5d95586a88fce94d7b47342355ead118Zack Rusin#include "cso_cache.h"
32e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin#include "cso_hash.h"
339780327c5d95586a88fce94d7b47342355ead118Zack Rusin
349780327c5d95586a88fce94d7b47342355ead118Zack Rusin#if 1
35e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusinstatic unsigned hash_key(const void *key, unsigned key_size)
369780327c5d95586a88fce94d7b47342355ead118Zack Rusin{
379780327c5d95586a88fce94d7b47342355ead118Zack Rusin   unsigned *ikey = (unsigned *)key;
389780327c5d95586a88fce94d7b47342355ead118Zack Rusin   unsigned hash = 0, i;
399780327c5d95586a88fce94d7b47342355ead118Zack Rusin
409780327c5d95586a88fce94d7b47342355ead118Zack Rusin   assert(key_size % 4 == 0);
419780327c5d95586a88fce94d7b47342355ead118Zack Rusin
429780327c5d95586a88fce94d7b47342355ead118Zack Rusin   /* I'm sure this can be improved on:
439780327c5d95586a88fce94d7b47342355ead118Zack Rusin    */
449780327c5d95586a88fce94d7b47342355ead118Zack Rusin   for (i = 0; i < key_size/4; i++)
459780327c5d95586a88fce94d7b47342355ead118Zack Rusin      hash ^= ikey[i];
469780327c5d95586a88fce94d7b47342355ead118Zack Rusin
479780327c5d95586a88fce94d7b47342355ead118Zack Rusin   return hash;
489780327c5d95586a88fce94d7b47342355ead118Zack Rusin}
499780327c5d95586a88fce94d7b47342355ead118Zack Rusin#else
509780327c5d95586a88fce94d7b47342355ead118Zack Rusinstatic unsigned hash_key(const unsigned char *p, int n)
519780327c5d95586a88fce94d7b47342355ead118Zack Rusin{
529780327c5d95586a88fce94d7b47342355ead118Zack Rusin   unsigned h = 0;
539780327c5d95586a88fce94d7b47342355ead118Zack Rusin   unsigned g;
549780327c5d95586a88fce94d7b47342355ead118Zack Rusin
559780327c5d95586a88fce94d7b47342355ead118Zack Rusin   while (n--) {
569780327c5d95586a88fce94d7b47342355ead118Zack Rusin      h = (h << 4) + *p++;
579780327c5d95586a88fce94d7b47342355ead118Zack Rusin      if ((g = (h & 0xf0000000)) != 0)
589780327c5d95586a88fce94d7b47342355ead118Zack Rusin         h ^= g >> 23;
599780327c5d95586a88fce94d7b47342355ead118Zack Rusin      h &= ~g;
609780327c5d95586a88fce94d7b47342355ead118Zack Rusin   }
619780327c5d95586a88fce94d7b47342355ead118Zack Rusin   return h;
629780327c5d95586a88fce94d7b47342355ead118Zack Rusin}
639780327c5d95586a88fce94d7b47342355ead118Zack Rusin#endif
649780327c5d95586a88fce94d7b47342355ead118Zack Rusin
659780327c5d95586a88fce94d7b47342355ead118Zack Rusinunsigned cso_construct_key(void *item, int item_size)
669780327c5d95586a88fce94d7b47342355ead118Zack Rusin{
67e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin   return hash_key((item), item_size);
689780327c5d95586a88fce94d7b47342355ead118Zack Rusin}
699780327c5d95586a88fce94d7b47342355ead118Zack Rusin
70e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusinstatic struct cso_hash *_cso_hash_for_type(struct cso_cache *sc, enum cso_cache_type type)
71e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin{
72e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin   struct cso_hash *hash = 0;
73e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin
74e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin   switch(type) {
75e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin   case CSO_BLEND:
76e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin      hash = sc->blend_hash;
77a0e948f3aaadf56ab206a6b3e597825f2085f6d1Zack Rusin      break;
78f117327a3f246713abfd4dc4320d4a1a7f1b811aZack Rusin   case CSO_SAMPLER:
79f117327a3f246713abfd4dc4320d4a1a7f1b811aZack Rusin      hash = sc->sampler_hash;
80a0e948f3aaadf56ab206a6b3e597825f2085f6d1Zack Rusin      break;
81bfe79babf99e6b9435195178d1ea64687c60d161Keith Whitwell   case CSO_DEPTH_STENCIL_ALPHA:
82d6ac959833a8e40a27907940969c622692f749b1Zack Rusin      hash = sc->depth_stencil_hash;
83a0e948f3aaadf56ab206a6b3e597825f2085f6d1Zack Rusin      break;
84294401814d1d89cc731de1c22c25333aa5d59374Zack Rusin   case CSO_RASTERIZER:
85294401814d1d89cc731de1c22c25333aa5d59374Zack Rusin      hash = sc->rasterizer_hash;
86a0e948f3aaadf56ab206a6b3e597825f2085f6d1Zack Rusin      break;
87f22e920f478d8732695913ec0d1f7244b451a8f5Zack Rusin   case CSO_FRAGMENT_SHADER:
88f22e920f478d8732695913ec0d1f7244b451a8f5Zack Rusin      hash = sc->fs_hash;
89a0e948f3aaadf56ab206a6b3e597825f2085f6d1Zack Rusin      break;
90f22e920f478d8732695913ec0d1f7244b451a8f5Zack Rusin   case CSO_VERTEX_SHADER:
91f22e920f478d8732695913ec0d1f7244b451a8f5Zack Rusin      hash = sc->vs_hash;
92a0e948f3aaadf56ab206a6b3e597825f2085f6d1Zack Rusin      break;
93e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin   }
94e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin
95e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin   return hash;
96e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin}
97e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin
98e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusinstatic int _cso_size_for_type(enum cso_cache_type type)
99e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin{
100e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin   switch(type) {
101e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin   case CSO_BLEND:
102e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin      return sizeof(struct pipe_blend_state);
103f117327a3f246713abfd4dc4320d4a1a7f1b811aZack Rusin   case CSO_SAMPLER:
104f117327a3f246713abfd4dc4320d4a1a7f1b811aZack Rusin      return sizeof(struct pipe_sampler_state);
105bfe79babf99e6b9435195178d1ea64687c60d161Keith Whitwell   case CSO_DEPTH_STENCIL_ALPHA:
106bfe79babf99e6b9435195178d1ea64687c60d161Keith Whitwell      return sizeof(struct pipe_depth_stencil_alpha_state);
107294401814d1d89cc731de1c22c25333aa5d59374Zack Rusin   case CSO_RASTERIZER:
108294401814d1d89cc731de1c22c25333aa5d59374Zack Rusin      return sizeof(struct pipe_rasterizer_state);
109f22e920f478d8732695913ec0d1f7244b451a8f5Zack Rusin   case CSO_FRAGMENT_SHADER:
110f22e920f478d8732695913ec0d1f7244b451a8f5Zack Rusin      return sizeof(struct pipe_shader_state);
111f22e920f478d8732695913ec0d1f7244b451a8f5Zack Rusin   case CSO_VERTEX_SHADER:
112ccd63b54cfbb6bb241d55f7ac95afcd14819f469Zack Rusin      return sizeof(struct pipe_shader_state);
113e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin   }
114e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin   return 0;
115e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin}
116e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin
117e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusinstruct cso_hash_iter
1189780327c5d95586a88fce94d7b47342355ead118Zack Rusincso_insert_state(struct cso_cache *sc,
119e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin                 unsigned hash_key, enum cso_cache_type type,
120e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin                 void *state)
1219780327c5d95586a88fce94d7b47342355ead118Zack Rusin{
122e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin   struct cso_hash *hash = _cso_hash_for_type(sc, type);
123e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin   return cso_hash_insert(hash, hash_key, state);
1249780327c5d95586a88fce94d7b47342355ead118Zack Rusin}
1259780327c5d95586a88fce94d7b47342355ead118Zack Rusin
126e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusinstruct cso_hash_iter
1279780327c5d95586a88fce94d7b47342355ead118Zack Rusincso_find_state(struct cso_cache *sc,
128e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin               unsigned hash_key, enum cso_cache_type type)
1299780327c5d95586a88fce94d7b47342355ead118Zack Rusin{
130e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin   struct cso_hash *hash = _cso_hash_for_type(sc, type);
1319780327c5d95586a88fce94d7b47342355ead118Zack Rusin
132e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin   return cso_hash_find(hash, hash_key);
1339780327c5d95586a88fce94d7b47342355ead118Zack Rusin}
1349780327c5d95586a88fce94d7b47342355ead118Zack Rusin
1356c597238b2e168b63738ac8cc9167c1d09185aadJosé Fonseca
1366c597238b2e168b63738ac8cc9167c1d09185aadJosé Fonsecavoid *cso_hash_find_data_from_template( struct cso_hash *hash,
1376c597238b2e168b63738ac8cc9167c1d09185aadJosé Fonseca				        unsigned hash_key,
1386c597238b2e168b63738ac8cc9167c1d09185aadJosé Fonseca				        void *templ,
1396c597238b2e168b63738ac8cc9167c1d09185aadJosé Fonseca				        int size )
1406c597238b2e168b63738ac8cc9167c1d09185aadJosé Fonseca{
1416c597238b2e168b63738ac8cc9167c1d09185aadJosé Fonseca   struct cso_hash_iter iter = cso_hash_find(hash, hash_key);
1426c597238b2e168b63738ac8cc9167c1d09185aadJosé Fonseca   while (!cso_hash_iter_is_null(iter)) {
1436c597238b2e168b63738ac8cc9167c1d09185aadJosé Fonseca      void *iter_data = cso_hash_iter_data(iter);
1446c597238b2e168b63738ac8cc9167c1d09185aadJosé Fonseca      if (!memcmp(iter_data, templ, size)) {
1456c597238b2e168b63738ac8cc9167c1d09185aadJosé Fonseca	 /* Return the payload:
1466c597238b2e168b63738ac8cc9167c1d09185aadJosé Fonseca	  */
1476c597238b2e168b63738ac8cc9167c1d09185aadJosé Fonseca         return (unsigned char *)iter_data + size;
1486c597238b2e168b63738ac8cc9167c1d09185aadJosé Fonseca      }
1496c597238b2e168b63738ac8cc9167c1d09185aadJosé Fonseca      iter = cso_hash_iter_next(iter);
1506c597238b2e168b63738ac8cc9167c1d09185aadJosé Fonseca   }
1516c597238b2e168b63738ac8cc9167c1d09185aadJosé Fonseca   return NULL;
1526c597238b2e168b63738ac8cc9167c1d09185aadJosé Fonseca}
1536c597238b2e168b63738ac8cc9167c1d09185aadJosé Fonseca
1546c597238b2e168b63738ac8cc9167c1d09185aadJosé Fonseca
155e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusinstruct cso_hash_iter cso_find_state_template(struct cso_cache *sc,
156e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin                                             unsigned hash_key, enum cso_cache_type type,
157e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin                                             void *templ)
1589780327c5d95586a88fce94d7b47342355ead118Zack Rusin{
159e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin   struct cso_hash_iter iter = cso_find_state(sc, hash_key, type);
160e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin   int size = _cso_size_for_type(type);
161e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin   while (!cso_hash_iter_is_null(iter)) {
162e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin      void *iter_data = cso_hash_iter_data(iter);
163e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin      if (!memcmp(iter_data, templ, size))
164e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin         return iter;
165e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin      iter = cso_hash_iter_next(iter);
1669780327c5d95586a88fce94d7b47342355ead118Zack Rusin   }
167e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin   return iter;
168e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin}
169e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin
170e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusinvoid * cso_take_state(struct cso_cache *sc,
171e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin                      unsigned hash_key, enum cso_cache_type type)
172e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin{
173e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin   struct cso_hash *hash = _cso_hash_for_type(sc, type);
174e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin   return cso_hash_take(hash, hash_key);
1759780327c5d95586a88fce94d7b47342355ead118Zack Rusin}
1769780327c5d95586a88fce94d7b47342355ead118Zack Rusin
1779780327c5d95586a88fce94d7b47342355ead118Zack Rusinstruct cso_cache *cso_cache_create(void)
1789780327c5d95586a88fce94d7b47342355ead118Zack Rusin{
1799780327c5d95586a88fce94d7b47342355ead118Zack Rusin   struct cso_cache *sc = malloc(sizeof(struct cso_cache));
1809780327c5d95586a88fce94d7b47342355ead118Zack Rusin
181ccd63b54cfbb6bb241d55f7ac95afcd14819f469Zack Rusin   sc->blend_hash         = cso_hash_create();
182ccd63b54cfbb6bb241d55f7ac95afcd14819f469Zack Rusin   sc->sampler_hash       = cso_hash_create();
183d6ac959833a8e40a27907940969c622692f749b1Zack Rusin   sc->depth_stencil_hash = cso_hash_create();
184ccd63b54cfbb6bb241d55f7ac95afcd14819f469Zack Rusin   sc->rasterizer_hash    = cso_hash_create();
185f22e920f478d8732695913ec0d1f7244b451a8f5Zack Rusin   sc->fs_hash            = cso_hash_create();
186f22e920f478d8732695913ec0d1f7244b451a8f5Zack Rusin   sc->vs_hash            = cso_hash_create();
1879780327c5d95586a88fce94d7b47342355ead118Zack Rusin
1889780327c5d95586a88fce94d7b47342355ead118Zack Rusin   return sc;
1899780327c5d95586a88fce94d7b47342355ead118Zack Rusin}
1909780327c5d95586a88fce94d7b47342355ead118Zack Rusin
191e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusinvoid cso_cache_delete(struct cso_cache *sc)
1929780327c5d95586a88fce94d7b47342355ead118Zack Rusin{
1939780327c5d95586a88fce94d7b47342355ead118Zack Rusin   assert(sc);
194e16c045b83f5c5b4f4064df67623bb76b46b6619Zack Rusin   cso_hash_delete(sc->blend_hash);
195f117327a3f246713abfd4dc4320d4a1a7f1b811aZack Rusin   cso_hash_delete(sc->sampler_hash);
196d6ac959833a8e40a27907940969c622692f749b1Zack Rusin   cso_hash_delete(sc->depth_stencil_hash);
197294401814d1d89cc731de1c22c25333aa5d59374Zack Rusin   cso_hash_delete(sc->rasterizer_hash);
198f22e920f478d8732695913ec0d1f7244b451a8f5Zack Rusin   cso_hash_delete(sc->fs_hash);
199f22e920f478d8732695913ec0d1f7244b451a8f5Zack Rusin   cso_hash_delete(sc->vs_hash);
2009780327c5d95586a88fce94d7b47342355ead118Zack Rusin   free(sc);
2019780327c5d95586a88fce94d7b47342355ead118Zack Rusin}
202