Memory increasing over time

Started by Thibs38, April 21, 2020, 09:46:17

Previous topic - Next topic

Thibs38

Hi everyone, I'm new to OpenGL and LWJGL, I followed a tutorial on youtube about creating a game using LWJGL, but it wasn't very optimized so I decided to tweak some of the features the author created. The problem is (and I'm sure he has the same problem but he is not showing how to fix it) that my RAM usage is increasing over time. I know this is a common issue and I figured out what part of my code was creating memory leakage (I commented stuff until the problem disappeared and finally found the 4-5 lines causing the issue). Here they are: (I'm using JOML for the maths)

public void render(Shader shader,Camera cam) {
		shader.bind();
		
		texture.bind(0);
		
		Matrix4f tile_pos = new Matrix4f().translate(tile.transform.position); //Starts here
		Matrix4f target = new Matrix4f();
		
		cam.getProjection().mul(cam.getScale(),target);
		target.mul(tile_pos);
		
		shader.setUniform("sampler", 0);
		shader.setUniform("projection", target); //Ends here

		model.render();
	}

The game is just a grid of tiles on 2d for now, this is a render method called every frame for each tile. 2 parts are causing the issue, the Matrix stuff and the setUniform stuff.

Matrix stuff:

public Matrix4f getProjection() {
		return projection.translate(position,new Matrix4f());
	}


Here is the code of getProjetion method, projection and scale are matrix4f, position a Vector3f.

Shader Stuff

Fragment Shader:

#version 120

uniform sampler2D sampler;

varying vec2 tex_coords;

void main(){
	gl_FragColor = texture2D(sampler,tex_coords);
}


Vertex Shader:

#version 120

attribute vec3 vertices;
attribute vec2 textures;

varying vec2 tex_coords;

uniform mat4 projection;

void main(){
	tex_coords = textures;
	gl_Position = projection * vec4(vertices,1);
}


And here is my setUniform method:

public void setUniform(String name, int value) {
		int location = glGetUniformLocation(program, name);
		if(location == -1)
			System.err.println("Couldn't find uniform location (int)(check the name?)");
		else
			glUniform1i(location,value);
	}
	
	public void setUniform(String name, Matrix4f value) {
		int location = glGetUniformLocation(program, name);
		FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
		value.get(buffer);
		if(location == -1)
			System.err.println("Couldn't find uniform location (Matrix4f)(check the name?)");
		else
			glUniformMatrix4fv(location,false,buffer);
	}


My question is how should I modify my render method to avoid memory leakage? Thanks for your time

KaiHH

You are not "leaking" memory, but you are asking the memory subsystem of the JVM and the garbage collector to allocate and deallocate lots of off-heap memory every frame, since you are allocating a ByteBuffer(16 bytes) for every single tile. So, the GC has a high memory throughput and prefers to eat up most of the available system's memory first, before trying to keep up with the deallocations of unreferenced memory. And you either profile your memory allocations with a JVM memory profiler or your memory allocations are not inlined and optimized/eliminated.
So, first you should read this: https://blog.lwjgl.org/memory-management-in-lwjgl-3/
and then you should use MemoryStack to allocate the ByteBuffer(16 bytes) to temporarily store the matrix to upload to OpenGL. This will significantly reduce the memory throughput.

Thibs38

Hi, thank's for your quick response, I read the article but I have trouble understanding it. I found another tutorial where MemoryStack is discussed, but I can't really see how I am supposed to use it in my code. They wrote this about a vbo:(https://github.com/LWJGL/lwjgl3-wiki/wiki/1.3.-Memory-FAQ)
int vbo;
try (MemoryStack stack = stackPush()) {
    IntBuffer ip = stack.callocInt(1);
    glGenBuffers(ip);
    vbo = ip.get(0);
} // stack automatically popped, ip memory automatically reclaimed

I'm completely new to memory management, buffers, and openGL, could you give me an example on how to use it, or some other resources please?

KaiHH

Change your setUniform(String, Matrix4f) to:
public void setUniform(String name, Matrix4f value) {
	int location = glGetUniformLocation(program, name);
	try (MemoryStack stack = MemoryStack.stackPush()) {
		if (location == -1)
			System.err.println("Couldn't find uniform location (Matrix4f)(check the name?)");
		else
			glUniformMatrix4fv(location, false, value.get(stack.mallocFloat(16)));
	}
}

Thibs38