Original Post
Hi, ive been trying to implement a texture cache for a while now. The caching seems to work however ive got some problems mapping the cache/textures to specific coordinates. I have a system that updates textures every frame (not all textures) so what ive done is created a simple ref counted vector of textures. The textures are pre-allocated, so I only update them using glTexSubImage2d (which is way faster than creating a new texture every frame). The problem comes from the fact that a texture is mapped to multiple xy coords, so I need to have a jump table with the index into the cache. The system then searches thru the cache and sees if it can find a texture with the correct image id, if the id doesnt exist it will update a texture in the pool with the new data and id, and give it an low reference count. The mapping doesnt work as I expected and im a little lost in what is wrong. I have 2 questions, is this kind of caching the way to go? There are around 500 textures to be updates each frames, but it can be as low as 5 or as high as 4000. I have succesfully tested it without caching and it runs at 10 to 15 fps depending on how many textures there are to update. I hope that with some caching I can increase it at least to 25 fps. The second question, if anybody can look at the code and see if theres something i've missed or a better way to do it? For the ones that are wondering im part of a collective that is working on a realtime mosaic generator. The generator itself runs at over 40 fps ;) but we want to add a lot of fancy opengl effects to it, so thats where I come in. Sorry for the long code dump ;)
CTextureCache::CTextureCache() {
std::cout << __FUNCTION__ << " Creating cache of size " << 64 * 48 * 4 << std::endl;
for ( int t = 0; t < 5000; t++ )
xyCoords = new int;
for ( int t = 0; t < 5000; t++ )
idCoords = new int;
for ( int i = 0; i < 500; i++ ) {
char blaat[ 64 * 64 * 4 ];
memset( blaat, 0xf0f0, sizeof( blaat ) );
textureCache.push_back( new CTexture( ( unsigned int* ) blaat, 64, 48 ) );
}
}
void CTextureCache::update() {
unsigned long tg_cnt = *( ( unsigned long* ) CObjectManager::getSingleton().getVariable( "tilecount" ) );
TileGrid* tg = reinterpret_cast<TileGrid*>( CObjectManager::getSingleton().getObject( "tilegrid" ) );
int tilecount = 0;
std::sort( textureCache.begin(), textureCache.end(), CTexture::TCompare() );
for ( int i = 0; i < tg_cnt; i++ ) {
if ( tg[ i ].changed ) {
bool cacheHit = false;
int cacheHitIndex = -1;
int t;
textureVectorType::iterator iter;
int iterCount = 0;
for ( iter = textureCache.begin(); iter != textureCache.end(); iter++ ) {
iterCount++;
if ( ( *iter ) ->tileID == tg[ i ].ID ) {
cacheHit = true;
( *iter ) ->m_priority += 5;
( *iter ) ->x = tg[ i ].x;
( *iter ) ->y = tg[ i ].y;
xyCoords[ tg[ i ].x + ( tg[ i ].y * 64 ) ] = iterCount - 1;
idCoords[ tg[ i ].x + ( tg[ i ].y * 64 ) ] = tg[ i ].ID;
if ( ( *iter ) ->tileID != textureCache.at( iterCount - 1 ) ->tileID )
std::cout << "Not equal!!" << std::endl;
xyCoords[tg.x + (tg.y*64)] = tilecount++;
break;
} else {
xyCoords[ tg[ i ].x + ( tg[ i ].y * 64 ) ] = iterCount-1;
idCoords[ tg[ i ].x + ( tg[ i ].y * 64 ) ] = tg[ i ].ID;
if (textureCache.at(xyCoords[ tg[ i ].x + ( tg[ i ].y * 64 ) ])->tileID !=
idCoords[ tg[ i ].x + ( tg[ i ].y * 64 ) ])
std::cout << "Not matching indexes!" << std::endl;
if ( ( *iter ) ->m_priority > 250 ) {
( *iter ) ->m_priority -= 1;
if ( ( *iter ) ->tileID != textureCache.at( iterCount - 1 ) ->tileID )
std::cout << "Not equal!!" << std::endl;
}
}
}
if ( !cacheHit ) {
iter = textureCache.end();
iter--;
( *iter ) ->x = tg[ i ].x;
( *iter ) ->y = tg[ i ].y;
( *iter ) ->tileID = tg[ i ].ID;
( *iter ) ->updateTexture(
( unsigned int* ) tg[ i ].tileptr, 64, 48
);
( *iter ) ->m_priority = 4;
xyCoords[ tg[ i ].x + ( tg[ i ].y * 64 ) ] = textureCache.size() - 1;
idCoords[ tg[ i ].x + ( tg[ i ].y * 64 ) ] = tg[ i ].ID;
if ( ( *iter ) ->tileID != textureCache.at( textureCache.size() - 1 ) ->tileID )
std::cout << "Not equal!!" << std::endl;
}
}
}
cacheRatio = tilecount * 100 / tg_cnt;
}
GLuint CTextureCache::getTexture( int x, int y ) {
int coordIndex = abs( xyCoords[ x + ( y * 64 ) ] );
// std::cout << "xycoords " << coordIndex << std::endl << std::flush;
if ( idCoords[ coordIndex ] != textureCache.at( coordIndex ) ->tileID )
std::cout << "IDs dont match!" << std::endl;
if ( coordIndex < 500 ) {
if ( textureCache[ coordIndex ] != NULL )
return textureCache[ coordIndex ] ->getID();
}
return 0;
}