Textures aren’t unloaded correctly from my levels

Each level of my game uses about 9 textures. However after going from one level to another, I see in profiler that textures aren’t unloaded correctly (most likely my fault), so in level 2 there are 18 textures, etc… This is cleanup function of LevelAppState, where all level-related things are going on:

[java]public void cleanup() {

super.cleanup();

this.app.music.stop();

// app.player.setEnabled(false);

assetManager.unregisterLocator(“assets”, FileLocator.class);

// unregister all my listeners, detach all my nodes, etc…

levelNode.detachAllChildren(); // all level-related things are attached here, including player

rootNode.detachAllChildren();

levelNode = null;

inputManager.deleteMapping(“Shoot”);

inputManager.removeListener((InputListener) actionListener);



inputManager.deleteMapping(“Left”);

inputManager.deleteMapping(“Right”);

inputManager.deleteMapping(“Up”);

inputManager.deleteMapping(“Down”);

// inputManager.deleteMapping(“Jump”);

inputManager.deleteMapping(“CAM”);

inputManager.removeListener((InputListener) movement);

inputManager.removeListener(actionListener);

inputManager.removeListener((InputListener) movement);

inputManager.removeListener((InputListener) movement);

inputManager.removeListener((InputListener) movement);

inputManager.removeListener((InputListener) movement);

fpp.removeAllFilters();

System.gc();

}[/java]



As you can see, I detach all children of levelNode, then detach it from rootNode (here detachAllChildren is just precaution, as there shouldn’t be any other children, but I want to be sure). As you can see, I’ve even tried to set levelNode to null afterwards, and even tried to call garbage collector as last instruction, but it didn’t help. Can you tell me, how to unload textures used by level properly? I can’t make cache before game starts, because every level can have different textures and I don’t know which until level loader is called.



//edit: It seems like same thing is going on for Framebuffers - for some reason they stay in memory, even after level change.

5 Likes

Maybe you just have to wait for the garbage collector to run and clean them up.



edit: just saw the manual GC call. Are you sure your cleanup() method gets called?

And why would you try to force it, do you get out of memory errors? Maybe the garbage collector will run eventually and when it does a full GC the textures will be reclaimed. Don’t fix it if it isn’t broken :slight_smile:

You might also try to google this forum (use the google search box up to the right) for “direct memory buffer”.

1 Like
@jmaasing said:
And why would you try to force it, do you get out of memory errors? Maybe the garbage collector will run eventually and when it does a full GC the textures will be reclaimed. Don't fix it if it isn't broken :)
You might also try to google this forum (use the google search box up to the right) for "direct memory buffer".

Because FPS is lower and lower with each level? Also as I said, it isn't problem that GC doesn't run - in fact I forced it and it still didn't clean any of the textures that aren't used. After playing game for a while profiler looks like this:

Framebuffers (M) 10
Framebuffers (F) 2
Framebuffers (S) 3
Textures (M) 47 (5*9 + two textures used in main menu that aren't unloaded properly either)
Textures (F) 9
Textures (S) 9

Make sure that there are not references to the materials (i.e: are you storing the materials in a list? or in a class’ property?).



I don’t know if jm3 uses some kind of cache for the materials. Check that also.

First, materials aren’t stored anywhere, except being attached to spatials (and textures aren’t stored anywhere either, except being attached to their appropriate materials). Detaching spatials should also take care of materials. I can send my level loading class on PM upon request - maybe the problem is in the way I load levels?

I was able to reproduce the issue simply in the SceneComposer by loading and unloading models (the SDK does that explicitly, so its even stranger), also in nightly. @Momoko_Fan, any ideas on recent changes that might cause this?

You could also get assetmanager cast to desktopassetmanger and call clearCache() before loading the next level.

@normen said:
I was able to reproduce the issue simply in the SceneComposer by loading and unloading models (the SDK does that explicitly, so its even stranger), also in nightly. @Momoko_Fan, any ideas on recent changes that might cause this?


That might explain what I'm getting too. This is something I noticed but since I'm working on something else I didn't delve into it at all. Of course, this could be something I'm doing.

I'll keep an eye on this thread.

I noticed that if I call System.gc() or DesktopAssetManager.clearCache() I can get some the textures to get collected … Unfortunately the GC doesn’t think the textures take a lot of space since the main part of it is in “direct memory” so it keeps them in.

@Momoko_Fan said:
I noticed that if I call System.gc() or DesktopAssetManager.clearCache() I can get some the textures to get collected ... Unfortunately the GC doesn't think the textures take a lot of space since the main part of it is in "direct memory" so it keeps them in.

Same here. It decreased usage a bit, but textures (M) are still about two times greater than textures (F), at best.

Also, issue is still present with framebuffers (I’m using postprocessing effects such as depth of field)

Any help on issue?

Just wait a bit, they are thinking ^^ Give them some time.

The solution in this SO thread for clearing direct buffers was regarded with some interest a while back but ended up not being a great solution… @normen would be able to say why it didn’t work out.

@dariuszg-jagielski said:
Because FPS is lower and lower with each level?

@dariuszg-jagielski said:
Any help on issue?

The added memory for the textures should not cause this, the fps drop is probably caused due to something else in your code so we cannot help with that. The number of textures still has to prove to be an issue outside the "normal" direct buffer handling traps as it might simply be a visual issue.

The issue is probably related though, as framebuffers used for postprocessing effects aren’t cleared either, despite removal all filters from fpp (see cleanup method on 1st page). So I have in first levels Framebuffers (M) 2 and Framebuffers (F) 2, then I have Framebuffers (M) 4,6,8,10,12,14,etc., though Framebuffers (F) is constant from level to level (2).

Yes, again, that in itself is not an issue.

In most cases the driver should remove the unused textures / framebuffers from VRAM since they are no longer used (even without being explicitly deleted by the app). Of course those resources are still kept in system memory by GL in the case that they are used again, but in general this would not slow down rendering.

@dariuszg-jagielski said:
The issue is probably related though, as framebuffers used for postprocessing effects aren't cleared either, despite removal all filters from fpp (see cleanup method on 1st page). So I have in first levels Framebuffers (M) 2 and Framebuffers (F) 2, then I have Framebuffers (M) 4,6,8,10,12,14,etc., though Framebuffers (F) is constant from level to level (2).


You aren't really listening. You can have 50 frame buffers and it probably won't cause an FPS drop. In my experience toggling post processing on and off, the buffers grow and then eventually shrink back down again. This is normal.

Your FPS drop is caused by something else in your code. Read that again until it sinks in and then figure out what it is. Something you've added, app states, controls, whatever aren't being cleaned up. Maybe stick printlns in their updates to see why you are losing frames.

Or if you are unconvinced, remove post processing and see if you still lose frames after some number of levels.