TextureManager out of memory

I have a loop that creates Quads, assigns a texture to it, then positions the Quad. The textures are 24 Bit 1024x758 PNGs. After 20 runs thru the loop, it appears that the TextureManager runs out of memory. Backing off to less than 20 tiles displays the scene as desired. Is there some sort of TextureManager initialization that I’m missing?



Following is the code & the error received.



Thanks.



Lynn



for(int j = 0; j < 17; j++)

{

for(int i = 0; i < 12; i++)

{



String s1 = “000” + (int)(i + (12 * j));

String s2 = s1.substring(s1.length() - 4, s1.length());

System.err.println(“Loading Tile: " + s2);



TextureState ts = display.getRenderer().getTextureState();

Texture tx = TextureManager.loadTexture(

“/WorkArea2/PSABTiles/PSABTile”+s2+”.png",

Texture.MM_LINEAR_LINEAR,

Texture.FM_LINEAR,

false);



ts.setEnabled(true);

ts.setTexture(tx);



Quad quad1 = new Quad(“Quad”+s2,50000,50000);



quad1.setLocalTranslation(new Vector3f((float)50000j,-(float)50000i,0.0f));

quad1.setRenderState(ts);

scene.attachChild(quad1);

}

}







May 18, 2004 8:35:48 AM com.jme.scene.Node attachChild

INFO: Child (Quad0020) attached to this node (Scene Node)

Loading Tile: 0021

java.lang.OutOfMemoryError

at java.nio.Bits.reserveMemory(Bits.java:618)

at java.nio.DirectByteBuffer.(DirectByteBuffer.java:95)

at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:285)

at com.jme.util.TextureManager.loadImage(Unknown Source)

at com.jme.util.TextureManager.loadTexture(Unknown Source)

at com.jme.util.TextureManager.loadTexture(Unknown Source)

at com.jme.util.TextureManager.loadTexture(Unknown Source)

at ZSMissionOverview.ZSMOMainScene.init(ZSMOMainScene.java:180)

at ZSMissionOverview.ZSMOFrame.(ZSMOFrame.java:89)

at ZSMissionOverview.ZSMO.initGame(ZSMO.java:97)

at com.jme.app.BaseGame.start(Unknown Source)

at ZSMissionOverview.ZSMO.main(ZSMO.java:40)

May 18, 2004 8:35:49 AM com.jme.app.BaseGame start

INFO: Application ending.

What is the file size of those PNGs? Are they in the megs?



TextureManager creates a Texture object for each texture you load.



The Texture contains:



An Image

and about 25 ints with texture settings (mipmap mode, etc).



Image contains:

3 ints (type, width, height)

the data (in byte buffer)



so you’ll have about 28 ints and the image data for each texture. So the ints add 112 bytes per texture overhead. Which doesn’t seem too bad.



I’m curious to know the size of the pngs you are loading.

Loading JPEGs ranging from size 60k to 110k causes the same error at the same tile (21).

If you are trying to make tiles, there is already an app on the app page that already does that for you. 2500 tiles is no problem.

Looks like this is a bug with Java 1.4.2 NIO



java -XX:MaxDirectMemorySize=1024m ZSMissionOverview.ZSMO



Seems to get me past the OutOfMemory Error



http://forum.java.sun.com/thread.jsp?forum=4&thread=433702&message=1944789

Interesting, thanks for the link Lynnt7. What version of 1.4.2 are you using? I’m using 1.4.2_02, and haven’t seen the issue yet. (I’m also using 1.5 beta with no problems). Perhaps they fixed it fairly quickly?

I still get the same OutOfMemoryEror and require the command line option when using version:



1.4.2_04-b05



This version of java resolved some other issues I was having - so it was definitely worth upgrading.

Could you post a test case that it’s occuring with? I’d like to do what we can to help (make sure we are using as little memory as possilbe, etc).

I was able to duplicate the error with the following program where PSABTile0001.jpg is a 76kb file. The program runs without error when using the 7k star.png.





import java.io.;

import java.net.
;

import java.util.;



import com.jme.app.
;

import com.jme.renderer.;

import com.jme.system.
;

import com.jme.scene.shape.;

import com.jme.scene.model.ase.
;

import com.jme.scene.model.msascii.;

import com.jme.scene.
;

import com.jme.scene.state.;

import com.jme.input.
;

import com.jme.math.;

import com.jme.light.
;

import com.jme.image.;

import com.jme.util.TextureManager;

import com.jme.util.Timer;

public class TestCase extends BaseGame

{



private Camera cam ;

private Node scene;

private InputHandler input;

private Timer timer;

private CameraNode camNode;





public static void main(String [ ] args)

{

TestCase app = new TestCase();

app.setDialogBehaviour(ALWAYS_SHOW_PROPS_DIALOG);

app.start();

}



protected void update(float interpolation)

{

timer.update();

input.update(timer.getTimePerFrame());

}



protected void quit()

{

super.quit();

}



protected void render(float interpolation)

{

display.getRenderer().clearBuffers();

display.getRenderer().draw(scene);

}



protected void initSystem()

{

try {

display = DisplaySystem.getDisplaySystem(properties.getRenderer());

display.createWindow(

properties.getWidth(),

properties.getHeight(),

properties.getDepth(),

properties.getFreq(),

properties.getFullscreen());

cam =

display.getRenderer().getCamera(

properties.getWidth(),

properties.getHeight());



} catch (JmeException e) {

e.printStackTrace();

System.exit(1);

}

ColorRGBA blackColor = new ColorRGBA(0, 0, 0, 1);

display.getRenderer().setBackgroundColor(blackColor);

cam.setFrustum(1.0f, 1000.0f, -0.55f, 0.55f, 0.4125f, -0.4125f);



display.getRenderer().setCamera(cam);



camNode = new CameraNode("Camera Node", cam);

camNode.setLocalTranslation(new Vector3f(0, 0, -100));

camNode.updateWorldData(0);

input = new NodeHandler(this, camNode, "LWJGL");

input.setKeySpeed(100f);

input.setMouseSpeed(1f);

display.setTitle("Test Case");

display.getRenderer().enableStatistics(true);

timer = Timer.getTimer(properties.getRenderer());

}



protected void initGame()

{

scene = new Node("TestCase");

for(int j = 0; j < 4; j++)

{

for(int i = 0; i < 12; i++)

{

String s1 = "000" + (int)(i + (12 * j));

String s2 = s1.substring(s1.length() - 4, s1.length());

System.err.println("Loading Tile: " + s2);



TextureState ts = display.getRenderer().getTextureState();

Texture tx = TextureManager.loadTexture(

"/WorkArea2/PSABTiles/PSABTile0001.jpg",

//"…/…/textures/star.png",

Texture.MM_LINEAR_LINEAR,

Texture.FM_LINEAR,

false);



ts.setEnabled(true);

ts.setTexture(tx);



Quad quad0 = new Quad("Quad"+s2,50000,50000);



quad0.setLocalTranslation(new Vector3f((float)50000
j,-(float)50000*i,0.0f));

quad0.setRenderState(ts);





scene.attachChild(quad0);

}

}



}

protected void reinit()

{

}

protected void cleanup()

{

}

}

I tried running your test with a 93KB image (Monkey.png) and did not get the issue… It gets to tile 00047 and then starts the game… everything is white though… No special cmd line args… Then I bumped up the number of tiles and it was able to get to tile 50 before dying with an out of mem issue.



Using some args to allow java to use more memory:



-Xms4000000 -Xmx250000000 -Xss4000000



did not solve the issue… Weird.

An FYI… it’s not the file size in bytes of the image that is killing it… it’s the size in bytes of the image itself in terms of number of pixels – width and height. We store the image contents as a buffer in Texture and if we could get away from doing that, we would greatly allieviate this issue as well as the total memory usage of our apps.