LWJGL Forum

Programming => Lightweight Java Gaming Library => Topic started by: rabidsponge on September 13, 2005, 03:04:40

Title: My Memory Leak
Post by: rabidsponge on September 13, 2005, 03:04:40
Here's what's happening in my game:  I'll start my game up and load a level.  This takes up about 40 megs of system memory.  When I exit the level, I call glDeleteTextures on all my textures.  The 40 megs will still be used by my game, but this isn't the problem.  When I load the exact same level, my game will use 50 megs instead of 40.   I'll repeat this process and the memory usage will go up 10 megs every time.  I can completely drain all my system memory by doing this.  (Because of this, I don't think it's a problem with Java garbage collection.  I'd probably throw an OutOfMemoryException long before I drained my system memory).  All the memory will be given back when the game closes.

What I think is happening is that I'm doing something stupid when I load my textures.   I'd really appreciate any help.

here's my texture loading code:


public Texture loadTexture(String name, boolean DXT1, boolean need_bitmask)
{
Texture t = null;

boolean loaded = textureWasLoaded(name);
boolean has_mask =  textureHasBitmask(name);

if(!loaded || (need_bitmask && !has_mask))
{
       IntBuffer image = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asIntBuffer();
       IL.ilGenImages(image);
       IL.ilBindImage(image.get(0));
       int il_handle = image.get(0);
       IL.ilLoadImage(name);
       
           int texture_width = IL.ilGetInteger(IL.IL_IMAGE_WIDTH);
           int texture_height = IL.ilGetInteger(IL.IL_IMAGE_HEIGHT);
           
       if(lowResolutionTextures && !need_bitmask)
       {         ILU.iluScale(IL.ilGetInteger(IL.IL_IMAGE_WIDTH)/2,IL.ilGetInteger(IL.IL_IMAGE_HEIGHT)/2,IL.ilGetInteger(IL.IL_IMAGE_BPP));
       }
       
       ByteBuffer scratch = ByteBuffer.allocateDirect(IL.ilGetInteger(IL.IL_IMAGE_WIDTH) * IL.ilGetInteger(IL.IL_IMAGE_HEIGHT) * 4);
       
       IL.ilCopyPixels(0, 0, 0, IL.ilGetInteger(IL.IL_IMAGE_WIDTH), IL.ilGetInteger(IL.IL_IMAGE_HEIGHT), 1, IL.IL_RGBA, IL.IL_BYTE, scratch);
       
       if(!loaded)
       {
        int texture_pointer = loadIntoGL(scratch,DXT1);
       
        t = new Texture(texture_width, texture_height, name, texture_pointer);
        textureMap.put(name,t);
       }
       else
       {
        t = textureMap.get(name);
       }
       
       if(need_bitmask && !has_mask)
       {
        ByteBuffer bitmask_data = IL.ilGetData();
        boolean bitmask[][] = createBitmask(t.getWidth(),t.getHeight(),bitmask_data);
        t.setBitmask(bitmask);
       }
   
       image.put(0, il_handle);
       IL.ilDeleteImages(image);
       
}
else
{
t = textureMap.get(name);
}

       

return t;
}

//actually loads the texture into openGL, returns the pointer to the texture data
private int loadIntoGL(ByteBuffer scratch, boolean DXT1)
{
       IntBuffer buf = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asIntBuffer();
       GL11.glGenTextures(buf); // Create Texture In OpenGL

       GL11.glBindTexture(GL11.GL_TEXTURE_2D, buf.get(0));
       
       //linear filtering
       GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
       GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
       
       ContextCapabilities cc = GLContext.getCapabilities();
if(cc.GL_EXT_texture_compression_s3tc)
{
if(DXT1)
{
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0,
EXTTextureCompressionS3TC.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
IL.ilGetInteger(IL.IL_IMAGE_WIDTH), IL.ilGetInteger(IL.IL_IMAGE_HEIGHT), 0,
GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, scratch);
}
else
{
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0,
EXTTextureCompressionS3TC.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
IL.ilGetInteger(IL.IL_IMAGE_WIDTH), IL.ilGetInteger(IL.IL_IMAGE_HEIGHT), 0,
GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, scratch);
}

}
else
{
       GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, IL.ilGetInteger(IL.IL_IMAGE_WIDTH),
       IL.ilGetInteger(IL.IL_IMAGE_HEIGHT), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, scratch);
}
       
buf.clear();
return buf.get(0);
}

Title: hmmmmm...
Post by: Fool Running on September 13, 2005, 20:37:12
Looks fine to me...
The only thing that I can see that might do what you are seeing is this:
image.put(0, il_handle)
might need to be:
image.put(0, il_handle).rewind()
But that seems unlikely as I think it throws an exception if this is not the case  :lol:
Maybe someone else has some more insights :wink:
Title: My Memory Leak
Post by: rabidsponge on September 14, 2005, 03:03:22
I found the problem.  My texture loading code is fine.  The problem was that when I put my openGL texture handle integers in an IntBuffer, I wasn't calling the "rewind()" method on the buffer before I passed it to "glDeleteTextures()".

Thanks, I woulnd't have thought of trying that without your post.  :D