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