memory usage fixes for glean/conform, use a better hash function

This commit is contained in:
Keith Whitwell
2006-05-22 16:09:27 +00:00
parent 64da16146f
commit 8065c120c4
2 changed files with 51 additions and 30 deletions

View File

@@ -1517,13 +1517,14 @@ struct gl_texture_unit
struct texenvprog_cache_item { struct texenvprog_cache_item {
GLuint hash; GLuint hash;
void *key; void *key;
void *data; struct fragment_program *data;
struct texenvprog_cache_item *next; struct texenvprog_cache_item *next;
}; };
struct texenvprog_cache { struct texenvprog_cache {
struct texenvprog_cache_item **items; struct texenvprog_cache_item **items;
GLuint size, n_items; GLuint size, n_items;
GLcontext *ctx;
}; };
/** /**

View File

@@ -185,12 +185,12 @@ static GLuint translate_tex_src_bit( GLbitfield bit )
* Examine current texture environment state and generate a unique * Examine current texture environment state and generate a unique
* key to identify it. * key to identify it.
*/ */
static struct state_key * static void make_state_key( GLcontext *ctx, struct state_key *key )
make_state_key(GLcontext *ctx)
{ {
struct state_key *key = CALLOC_STRUCT(state_key);
GLuint i, j; GLuint i, j;
memset(key, 0, sizeof(*key));
for (i=0;i<MAX_TEXTURE_UNITS;i++) { for (i=0;i<MAX_TEXTURE_UNITS;i++) {
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i]; struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
@@ -233,8 +233,6 @@ make_state_key(GLcontext *ctx)
key->fog_enabled = 1; key->fog_enabled = 1;
key->fog_mode = translate_fog_mode(ctx->Fog.Mode); key->fog_mode = translate_fog_mode(ctx->Fog.Mode);
} }
return key;
} }
/* Use uregs to represent registers internally, translate to Mesa's /* Use uregs to represent registers internally, translate to Mesa's
@@ -1142,6 +1140,26 @@ static void rehash( struct texenvprog_cache *cache )
cache->size = size; cache->size = size;
} }
static void clear_cache( struct texenvprog_cache *cache )
{
struct texenvprog_cache_item *c, *next;
GLuint i;
for (i = 0; i < cache->size; i++) {
for (c = cache->items[i]; c; c = next) {
next = c->next;
_mesa_free(c->key);
cache->ctx->Driver.DeleteProgram(cache->ctx, (struct program *)c->data);
_mesa_free(c);
}
cache->items[i] = NULL;
}
cache->n_items = 0;
}
static void cache_item( struct texenvprog_cache *cache, static void cache_item( struct texenvprog_cache *cache,
GLuint hash, GLuint hash,
void *key, void *key,
@@ -1149,12 +1167,20 @@ static void cache_item( struct texenvprog_cache *cache,
{ {
struct texenvprog_cache_item *c = MALLOC(sizeof(*c)); struct texenvprog_cache_item *c = MALLOC(sizeof(*c));
c->hash = hash; c->hash = hash;
c->key = key;
c->key = _mesa_malloc(sizeof(*key));
memcpy(c->key, key, sizeof(*key));
c->data = data; c->data = data;
if (++cache->n_items > cache->size * 1.5) if (cache->n_items > cache->size * 1.5) {
if (cache->size < 1000)
rehash(cache); rehash(cache);
else
clear_cache(cache);
}
cache->n_items++;
c->next = cache->items[hash % cache->size]; c->next = cache->items[hash % cache->size];
cache->items[hash % cache->size] = c; cache->items[hash % cache->size] = c;
} }
@@ -1164,27 +1190,31 @@ static GLuint hash_key( struct state_key *key )
GLuint *ikey = (GLuint *)key; GLuint *ikey = (GLuint *)key;
GLuint hash = 0, i; GLuint hash = 0, i;
/* I'm sure this can be improved on, but speed is important: /* Make a slightly better attempt at a hash function:
*/ */
for (i = 0; i < sizeof(*key)/sizeof(GLuint); i++) for (i = 0; i < sizeof(*key)/sizeof(*ikey); i++)
hash ^= ikey[i]; {
hash += ikey[i];
hash += (hash << 10);
hash ^= (hash >> 6);
}
return hash; return hash;
} }
void _mesa_UpdateTexEnvProgram( GLcontext *ctx ) void _mesa_UpdateTexEnvProgram( GLcontext *ctx )
{ {
struct state_key *key; struct state_key key;
GLuint hash; GLuint hash;
struct fragment_program *prev = ctx->FragmentProgram._Current; struct fragment_program *prev = ctx->FragmentProgram._Current;
if (!ctx->FragmentProgram._Enabled) { if (!ctx->FragmentProgram._Enabled) {
key = make_state_key(ctx); make_state_key(ctx, &key);
hash = hash_key(key); hash = hash_key(&key);
ctx->FragmentProgram._Current = ctx->_TexEnvProgram = ctx->FragmentProgram._Current = ctx->_TexEnvProgram =
(struct fragment_program *) (struct fragment_program *)
search_cache(&ctx->Texture.env_fp_cache, hash, key, sizeof(*key)); search_cache(&ctx->Texture.env_fp_cache, hash, &key, sizeof(key));
if (!ctx->_TexEnvProgram) { if (!ctx->_TexEnvProgram) {
if (0) _mesa_printf("Building new texenv proggy for key %x\n", hash); if (0) _mesa_printf("Building new texenv proggy for key %x\n", hash);
@@ -1193,11 +1223,10 @@ void _mesa_UpdateTexEnvProgram( GLcontext *ctx )
(struct fragment_program *) (struct fragment_program *)
ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
create_new_program(key, ctx, ctx->_TexEnvProgram); create_new_program(&key, ctx, ctx->_TexEnvProgram);
cache_item(&ctx->Texture.env_fp_cache, hash, key, ctx->_TexEnvProgram); cache_item(&ctx->Texture.env_fp_cache, hash, &key, ctx->_TexEnvProgram);
} else { } else {
_mesa_free(key);
if (0) _mesa_printf("Found existing texenv program for key %x\n", hash); if (0) _mesa_printf("Found existing texenv program for key %x\n", hash);
} }
} }
@@ -1217,6 +1246,7 @@ void _mesa_UpdateTexEnvProgram( GLcontext *ctx )
void _mesa_TexEnvProgramCacheInit( GLcontext *ctx ) void _mesa_TexEnvProgramCacheInit( GLcontext *ctx )
{ {
ctx->Texture.env_fp_cache.ctx = ctx;
ctx->Texture.env_fp_cache.size = 17; ctx->Texture.env_fp_cache.size = 17;
ctx->Texture.env_fp_cache.n_items = 0; ctx->Texture.env_fp_cache.n_items = 0;
ctx->Texture.env_fp_cache.items = (struct texenvprog_cache_item **) ctx->Texture.env_fp_cache.items = (struct texenvprog_cache_item **)
@@ -1227,16 +1257,6 @@ void _mesa_TexEnvProgramCacheInit( GLcontext *ctx )
void _mesa_TexEnvProgramCacheDestroy( GLcontext *ctx ) void _mesa_TexEnvProgramCacheDestroy( GLcontext *ctx )
{ {
struct texenvprog_cache_item *c, *next; clear_cache(&ctx->Texture.env_fp_cache);
GLuint i;
for (i = 0; i < ctx->Texture.env_fp_cache.size; i++)
for (c = ctx->Texture.env_fp_cache.items[i]; c; c = next) {
next = c->next;
_mesa_free(c->key);
_mesa_free(c->data);
_mesa_free(c);
}
_mesa_free(ctx->Texture.env_fp_cache.items); _mesa_free(ctx->Texture.env_fp_cache.items);
} }