@@ -59,20 +59,15 @@ export class UnloadTilesPlugin {
5959 this . tiles = tiles ;
6060
6161 const { lruCache, deferCallbacks } = this ;
62- deferCallbacks . callback = tile => {
63-
64- lruCache . markUnused ( tile ) ;
65- lruCache . scheduleUnload ( false ) ;
66-
67- } ;
6862
6963 const unloadCallback = tile => {
7064
65+ // trigger a tile unload from the GPU if it's not currently visible
7166 const scene = tile . engineData . scene ;
7267 const visible = tiles . visibleTiles . has ( tile ) ;
73-
7468 if ( ! visible ) {
7569
70+ // extra visible check in case another plugin or system has forced it to be visible
7671 tiles . invokeOnePlugin ( plugin => plugin . unloadTileFromGPU && plugin . unloadTileFromGPU ( scene , tile ) ) ;
7772
7873 }
@@ -83,47 +78,75 @@ export class UnloadTilesPlugin {
8378
8479 // update lruCache in "update" in case the callback values change
8580 lruCache . unloadPriorityCallback = tiles . lruCache . unloadPriorityCallback ;
86- lruCache . computeMemoryUsageCallback = tiles . lruCache . computeMemoryUsageCallback ;
81+
82+ // adjust the settings so we don't reject tiles added
8783 lruCache . minSize = Infinity ;
8884 lruCache . maxSize = Infinity ;
8985 lruCache . maxBytesSize = Infinity ;
86+
87+ // unload all tiles possible at once
9088 lruCache . unloadPercent = 1 ;
89+
90+ // do not run mark unused without an explicit call
9191 lruCache . autoMarkUnused = false ;
9292
9393 } ;
9494
95- this . _onVisibilityChangeCallback = ( { tile, visible } ) => {
95+ this . _onVisibilityChangeCallback = ( { tile, scene , visible } ) => {
9696
9797 if ( visible ) {
9898
99+ // if the tile is visible then do not trigger disposal - for the tile to have at least 1 byte of
100+ // memory usage to ensure the lru cache will always remove the item to reduce memory pressure
99101 lruCache . add ( tile , unloadCallback ) ;
102+ lruCache . setMemoryUsage ( tile , tiles . calculateBytesUsed ( tile , scene ) || 1 ) ;
100103 tiles . markTileUsed ( tile ) ;
101104 deferCallbacks . cancel ( tile ) ;
102105
103106 } else {
104107
108+ // mark the tile as unused in our cache and trigger an unload after the delay
105109 deferCallbacks . run ( tile ) ;
106110
107111 }
108112
109113 } ;
110114
115+ this . _onDisposeModel = ( { tile } ) => {
116+
117+ lruCache . remove ( tile ) ;
118+ deferCallbacks . cancel ( tile ) ;
119+
120+ } ;
121+
122+ deferCallbacks . callback = tile => {
123+
124+ // try to unload the tile up to our limit
125+ lruCache . markUnused ( tile ) ;
126+ lruCache . scheduleUnload ( ) ;
127+
128+ } ;
129+
130+ // initialize all existing tiles
111131 tiles . forEachLoadedModel ( ( scene , tile ) => {
112132
113133 const visible = tiles . visibleTiles . has ( tile ) ;
114- this . _onVisibilityChangeCallback ( { scene , visible } ) ;
134+ this . _onVisibilityChangeCallback ( { tile , visible } ) ;
115135
116136 } ) ;
117137
118138 tiles . addEventListener ( 'tile-visibility-change' , this . _onVisibilityChangeCallback ) ;
119139 tiles . addEventListener ( 'update-before' , this . _onUpdateBefore ) ;
140+ tiles . addEventListener ( 'dispose-model' , this . _onDisposeModel ) ;
120141
121142 }
122143
123144 unloadTileFromGPU ( scene , tile ) {
124145
125146 if ( scene ) {
126147
148+ // disposes of all GPU memory and materials associated with the tile but does not
149+ // close any image bitmaps so we can reupload them as needed
127150 scene . traverse ( c => {
128151
129152 if ( c . material ) {
@@ -158,9 +181,19 @@ export class UnloadTilesPlugin {
158181
159182 dispose ( ) {
160183
161- this . tiles . removeEventListener ( 'tile-visibility-change' , this . _onVisibilityChangeCallback ) ;
162- this . tiles . removeEventListener ( 'update-before' , this . _onUpdateBefore ) ;
163- this . deferCallbacks . cancelAll ( ) ;
184+ const { lruCache, tiles, deferCallbacks } = this ;
185+
186+ tiles . removeEventListener ( 'tile-visibility-change' , this . _onVisibilityChangeCallback ) ;
187+ tiles . removeEventListener ( 'update-before' , this . _onUpdateBefore ) ;
188+ tiles . removeEventListener ( 'dispose-model' , this . _onDisposeModel ) ;
189+ deferCallbacks . cancelAll ( ) ;
190+
191+ // clear the lru cache
192+ lruCache . minBytesSize = 0 ;
193+ lruCache . minSize = 0 ;
194+ lruCache . maxSize = 0 ;
195+ lruCache . markAllUnused ( ) ;
196+ lruCache . scheduleUnload ( ) ;
164197
165198 }
166199
@@ -192,7 +225,12 @@ class DeferCallbackManager {
192225
193226 } else {
194227
195- map . set ( tile , setTimeout ( ( ) => this . callback ( tile ) , delay ) ) ;
228+ map . set ( tile , setTimeout ( ( ) => {
229+
230+ this . callback ( tile ) ;
231+ map . delete ( tile ) ;
232+
233+ } , delay ) ) ;
196234
197235 }
198236
0 commit comments