Delete Textures

Well assume we have a texture x wich was on a object, but is no longer used, what happens to it?

Will it e cleaned up automatically due to garbage collection, or will it stay in the graficmemory forever? Is there a way to tell opengl to delete it from the buffers?

The textures in the graphics card are replaced as needed, so if you dont display a texture for a while and display others, the old texture will be overwritten in memory. But I don't know about the internal jme/lwjgl reference to the texture… I hope its being garbage collected :slight_smile:

Well more is a bit more aviable so it's not that hard problem, but graficram is usually kinda limited



Is it defined, what happens if you use more/larger textures than fit into the videoram?

Sounds to me like you should write a nice texture stress-test with the different scenarios.



I'm also interested in the result…

Actually this is a bit more complicated than you think… When you upload the texture to the GL, the GL will keep a local copy on system memory and then move it to vram when you actually use the texture on a model. The problem is, jME does not tell the driver when the texture is not used anymore, so even though vram will not have a copy because the texture is not used actively, it will still stay in driver's memory space, hoping that at some point you will use it again. The only way to alleviate this problem for jME1/2 is to manually call TextureState.deleteTextures() to delete the textures from GL. This doesn't apply just to textures, by the way, VBOs, displaylists, and shaders have the same issue and also must be manually deleted this way. This explains why many "dynamic" or "infinite world" games using jME suffer from high memory usage.

However, both jME3 and Ardor3D have fixed this issue and these GL resources are deleted the same time when they are garbage collected on the java side.

Whoops, really? So I was wrong… But from what I experienced, I was using way too big and many textures once and it just ran very slow, not throwing any video errors. I was supposing the performance was dropping because the renderer is copying textures from ram to vram, so I was thinking that vram/ram swapping was happening automatically…



So from what you say, the TextureState.deleteTextures() call frees all vram and then on the next render() jme copies the textures one still uses to vram again?

normen said:

So from what you say, the TextureState.deleteTextures() call frees all vram and then on the next render() jme copies the textures one still uses to vram again?

Like I said, it's not that simple.. TextureState.deleteTextures() only deletes textures that are on that specific texture state. If you want more generalized control, you can use TextureManager.deleteAllTextures (or similar) method, however beware that this will delete all textures, including gui and anything else, and you'll have to reload everything over again. Also, forget about VRAM, technically speaking, you're not even supposed to know it exists since there's no mention of it in any of the GL APIs and the OpenGL implementation might be in software. My explanation is a theoretical one, I am not sure of how the driver/GL handles this exactly but I can guess.
I'll try to explain in more detail, essentially the path the texture takes from being loaded for your model on jME until the video card uses it to draw the model:

Texture object on jME side, it's stored as a direct ByteBuffer

|      (the texture is requested to be drawn by jme application)
V

jME uploads texture to OpenGL/driver. It keeps it locally in CPU/System memory until it's used. Now there are two copies of the texture data lying around, one in Java as a jME texture object and another in OpenGL.

|      (opengl prepares to draw the model on the gpu)
V

OpenGL uploads the texture to the video card, it's stored in VRAM and then used to draw model(s). There are now three copies of the texture data lying around, two in CPU/Sys memory and one in VRAM.



Now assuming at some point your jme application stops using some textures, they are garbage collected on the java side. After a while, OpenGL notices these textures are not being used very often and so it takes them off VRAM. Since jME never told OpenGL these textures are to be deleted, OGL still keeps these textures in it's own share of CPU/System memory waiting for them to be used again. You now have a single copy of these unused textures lying around. Since the application no longer references them, there's no way for them to be deleted. You now have a memory leak.

Informative. Might be good to have a wiki entry on this.



But I don't see a deleteTextures()  method (jme2). Do you mean deleteAll() ?


So if i know like in lightmaps for only one map, that a specific texture is not used, I should delete it from the texturestate with the delete method prior to dereferenzing it? Good to know, since my game already uses a dispose for every object :slight_smile:

I should have said "OpenGL memory space" instead of "vram" but your description was very enlightening, good to know more about the relation of OpenGL and JME in this respect.

I took a quick look at jme3's codebase on how this is implemented,

inside GLObjectManager. A thought I had, which I'm not sure if it is

a good idea yet and just wanted to throw it out and see what you

guys think - would it be better (and less error-prone) to have GLObjects

(e.g. Framebuffer, Texture etc.) add themselves to GLObjectManager

in their constructor? This way you won't have to always manually

make calls like:



objManager.registerForCleanup(fb);



since it is possible to forget and cause a leak.

well when i think about renderstates, I think such stuff is easily forgotten. (Be honest who of you never forgot a updaterenderstate call?)

@rexguo: it won't work. if you notice when the registerForCleanup is called, its when the native object is being allocated. It wouldn't be correct if it were registered if there was no equivalent native object.


since it is possible to forget and cause a leak.

The leak can only be caused if the native object is forgotten, which can only happen after the native object is allocated.

So which methods do delete the textures from OpenGL memory?

I'm sure this would have been proposed before if it would work, but since I have very limited knowledge of OpenGL I'll ask anyway, to perhaps learn some more:

Wouldn't it be possible to put something like


if(getRenderState(StateType.Texture) != null) {
   ((TextureState)getRenderState(StateType.Texture)).deleteAll(true);
}


(As I don't know which methods delete the textures from OpenGL memory, the actual method used here is just an example)

in the finalize method of Spatial?
I'm thinking that would clean up the textures when the Spatial gets garbage collected, no?

As far as I understand you could brutally^^ kill them with the LWJGL commands to do so (I don't know them)



My solution sice it will probably need long untill my game is really playable is simply changing to jme3, wich I find already far superior in terms of post processinga nd materials system.

Oh, well, I'd prefer not being brutal, if possible. :stuck_out_tongue:

I would definitely also switch to JME3 as soon as it has all the functions I need, if it weren't for the requirement of OpenGL 2.0. We're wanting to make our game compatible with earlier OpenGL versions as well (at least that's the plan at the moment), so we'll stick to JME2 for now at least.

That's why I'm hoping JME 2.1 will not be abandoned and that there is a way to avoid this kind of memory leak without going too far into OpenGL commands.

i dont know the requiments, but what about the jogl renderer in jme3?

Hey, sorry to digg out this older post: But i can’t seem to find a way to delete Textures from OpenGL in jme3. Neither TextureState nor TextureManager are available? Are there any JME3 alternatives?

@paulhoepner said: Hey, sorry to digg out this older post: But i can't seem to find a way to delete Textures from OpenGL in jme3. Neither TextureState nor TextureManager are available? Are there any JME3 alternatives?

I guess it depends. Why do you need to delete textures?

@paulhoepner said: Hey, sorry to digg out this older post: But i can't seem to find a way to delete Textures from OpenGL in jme3. Neither TextureState nor TextureManager are available? Are there any JME3 alternatives?
I am not sure exactly what you are looking for but have you tried something like:

[java]
texture.getImage().dispose();
[/java]