OpenGL Texture Memory and Nifty

Is there any way to clear out the OpenGL memory when it comes to textures? I only ask because I’m using Nifty GUI, and whenever the screen is switched, all of the old textures continue sitting in memory, taking up space. While this is probably fine for the time being, I’m not sure if it’ll become an issue when the menu starts getting larger and larger (so far I’ve managed to get about 85 textures into the memory stat listed with the stats view).

I’m using either Nifty 1.3 or 1.3.1, and JME 3.0RC2.

Any guidance would be appreciated.

Have you tried using the nifty renderer that batches? It only uses 1 texture and supposedly optimizes it based on what is visible on-screen.

i would like to have cleanup too.
For example when i loaded a screen, then i remove it like this:
[java]nifty.removeScreen(“myScreen”);[/java]
unused textures should be removed too.

@Momoko_Fan: No, I don’t think so, because I think that was added in 1.3.3 if I’m not mistaken. I have 1.3 or 1.3.1, and last time I tried to upgrade, half my stuff stopped working…

Hm… maybe checking out the diffs of Nifty’s unit tests might help catch that kind of breakage.

1.3 is rather ancient, and the API between the JME engine and Nifty has changed between 1.3.1 and 1.3.2 I think, so you’ll have trouble upgrading JME.

Nifty has some architectural problems that will always push it towards fragility (breakage on version upgrades is one of the symptoms). Jens is fighting that fragility, but I suspect it’s a battle that can’t be won.
In that situation, it’s probably best to fix only those Nifty-related problems that really need fixing, and otherwise push just for a “good enough” state - time spent beyond that it probably better spent on improving other parts of the game.
If some Nifty-related problem is both unbearable and unfixable, it’s time to try another GUI library. It means a full rewrite of the GUI stuff though, and no guarantees, so make that an experiment, not a decision.

I’m not entirely sure what the best course of action would be; I’m not sure how harmful having a bunch of textures in memory is, and whether or not there is in fact some way to remove them. Upgrading isn’t a particularly desirable option due to all the rewriting that would be needed, especially if I’m not sure it’ll fix the problem anyway.

Maybe if I remove all the images from the XML file and just create them when the Screen Controller loads? Most of them have their ImageRenderer’s in the controller anyway, because of other things I do with it.

Anyone have any idea if that’d work or not?

Well are you on desktop? is your game desigend to run less than 6 hours straigt? then you can probably ignore the memory leaking.

Well, sooner or later the texture is going to go into GPU memory and stay there, for better or for worse. I don’t really see how delaying the images would prevent the problem, but maybe I didn’t understand what you’re trying.

A 1000x1000 pixel RGBA texture would be 1000x1000x4 = 4,000,000 bytes = ca. 4 MB.
Given that even low-end graphics cards tend to have at least 1 GB RAM nowadays, I wouldn’t worry too much about that unless I had plans for hundreds of megapixel textures. This might be different if you’re targetting Android - but there you wouldn’t use megapixel textures since you’re coding for a smaller screen.

Newer Nifty versions (1.3.3 or 1.3.4 I think) have been mentioned to use a single large GPU texture, reloading sections with different images as needed. So yes that would be supposed to fix your problems - whether it really does I can’t say.

@Empire Phoenix: Yeah, I’m on desktop. It’s not designed to run for more than 6 hours straight, but I certainly wouldn’t want to deny anyone the ability. I don’t think it’s a problem until I add more textures (which will happen pretty much any time a match or new menu is loaded…).

@toolforger: What I meant was that if I don’t actually create the textures in the XML file, but instead in a bunch of NiftyImage objects that it displays, would you think setting those to null would remove the image when normal garbage collection happens, because nothing’s referencing it? I’d test it, but I won’t have time for the next couple days, I think. Alternatively, I could try using that TextureAtlas class in JME, maybe. I’m just not sure how people handled this back before Nifty 1.3.3, because this couldn’t possibly be the first time this was encountered (then again, maybe they could just ignore it, I’m not sure).

The latest version of jME3 does support a “dispose” method on textures, assuming that you created the texture object and control where its used, then you can call it safely.

Nifty can detect when certain textures are not used and tell jME3 that it no longer needs them, but we cannot really take advantage of that information because the texture cache in jME3 is shared with the user and nifty, so even if nifty might not be using that texture does not mean the user isn’t using it, we do not have the right to dispose it from memory.

I’m guessing you can’t access the texture cache in JME (at least in RC2)?

You can, but its somewhat hidden away. You have the cast the AssetManager into DesktopAssetManager and then you have cache related methods such as
http://hub.jmonkeyengine.org/javadoc/com/jme3/asset/DesktopAssetManager.html#deleteFromCache(com.jme3.asset.AssetKey)

@Momoko_Fan: So the relevant texture information should all be in there, right? Would it be safe to clear it between screens, or would that end up breaking other stuff (assuming using clear() works like I think it does)?

Or is it best to not touch that much?

@Inferno630 said: @Momoko_Fan: So the relevant texture information should all be in there, right? Would it be safe to clear it between screens, or would that end up breaking other stuff (assuming using clear() works like I think it does)?

Or is it best to not touch that much?


That would clear everything, including models. I wouldn’t recommend it.

@Momoko_Fan: Ah, alright. But it just clears the models that are currently loaded, right? So I could theoretically call it on an onEndScreen(), and as long as nothing’s been instantiated, it shouldn’t have much of an effect, should it?

If that works, it’d probably just be a last-resort option, most likely.

Or is there some way to retrieve/create the AssetKey from/for any given texture and just remove it one-by-one? Would it be as simple as creating a new AssetKey object with the filename/path in the constructor and removing it from the DesktopAssetManager’s cache?

You can probably create your own nifty resource locator that would be able to track which textures are used and clear them as needed. You can get the key from a texture using getKey()

@Momoko_Fan: I have a feeling I’m going about this the wrong way. I tried clearing the cache directly just to see if it did anything, and it doesn’t appear that it has. I have no idea where the images are even being sent into the OpenGL memory in the first place, which means I have no chance of finding out where (or how many places) to remove them from.

So I’m also not sure how I would make my own Nifty Resource Locator, seeing as the main systems that JME and Nifty are built on don’t seem to have much of a connection at any point (Nifty uses NiftyImages and JME uses a variety of Image/Texture objects). I don’t quite have the know-how to pull off something like that.

Do you happen to know where stuff is actually being pushed into OpenGL memory? If I knew that, I might be able to go from the source to a way of changing it…

Sorry for the double-post, but I might have found a solution.

It seems like calling the code [java]app.getRenderer().resetGLObjects();[/java] causes the old stuff to go away. However, I’m not sure if it’ll work as intended when actual objects get involved or not. I don’t have the time to check at the moment, so if anyone could verify, I’d be highly appreciative.

@Inferno630 said: Sorry for the double-post, but I might have found a solution.

It seems like calling the code [java]app.getRenderer().resetGLObjects();[/java] causes the old stuff to go away. However, I’m not sure if it’ll work as intended when actual objects get involved or not. I don’t have the time to check at the moment, so if anyone could verify, I’d be highly appreciative.


That actually leaks everything by removing references to it… Something slightly closer to what you’re looking for is Renererer.cleanup() which does everything resetGLObjects() except it also deletes them from VRAM.

Anyway, the proper ways as mentioned before are to clear the cache and calling dispose() on any native objects that are no longer needed.

Well, given that I’m not sure how to access all the individual dispose methods (and I’ve tried disposing a NiftyImage from the built in method, but it did nothing). I’d assume you mean the JME’s texture-y part of it, but I’m not really sure how to get at it to remove it individually.

Wouldn’t removing references to something cause Java’s garbage collection to dispose of it? (this is more a curiosity question)

But running cleanup() shouldn’t straight-out break anything, should it, even though it’s not the proper way of doing things? I know I should probably make an effort to do it properly, but given my failure to understand relatively simple graphics concepts (I don’t quite have the experience), using the quick-and-dirty burn-it-all method might be better, for the time being, that is (provided it isn’t “wrong,” in the sense that it doesn’t achieve what I need).

Or were you saying you clear it from the cache, and then dispose everything afterwards? I guess I’m not quite clear on what the dispose() methods do…