PDA

View Full Version : Memory leak when using glUniform?



c4ooo123
07-21-2017, 12:02 PM
I have noticed a memory leak in my program, and seems like if i comment out the commented lines in the following code, the leak goes away.

The code goes like this:

groundShader->Use();

int vertexLoc = glGetAttribLocation(groundShader->Program, "InVertex");
int texCoord0Loc = glGetAttribLocation(groundShader->Program, "InTexCoord0");

glActiveTexture(GL_TEXTURE0 + 0);
glBindTexture(GL_TEXTURE_2D, c->AlphaMap->ID);
// glUniform1i(glGetUniformLocation(groundShader->Program, "AlphaMap"), 0);

/*glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_2D, GroundTextures[c->groundTexIDs[0]]);
glUniform1i(glGetUniformLocation(groundShader->Program, "groundRedTex"), 1);

glActiveTexture(GL_TEXTURE0 + 2);
glBindTexture(GL_TEXTURE_2D, GroundTextures[c->groundTexIDs[1]]);
glUniform1i(glGetUniformLocation(groundShader->Program, "groundGreenTex"), 2);

glActiveTexture(GL_TEXTURE0 + 3);
glBindTexture(GL_TEXTURE_2D, GroundTextures[c->groundTexIDs[2]]);
glUniform1i(glGetUniformLocation(groundShader->Program, "groundBlueTex"), 3);

glActiveTexture(GL_TEXTURE0 + 4);
glBindTexture(GL_TEXTURE_2D, GroundTextures[c->groundTexIDs[3]]);
glUniform1i(glGetUniformLocation(groundShader->Program, "groundAlphaTex"), 4);

glEnableVertexAttribArray(vertexLoc);
glEnableVertexAttribArray(texCoord0Loc);

glBindBuffer(GL_ARRAY_BUFFER, c->GroundMesh->VBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, c->GroundMesh->IBO);

glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, GL_FALSE, sizeof(VertexCompound), 0);
glVertexAttribPointer(texCoord0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(VertexCompound), (const void*)(sizeof(float) * 3));

glEnableClientState(GL_VERTEX_ARRAY);

glDrawElements(GL_TRIANGLES, c->GroundMesh->IBOSize, GL_UNSIGNED_INT, 0);

glDisableClientState(GL_VERTEX_ARRAY);

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

glDisableVertexAttribArray(vertexLoc);
glDisableVertexAttribArray(texCoord0Loc);*/

glUseProgram(0);
However as soon as i uncomment the line "glUniform1i(glGetUniformLocation(groundShader->Program, "AlphaMap"), 0);", my program's memory usage slowly creeps up. Am i doing something wrong?
(The code is for a shader that uses alpha-mapping to mix 4 different textures onto a mesh.)

mhagain
07-21-2017, 01:30 PM
A couple of observations.

Firstly, it's common enough for memory usage to gradually increase to a point, then level off and not increase any more. If you haven't run your program long enough to check if this is, in fact, what's happening, then I suggest that you do so and report back.

Secondly, uniform values are per-program state in OpenGL. A consequence of this is that if a uniform value never needs to change (and sampler uniforms are exactly of this type) then you can set them just once after program creation, rather than each frame, and they will survive for ever after, including surviving multiple glUseProgram calls. So doing this will work around your observed leak.

c4ooo123
07-21-2017, 02:24 PM
A couple of observations.

Firstly, it's common enough for memory usage to gradually increase to a point, then level off and not increase any more. If you haven't run your program long enough to check if this is, in fact, what's happening, then I suggest that you do so and report back.

Secondly, uniform values are per-program state in OpenGL. A consequence of this is that if a uniform value never needs to change (and sampler uniforms are exactly of this type) then you can set them just once after program creation, rather than each frame, and they will survive for ever after, including surviving multiple glUseProgram calls. So doing this will work around your observed leak.


Thanks for the reply! :D

Running my program without calling the render function (consisting of the above code), the memory usage flattens out at around 51000 Kb.
How ever with the render function being called, the memory keeps going up without any signs of stopping. I ran it for ten minuts and it reached half a Gb!

Anyways, i could change my program to only set the uniforms once, during startup, but this seems more like avoiding the problem then figuring out what it is. And if i decide to implement lights that move, i would end up having this problem again.

Edit:
Also, why can i not do something like: texture2D(<integer>, texture_coordinate) in my glsl shader? I always bind "AlphaMap" to GL_TEXTURE0 and "groundRedTex" to GL_TEXTURE0+1, so why do i have to use glUniform1i() to tell the shader that i have bounded it?

Cornix
07-21-2017, 02:48 PM
I would suggest stripping your program down bit by bit until you are left with the smallest possible program which still shows the problem. Finding the source of leaks in big development code can be very difficult.

c4ooo123
07-21-2017, 03:14 PM
I would suggest stripping your program down bit by bit until you are left with the smallest possible program which still shows the problem. Finding the source of leaks in big development code can be very difficult.

As i said, the leak does not happen if the render function is never called, so unless some outside code can have an effect, the problem stems from there ;)

Also, i just resized that i cant move the glUniform1i() outside my render function. My world is split into cells/chunks, and each cell has its own alphamap and its own 4 different ground textures that must be bound when that cell is rendered. (the alpha map's red channel tells how strong ground texture #1 should be in a fragment, green tells how strong ground texture #2 should be, and so on: gl_FragColor = (texture2D(groundRedTex, texture_coordinate) * AlphaMapFrag.r + texture2D(groundGreenTex, texture_coordinate) * AlphaMapFrag.g ... etc for all 4). Thus when i render a different cell, i need to bind that cell's alpha map and that cell's four ground textures.

mhagain
07-21-2017, 11:58 PM
The glUniform1i call is nothing to do with which texture is bound. It's used for associating a texture unit with a sampler uniform. So changing the bound texture has no effect on it, and you absolutely can move it outside of your render function.

john_connor
07-22-2017, 01:49 AM
... why can i not do something like: texture2D(<integer>, texture_coordinate) in my glsl shader? I always bind "AlphaMap" to GL_TEXTURE0 and "groundRedTex" to GL_TEXTURE0+1, so why do i have to use glUniform1i() to tell the shader that i have bounded it?

take a look at possible layout qualifiers (https://www.khronos.org/opengl/wiki/Layout_Qualifier_(GLSL)#Binding_points)
you can directly in the shader source specify the texture unit to sample from:
layout(binding = 3) uniform sampler2D mainTexture;

c4ooo123
07-23-2017, 09:19 AM
The glUniform1i call is nothing to do with which texture is bound. It's used for associating a texture unit with a sampler uniform. So changing the bound texture has no effect on it, and you absolutely can move it outside of your render function.

Thanks! I thought you had to set the uniform every time you bound a texture. (Cant use 'layout' becouse opengl 2.1 ):