OpenGL Texture Memory and Nifty

You should probably better try to find out whats hodling the referneces with stuff like jvisualvm, wich can show (when configured to do so) object allocation traces for every instance of everything. SO you cna see where the textures are created from, and if indeed they are leaking or just no collected cause you still have enough ram from the jvm opinion

1 Like
@Inferno630 said: 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.
RenderImageJme has a getTexture() method: http://hub.jmonkeyengine.org/javadoc/com/jme3/niftygui/RenderImageJme.html#getTexture%28%29
@Inferno630 said: Wouldn't removing references to something cause Java's garbage collection to dispose of it? (this is more a curiosity question)
Ideally yes, however the garbage collector is collecting lazily rather than eagerly, so objects will remain in memory much longer than they should. In hindsight, jME3 shouldn't have used the garbage collector for this, instead using an LRU cache would have been easier and more reliable.
@Inferno630 said: 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).
Try it and see if it solves your problems... It does the same thing as Renderer.resetGLObjects() but it also deletes them from VRAM - so it should be safe to call at any point. It will of course, flush down all the models, shaders, etc and so it may take significant time to upload them back to VRAM.
@Momoko_Fan said: In hindsight, jME3 shouldn't have used the garbage collector for this, instead using an LRU cache would have been easier and more reliable.

You’d still want to use GC to make sure that any unreachable GPU resources get freed.

One could add an LRU algorithm on top of that. Kill the least recently used GPU resources when a resource upload would exceed the limit. Keep track of the swapped-out resources and re-upload them on their next use (possibly causing some other resource to be killed).
You’d want a line in the StatsView to see when excessive resource swapping happens. So it’s not really that much easier, the number of failure modes that the developer needs to be aware of stays the same - hard fail for overcommit now, thrashing and bad framerates for overcommit with LRU.
The saving grace of an LRU algorithm is that it will make the programs hit the limit later in those cases where the overcommit is just a late-GC artefact; I don’t know whether that it worth it or not, I haven’t yet read anyboy complaining about that.

@Momoko_Fan: Ohh, so I’d make the NiftyImage using the actual constructor, using RenderImageJme. Then, when I want to get rid of it, I’d call the object’s getTexture() method, get that’s key with getKey(), then remove it from the DesktopAssetManager’s cache. Then I’d call the dispose() method on the texture? Is that the right flow, or am I missing something?

Right now I just create NiftyImages either in the XML, or using the nifty.createImage() method.

Although, the renderer cleanup method seems to be working as desired for what I’m working on now. It would be useful to know the correct way to do it properly in case I need to remove some things and not others later (like if there’s a larger level or something).

It would be easier to just fix the issue, instead of trying to work around it…

Nifty already uses the dispose() method, so jME3 just has to implement it properly. Easiest way is to use a custom subclass of TextureKey whose equals/hashCode methods do not equate with regular TextureKeys. That way only nifty will be the one owning those textures, hence they could be safely disposed of in the nifty dispose method.

But isn’t the TextureKey stuff created by the objects in question? Like if I make an image, it has a TextureKey, which wouldn’t be my special version of it, would it?

Sorry, I’m really just not sure what would need to be done exactly… :confused: (although I’m sure you’re spelling it out pretty well, I’m just not catching on…)

@Inferno630 said: But isn't the TextureKey stuff created by the objects in question? Like if I make an image, it has a TextureKey, which wouldn't be my special version of it, would it?

Sorry, I’m really just not sure what would need to be done exactly… :confused: (although I’m sure you’re spelling it out pretty well, I’m just not catching on…)

a) he’s talking about a fix internal to the Nifty/JME layer, I think.

b) TextureKey is used to lookup textures. It’s created before the “object” because it’s used to find and load the “object”.

@pspeed: But if it’s internal, can’t I not really do anything about it without modifying the source code?

I guess I thought the TextureKey was an attribute of a Texture. Although that doesn’t really make sense, I suppose.

@Inferno630 said: @pspeed: But if it's internal, can't I not really do anything about it without modifying the source code?

I guess I thought the TextureKey was an attribute of a Texture. Although that doesn’t really make sense, I suppose.

It is because you can get the asset key after the texture has been looked up. Put another way, I can get a file name from a File object after I have the File object… but I still needed the name to get the file object in the first place.

Correct… you cannot really do anything about it until is is fixed in JME. That’s what I believe he was saying. Though I don’t know which core dev is in a position to fix it right now. (not me)

@pspeed: Okay, I think that makes sense. You need to get the TextureKey to get the Texture, you need the Texture to get the AssetKey.

So I guess if that’s the case, I’ll need to make due with the renderer.cleanup() method, because that’s my only real option (and it seems to work, even if it’s not the best way of doing things).

Thanks for all the help, everyone.

The AssetKey is the TextureKey is the AssetKey… but, yes.

@pspeed: Wait, the AssetKey and the TextureKey are the same thing?

http://hub.jmonkeyengine.org/javadoc/com/jme3/asset/AssetKey.html
http://hub.jmonkeyengine.org/javadoc/com/jme3/asset/TextureKey.html

TextureKey is a subclass of AssetKey, so every TextureKey is an AssetKey.

Okay, so it goes like this: Use assetManager.loadTexture("[filepath]"), then cast that Texture into a Texture2D, create a RenderImageJme from that, create a NiftyImage from that, and lastly use that in the Nifty ImageRenderer?

Then, when you want to delete the texture, you get the initial Texture’s Key, dispose everything with their methods, and remove it from the cache?

Or is that just overcomplicating what needs to be done. Sorry, I’m not sure what it is, but I just don’t seem to be catching on… :confused:

Just a note: assetManager.loadTexture(“[filepath]“)
…internally is creating a TextureKey and calling loadTexture(textureKey)

The fix mentioned above (if I followed it correctly) involves modifying the JME-nifty layer to use a different asset key to load the texture. Probably a subclass of TextureKey I guess. This means that if the app loads the same texture then it will be using its own non-nifty-specific key. Meanwhile, the nifty layer is loading its own copy of the texture since it is using a different key than the application would.

That way if nifty disposed of the texture using its key it won’t cause the app (or OS) to crash if the app is also using that texture.

Ah. Well the more I see, the more I think that my only realistic option is wiping the slate every once in a while, so to speak. Good to know, I suppose.

What is your texture memory usage, anyway?
Having less texture memory is annoying, but breaking Nifty because it doesn’t like textures getting cleaned up or whatever would be worse.