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

@@ -185,12 +185,12 @@ static GLuint translate_tex_src_bit( GLbitfield bit )
* Examine current texture environment state and generate a unique
* key to identify it.
*/
static struct state_key *
make_state_key(GLcontext *ctx)
static void make_state_key( GLcontext *ctx, struct state_key *key )
{
struct state_key *key = CALLOC_STRUCT(state_key);
GLuint i, j;
memset(key, 0, sizeof(*key));
for (i=0;i<MAX_TEXTURE_UNITS;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_mode = translate_fog_mode(ctx->Fog.Mode);
}
return key;
}
/* Use uregs to represent registers internally, translate to Mesa's
@@ -1142,6 +1140,26 @@ static void rehash( struct texenvprog_cache *cache )
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,
GLuint hash,
void *key,
@@ -1149,12 +1167,20 @@ static void cache_item( struct texenvprog_cache *cache,
{
struct texenvprog_cache_item *c = MALLOC(sizeof(*c));
c->hash = hash;
c->key = key;
c->key = _mesa_malloc(sizeof(*key));
memcpy(c->key, key, sizeof(*key));
c->data = data;
if (++cache->n_items > cache->size * 1.5)
rehash(cache);
if (cache->n_items > cache->size * 1.5) {
if (cache->size < 1000)
rehash(cache);
else
clear_cache(cache);
}
cache->n_items++;
c->next = cache->items[hash % cache->size];
cache->items[hash % cache->size] = c;
}
@@ -1164,27 +1190,31 @@ static GLuint hash_key( struct state_key *key )
GLuint *ikey = (GLuint *)key;
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++)
hash ^= ikey[i];
for (i = 0; i < sizeof(*key)/sizeof(*ikey); i++)
{
hash += ikey[i];
hash += (hash << 10);
hash ^= (hash >> 6);
}
return hash;
}
void _mesa_UpdateTexEnvProgram( GLcontext *ctx )
{
struct state_key *key;
struct state_key key;
GLuint hash;
struct fragment_program *prev = ctx->FragmentProgram._Current;
if (!ctx->FragmentProgram._Enabled) {
key = make_state_key(ctx);
hash = hash_key(key);
make_state_key(ctx, &key);
hash = hash_key(&key);
ctx->FragmentProgram._Current = ctx->_TexEnvProgram =
(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 (0) _mesa_printf("Building new texenv proggy for key %x\n", hash);
@@ -1193,11 +1223,10 @@ void _mesa_UpdateTexEnvProgram( GLcontext *ctx )
(struct fragment_program *)
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 {
_mesa_free(key);
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 )
{
ctx->Texture.env_fp_cache.ctx = ctx;
ctx->Texture.env_fp_cache.size = 17;
ctx->Texture.env_fp_cache.n_items = 0;
ctx->Texture.env_fp_cache.items = (struct texenvprog_cache_item **)
@@ -1227,16 +1257,6 @@ void _mesa_TexEnvProgramCacheInit( GLcontext *ctx )
void _mesa_TexEnvProgramCacheDestroy( GLcontext *ctx )
{
struct texenvprog_cache_item *c, *next;
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);
}
clear_cache(&ctx->Texture.env_fp_cache);
_mesa_free(ctx->Texture.env_fp_cache.items);
}