JOGL Textures Hogging Memory

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

JOGL Textures Hogging Memory

JimmyNeutron
Okay, so I'd like to know what the "correct" way to load and use textures is in JOGL. I've seen a number of ways (such as Texture.bind or glGenTextures). I don't know what the correct way to do it is. For what it's worth, I am not using the "modern" OpenGL methods, but the fixed function pipeline (modern was too darn difficult to get working).

Here's the problem: I'm loading textures using AWTTextureIO.newTexture and passing it a BufferedImage. The image is 1080x1080 RGBA. Once I have the Texture, I can do one of two things that I know of:

1. Get that Texture object every frame and use Texture.bind()
2. Use Texture.getTextureObject() to get the int id for this texture.

Regardless of which one I do, Activity Monitor (I'm on a Mac, btw) shows that my program is using about 20 MB of ram for each texture I load. Is this a lot? Aren't textures supposed to stored in the GPU memory? Am I doing something wrong?
Reply | Threaded
Open this post in threaded view
|

Re: JOGL Textures Hogging Memory

gouessej
Administrator
Hi

Please use more accurate titles and don't overreact. No, JOGL textures don't hog memory. I remind you that JOGL is open source, I advise you to spend some time in studying its source code before making peremptory claims on its memory footprint even though you seem to ask some questions. Personally, I would have chosen a less aggressive title like "textures memory footprint".

I advise you to use JVisualVM. It will show you that the image raster of your buffered image probably occupies about (at least) 4 MB. If you use a JPEG image, JOGL simply will use Swing ImageIO under the hood to decode it, it might need to create another buffered image or two and of course it creates a texture data object, then at least 4 * 4 MB in the worst case.

You can reduce memory usage by using compressed textures (elect knows that better than me) or simply by using another image format that JOGL can decode without using Swing ImageIO, for example PNG. You can contribute to the JOGL JPEG decoder, it would drastically reduce your memory usage too. You can use TextureIO instead of AWTTextureIO and avoid passing any buffered image, it will reduce a bit your memory usage. By the way, Swing ImageIO has a kind of cache, you can disable it too, maybe it would make a small difference, look at javax.imageio.ImageIO.setUseCache().

You can use smaller images but it's probably not what you want to do.

Yes, some texture data are stored on the GPU but there are still numerous Java objects that contain the same data elsewhere. I try to store those data only in texture data objects.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: JOGL Textures Hogging Memory

elect
In reply to this post by JimmyNeutron
JimmyNeutron wrote
For what it's worth, I am not using the "modern" OpenGL methods, but the fixed function pipeline (modern was too darn difficult to get working).

What problems are you having? We can help you to get it working

Reply | Threaded
Open this post in threaded view
|

Re: JOGL Textures Hogging Memory

JimmyNeutron
Well, with modern OpenGL, it is difficult to find a decent example of the basics. All the examples I find are either A) Not for Java/JOGL, or B) Include more than just a simple JOGL program. I often end up having to download a few additional Java libraries just to get the example code to run. I don't know, maybe modern OpenGL is JOGL really is that complicated, or maybe the examples just do more than they need to.

Basically, I'm having a hard time getting modern OpenGL working because I can't find a good example of how it's done.

As for the textures, I'm not sure how the BufferedImage could be part of the problem, since the BufferedImage scope is only the image loading method.
Reply | Threaded
Open this post in threaded view
|

Re: JOGL Textures Hogging Memory

gouessej
Administrator
JimmyNeutron wrote
As for the textures, I'm not sure how the BufferedImage could be part of the problem, since the BufferedImage scope is only the image loading method.
Please use JVisualVM instead of "Activity Monitor" and you'll see more precisely the memory footprint of the Java objects on the Java heap (build-in feature) and on the native heap (requires a plugin).

JOGL creates a buffered image:
https://github.com/sgothel/jogl/blob/master/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureWriter.java#L67

You see that JOGL creates a buffered image in a particular case:
https://github.com/sgothel/jogl/blob/master/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureWriter.java#L107

I don't understand what isn't understandable in my previous post. You create a buffered image (~4MB) + JOGL creates a BufferedImage at the beginning of the decoding (~4 MB) + JOGL might create a buffered image in a particular case when decoding the JPEG (~4 MB) + JOGL creates a TextureData object containing the data used to create a texture (~4 MB) and Swing can copy your image in its cache (~4 MB).
If you don't use a buffered image and if you don't use an image format requiring to create a buffered image while decoding, JOGL creates a TextureData object (~4 MB) and that's all.
4 MB < 20 MB What isn't crystal clear in that?
The Swing cache can keep a copy of the buffered image you create beyond its scope. Moreover, the garbage collection takes care of the Java heap, not of the native heap. When a TextureData object is created by (AWT)TextureIO, it creates a direct NIO buffer to store the data used later to create a texture. If you keep a strong reference on this Java object, it won't be garbage collected. If you still have enough available memory on the Java heap, the texture data object won't be garbage collected immediately even though you don't need it and it's the same for the buffered images.

Maybe there is a leak in your source code but anyway, if you use the buffered image only to pass it to AWTTextureIO, why not passing a file or an input stream to TextureIO instead (and preferably not use a JPEG)?

Let me know if something is still unclear.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: JOGL Textures Hogging Memory

JimmyNeutron
Okay, so you're saying that even though I no longer maintain a reference to a Texture object, the VM won't garbage collect it until it's running short of memory? That would certainly explain why the memory footprint stays despite the fact that I have absolutely no reference to the texture object anywhere at all. Thanks for the advice.
Reply | Threaded
Open this post in threaded view
|

Re: JOGL Textures Hogging Memory

elect
In reply to this post by JimmyNeutron
JimmyNeutron wrote
Well, with modern OpenGL, it is difficult to find a decent example of the basics. All the examples I find are either A) Not for Java/JOGL, or B) Include more than just a simple JOGL program. I often end up having to download a few additional Java libraries just to get the example code to run. I don't know, maybe modern OpenGL is JOGL really is that complicated, or maybe the examples just do more than they need to.

Basically, I'm having a hard time getting modern OpenGL working because I can't find a good example of how it's done.

As for the textures, I'm not sure how the BufferedImage could be part of the problem, since the BufferedImage scope is only the image loading method.

I have a couple of projects that might intest you:

- Hello Triangle, a couple of samples using using just jogl without any additional dependency. There is an hello triangle and texture, both in gl3 and gl4

- jogl-samples, it's the jogl porting I made from the original ogl-samples of g-truc, they show almost all the whole opengl world. A couple of additional libraries is needed

- modern jogl examples is the jogl porting of one of the best opengl tutorial out there. Again additional libraries
Reply | Threaded
Open this post in threaded view
|

Re: JOGL Textures Hogging Memory

gouessej
Administrator
In reply to this post by JimmyNeutron
JimmyNeutron wrote
Okay, so you're saying that even though I no longer maintain a reference to a Texture object, the VM won't garbage collect it until it's running short of memory? That would certainly explain why the memory footprint stays despite the fact that I have absolutely no reference to the texture object anywhere at all. Thanks for the advice.
It's the principle of garbage collection in general, there is a latency between disuse and reclaim. Of course, avoiding to maintain a reference on a useless object helps and is necessary to allow the garbage collector to do its job. Maybe you shouldn't worry. I advise you to force the garbage collection in JVisualVM (it's in the JDK) and to look at the memory usage. If you see that it increases despite the forced garbage collections and even though you no longer use some textures or images, then maybe you have an high memory usage or a memory leak. Otherwise, you don't have to worry except if you really want to decrease the memory usage of your software (then use another image format + TextureIO + file / input stream and no buffered images at all).
Julien Gouesse | Personal blog | Website