From b3c5a8fb95335de6bef4f4a814c1e9e3c611d781 Mon Sep 17 00:00:00 2001 From: curt Date: Mon, 29 Jul 2002 05:07:38 +0000 Subject: [PATCH] Various tweaks, enhancements, and optimizations surrounding tile paging (specifically freeing tiles when we need to remove them from the tile cache.) --- src/Scenery/tileentry.cxx | 27 ++++++++++----------------- src/Scenery/tileentry.hxx | 5 ----- src/Scenery/tilemgr.cxx | 20 ++++++++++++++++++-- 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/src/Scenery/tileentry.cxx b/src/Scenery/tileentry.cxx index b6bb04198..8aae404f7 100644 --- a/src/Scenery/tileentry.cxx +++ b/src/Scenery/tileentry.cxx @@ -682,24 +682,16 @@ ssgBranch* FGTileEntry::gen_runway_lights( ssgVertexArray *points,ssgVertexArray } // ADA -#ifdef WISH_PLIB_WAS_THREADED // but it isn't - -// Schedule tile to be freed/removed -void FGTileEntry::sched_removal() { - global_tile_mgr.ready_to_delete( this ); -} - -#endif - // Free "n" leaf elements of an ssg tree. returns the number of // elements freed. An empty branch node is considered a leaf. This // is intended to spread the load of freeing a complex tile out over // several frames. static int fgPartialFreeSSGtree( ssgBranch *b, int n ) { + int num_deletes = 0; + if ( n > 0 ) { // we still have some delete budget left - int num_deletes = 0; for ( int i = 0; i < b->getNumKids(); ++i ) { ssgEntity *kid = b->getKid(i); if ( kid->isAKindOf( ssgTypeBranch() ) && kid->getRef() <= 1 ) { @@ -719,10 +711,15 @@ static int fgPartialFreeSSGtree( ssgBranch *b, int n ) { num_deletes++; } } - return num_deletes; - } else { - return 0; + // remove the parent if it is empty + if ( b->getNumKids() < 0 ) { + ssgDeRefDelete( b ); + num_deletes++; + n--; + } } + + return num_deletes; } @@ -767,7 +764,6 @@ bool FGTileEntry::free_tile() { // disconnected from the scene graph) SG_LOG( SG_TERRAIN, SG_DEBUG, "FREEING terra_transform" ); if ( fgPartialFreeSSGtree( terra_transform, delete_size ) == 0 ) { - ssgDeRefDelete( terra_transform ); // polish off the parent free_tracker |= TERRA_NODE; } } else if ( !(free_tracker & GROUND_LIGHTS) && gnd_lights_transform ) { @@ -775,7 +771,6 @@ bool FGTileEntry::free_tile() { // disconnected from the scene graph) SG_LOG( SG_TERRAIN, SG_DEBUG, "FREEING gnd_lights_transform" ); if ( fgPartialFreeSSGtree( gnd_lights_transform, delete_size ) == 0 ) { - ssgDeRefDelete( gnd_lights_transform ); // polish off the parent free_tracker |= GROUND_LIGHTS; } } else if ( !(free_tracker & RWY_LIGHTS) && rwy_lights_transform ) { @@ -783,7 +778,6 @@ bool FGTileEntry::free_tile() { // disconnected from the scene graph) SG_LOG( SG_TERRAIN, SG_DEBUG, "FREEING rwy_lights_transform" ); if ( fgPartialFreeSSGtree( rwy_lights_transform, delete_size ) == 0 ) { - ssgDeRefDelete( rwy_lights_transform ); // polish off the parent free_tracker |= RWY_LIGHTS; } } else if ( !(free_tracker & LIGHTMAPS) && lightmaps_transform ) { @@ -792,7 +786,6 @@ bool FGTileEntry::free_tile() { // disconnected from the scene graph) SG_LOG( SG_TERRAIN, SG_DEBUG, "FREEING lightmaps_transform" ); if ( fgPartialFreeSSGtree( lightmaps_transform, delete_size ) == 0 ) { - ssgDeRefDelete( lightmaps_transform ); // polish off the parent free_tracker |= LIGHTMAPS; } } else { diff --git a/src/Scenery/tileentry.hxx b/src/Scenery/tileentry.hxx index 5f413b047..fec233e99 100644 --- a/src/Scenery/tileentry.hxx +++ b/src/Scenery/tileentry.hxx @@ -218,11 +218,6 @@ public: // Destructor ~FGTileEntry(); -#ifdef WISH_PLIB_WAS_THREADED // but it isn't - // Schedule tile to be freed/removed - void sched_removal(); -#endif - // Clean up the memory used by this tile and delete the arrays // used by ssg as well as the whole ssg branch. This does a // partial clean up and exits so we can spread the load across diff --git a/src/Scenery/tilemgr.cxx b/src/Scenery/tilemgr.cxx index aaf6b0da3..c9b335249 100644 --- a/src/Scenery/tilemgr.cxx +++ b/src/Scenery/tilemgr.cxx @@ -362,9 +362,25 @@ int FGTileMgr::update( double lon, double lat, double visibility_meters, // cout << "Adding ssg nodes for " } - // cout << "delete queue = " << delete_queue.size() << endl; if ( !delete_queue.empty() ) { - FGTileEntry* e = delete_queue.front(); + // cout << "delete queue = " << delete_queue.size() << endl; + + while ( delete_queue.size() > 30 ) { + // uh oh, delete queue is blowing up, we aren't clearing + // it fast enough. Let's just panic, well not panic, but + // get real serious and agressively free up some tiles so + // we don't explode our memory usage. + + SG_LOG( SG_TERRAIN, SG_ALERT, + "Alert: catching up on tile delete queue" ); + + FGTileEntry* e = delete_queue.front(); + while ( !e->free_tile() ); + delete_queue.pop(); + delete e; + } + + FGTileEntry* e = delete_queue.front(); if ( e->free_tile() ) { delete_queue.pop(); delete e; -- 2.39.5