My Memory Leak

Started by rabidsponge, September 13, 2005, 03:04:40

Previous topic - Next topic

rabidsponge

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);
	}

Fool Running

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:
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

rabidsponge

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