memory usage fixes for glean/conform, use a better hash function
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user