Skip to content

Commit

Permalink
Add "UnloadTilesPlugin" to save GPU memory (#874)
Browse files Browse the repository at this point in the history
* Add "UnloadTilesPlugin" to save memory

* Remove options

* Add to README

* BatchedTilesPlugin: Add option to not dispose of original tiles

* Add batched mesh logic

* Remove event dependency

* Updates to BatchedMesh unload

* Add setting to docs

* Change setTileVisible call

* fixes

* Add ordered "priority" support for plugins

* Add names, priorities, unload callback for batched plugin

* Handle plugins

* README update

* remove set active plugin call

* remove comments

* add comment

* Fix incorrect reversion

* comment update
  • Loading branch information
gkjohnson authored Dec 20, 2024
1 parent b98051a commit 837cca8
Show file tree
Hide file tree
Showing 7 changed files with 338 additions and 136 deletions.
95 changes: 95 additions & 0 deletions example/src/plugins/UnloadTilesPlugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { estimateBytesUsed } from '../../../src/three/utilities.js';

// Plugin that disposes tiles on unload to remove them from the GPU, saving memory

// TODO:
// - abstract the "tile visible" callback so fade tiles can call it when tiles are _actually_ marked as non-visible
// - add a memory unload function to the tiles renderer that can be called and reacted to by any plugin including BatchedMesh,
// though this may prevent different options. Something like a subfunction that "disposeTile" calls without full disposal.
export class UnloadTilesPlugin {

constructor() {

this.name = 'UNLOAD_TILES_PLUGIN';

this.tiles = null;
this.estimatedGpuBytes = 0;

}

init( tiles ) {

this.tiles = tiles;

this._onVisibilityChangeCallback = ( { scene, visible, tile } ) => {

if ( scene ) {

const size = estimateBytesUsed( scene );
this.estimatedGpuBytes += visible ? size : - size;

if ( ! visible ) {

tiles.invokeOnePlugin( plugin => plugin.unloadTileFromGPU && plugin.unloadTileFromGPU( scene, tile ) );

}

}

};

tiles.forEachLoadedModel( ( scene, tile ) => {

const visible = tiles.visibleSet.has( tile );
this._onVisibilityChangeCallback( { scene, visible } );

} );

tiles.addEventListener( 'tile-visibility-change', this._onVisibilityChangeCallback );

}

unloadTileFromGPU( scene, tile ) {

if ( scene ) {

scene.traverse( c => {

if ( c.material ) {

const material = c.material;
material.dispose();

for ( const key in material ) {

const value = material[ key ];
if ( value && value.isTexture ) {

value.dispose();

}

}

}

if ( c.geometry ) {

c.geometry.dispose();

}

} );

}

}

dispose() {

this.tiles.removeEventListener( 'tile-visibility-change', this._onVisibilityChangeCallback );
this.estimatedGpuBytes = 0;

}

}
Loading

0 comments on commit 837cca8

Please sign in to comment.