VRAM doesn't get released properly

Hi PlayCanvas Team,

When switching scenes, the VRAM doesn’t get released.

I have forked the scene-switching project for testing this issue:

https://playcanvas.com/project/650110

The 6 scenes in the test project auto-switch after 3 seconds. Observe that the total texture memory in VRAM (PlayCanvas Profiler) don’t get released properly.

You can enable the PlayCanvas Profile by hovering the “Play” Button and check “Profiler”.

@moka I have seen you are already working on the Ammo memory leaks, maybe this one is related?

Best,
Rene

Hi @dexter_deluxe,

I think what is happening is normal given the existing scene loader.

loadSceneHierarchy(): Load a scene file, create and initialize the Entity hierarchy and add the hierarchy to the application root Entity.

So basically this isn’t a scene switcher, but mainly loads a scene (entities and assets dumped in VRAM) and appends it to the existing scene as a child entity. This method won’t unload anything.

You will have to manually take care of unloading all scene assets, much like you destroy the oldHierarchy.

Here is a helpful thread on the subject:

1 Like

Hi @Leonidas,

thanks for your answer. Please have a look at line 23 of changing-scenes.js, which calls oldHierarchy.destroy();

This is basically the same script as in changing scenes example.

Best,
Rene

`

You are doing everything fine, but still you will need to manually unload all assets that get loaded by each scene. This is by design, and there are some cases that it can be useful (fast scene switching, assets with small VRAM footprint etc).

oldHierarchy.destroy();

That method will remove only the scene entities from the scene hierarchy, it will not unload the resources used (models, materials, textures etc.).

You could post a feature request in the engine repo about that, for a method that can handle the scene assets unloading.

Hi @Leonidas,

thanks for the answer. In the sample project, how should one tackle this? The asset registry “this.app.assets” has all the assets listed. Even textures where I set “preload” to false have their loaded flag set to true. So how can I find out which assets are currently loaded, so I can unload them on scene change?

Good point, textures that have preload to false on run-time eventually they will get loaded automatically as soon as they get used somewhere. For example an entity referencing a model that references materials that reference that texture.

I think since you are changing scenes, what you expect is to unload all assets currently loaded. So you could iterate through all the assets in the asset registry, check the loaded property and if it is set to true, do myAsset.unload().

If you do this as a blocking step, after you destroy the oldHierarchy and before loading the new scene, I think that would work nicely.

To iterate through all assets in the registry you can use either the filter method (without doing anything meaningful on return) or the this.app.assets._assets private property (it’s an array with all registry assets). Example code:

this.app.assets.filter( function(asset){

    if( asset.loaded === true ) asset.unload();
    
    return false;
});

https://developer.playcanvas.com/en/api/pc.AssetRegistry.html

Hi @Leonidas,

the problem is, that the “loaded” property is true to all assets. Even assets which are not referenced in the scene (as far as I know).

I have disabled the scene “switching” for now and print all loaded assets after 1 seconds like this:

    var loadedAssets = this.app.assets.filter(
        function(asset) 
        {
            return asset.loaded === true;
        }
    );
    
    loadedAssets.forEach(function(asset)
    {
        console.log(asset.name);
    });

It prints me all assets, even the other textures

Here is a new sample project.

EDIT: I’ve just found out that the material was still set to preload true (which also loads the texture where preload is set to false). I’m currently investigating it further

Best,
Rene

Yes, exactly, anything that references the textures will trigger the action to load them. Unticking preload in those materials will keep both the materials and textures from getting loaded:

Hi @Leonidas,

the VRAM seems to be released now. https://playcanvas.com/project/650137

It works for the first iteration of scene switching, but when loading a scene again (after reaching scene 6) the material stays black -.-

Yes, whatever asset has been removed from VRAM using the unload() method, it has to be reloaded manually using the load() method available in the registry.

Check this post for more on this system:

@Leonidas So the developer has to manually store a list of all assets per scene for the occasion when he wants to load that scene again? This seems quite counter-intuitive - since the scene already knows all if its assets to load (e.g. when loading it the first time).

You make a fair point, there have been a lot of requests for improving the scene changing methods in Playcanvas. I’d say go ahead and post this as a feature request in the engine repository.

Regarding assets loading/unloading, speaking from my experience, as soon as you get up to speed with how everything works that fine grained control pays off in the long term. Not only between scenes but inside a single more complex scene helps keep performance and memory usage in control.

Thanks a lot @Leonidas,

I’ve posted a feature request here: https://github.com/playcanvas/engine/issues/1751

1 Like

Hi dexter_deluxe, I’ve posted a response on Issue on github.

2 Likes