Oh, sorry, this is the method in the new iteration that I talked about, that uses 1 single buffer for everything.
The proper OLD version looks like this:
public Mesh(float[] vertexes, int[] indexes)
{
FloatBuffer vertexesBuffer = null;
IntBuffer indexesBuffer = null;
try
{
meshAccessor.acquire();
int vboID;
vaoID = glGenVertexArrays();
vboIDList = new ArrayList<>();
glBindVertexArray(vaoID);
// Vertices VBO generation
vboID = glGenBuffers();
vboIDList.add(vboID);
vertexCount = vertexes.length;
this.vertexSize = vertexSize;
vertexesBuffer = MemoryUtil.memAllocFloat(vertexSize); // !!! Must Be manually freed!
vertexesBuffer.put(vertexes).flip();
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, vertexesBuffer, GL_STATIC_DRAW);
glVertexAttribPointer(0, vertexSize, GL_FLOAT, false, 0, 0);
vertexAttrArrCount++;
// Indices VBO generation
vboID = glGenBuffers();
vboIDList.add(vboID);
indexCount = indexes.length;
indexesBuffer = MemoryUtil.memAllocInt(indexBufferLength); // !!! Must be manually freed!
indexesBuffer.put(indexes).flip();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexesBuffer, GL_STATIC_DRAW);
// unbinding
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
if (vertexesBuffer != null) {
MemoryUtil.memFree(vertexesBuffer); // Freeing vertex buffer
}
if (indexesBuffer != null) {
MemoryUtil.memFree(indexesBuffer); // Freeing indices buffer
}
meshAccessor.release();
}}
So that line wasn't supposed to be there, I forgot to remove it when posting the code.
Just in case, here's the BufferController class that holds that method:
public class BufferController
{
protected static FloatBuffer floatBuffer = MemoryUtil.memAllocFloat(1000000);
protected static IntBuffer intBuffer = MemoryUtil.memAllocInt(1000000);
protected static ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1000000);
public static FloatBuffer getFloatBuffer(float[] array)
{
floatBuffer.clear();
floatBuffer.put(array);
floatBuffer.flip();
// FloatBuffer result = MemoryUtil.memSlice(floatBuffer,0,array.length);
return floatBuffer;
}
public static FloatBuffer getFloatBuffer(int size)
{
floatBuffer.clear();
floatBuffer.put(new float[size]);
floatBuffer.flip();
return floatBuffer;
}
public static IntBuffer getIntBuffer(int[] array)
{
intBuffer.clear();
intBuffer.put(array);
intBuffer.flip();
return intBuffer;
}
public static IntBuffer getIntBuffer(int size)
{
intBuffer.clear();
intBuffer.put(new int[size]);
intBuffer.flip();
return intBuffer;
}
public static ByteBuffer getByteBuffer(byte[] array)
{
byteBuffer.clear();
byteBuffer.put(array);
byteBuffer.flip();
ByteBuffer result = MemoryUtil.memSlice(byteBuffer,0,array.length);
return result;
}
public static ByteBuffer getByteBuffer(int size)
{
byteBuffer.clear();
ByteBuffer result = MemoryUtil.memSlice(byteBuffer,0,size);
return result;
}
}
This was an attemt to prevent java from allocating extra memory for buffers, because at some point we thought that that's the issue. I might revert that change in the future or leave it, because in my mind not processing new allocatuins is faster.
Anyway here's the code that I run currently that uses this class. I should note that the memory behavior is similar in both cases.
public Mesh(float[] vertexes, int[] indexes, int lengthStep, int vertexSize, int vertexLayoutSlot)
{
bufferLengthStep = lengthStep;
try
{
meshAccessor.acquire();
int vboID;
vaoID = glGenVertexArrays();
vboIDList = new ArrayList<>();
glBindVertexArray(vaoID);
// Vertices VBO generation
vboID = glGenBuffers();
vboIDList.add(vboID);
vertexCount = vertexes.length;
this.vertexSize = vertexSize;
vertexBufferLength = calculateBufferLength(vertexCount, vertexSize);
FloatBuffer vertexesBuffer = getFloatBuffer(vertexes);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, vertexesBuffer, GL_STATIC_DRAW);
glVertexAttribPointer(vertexLayoutSlot, vertexSize, GL_FLOAT, false, 0, 0);
vertexAttrArrCount++;
// Indices VBO generation
vboID = glGenBuffers();
vboIDList.add(vboID);
indexCount = indexes.length;
indexBufferLength = calculateBufferLength(indexCount, vertexSize);
IntBuffer indexesBuffer = getIntBuffer(indexes);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexesBuffer, GL_STATIC_DRAW);
// unbinding
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
meshAccessor.release();
}
}
As for memory leak happening elsewhere in java, as I said, I've tested it with everything else enabled BUT the mesh construction. Basically, think of it as having a return statement in the beginning of that method that skips everything here. So everything else in the program works, all the triangulation, array shuffling, data exchange between various threads, etc. No memory leaks occur. But once I return mesh creation - it leaks.
I have an idea today to keep everything in this method but only remove openGL calls. if I don't see any leak, this should mean that the memory gobbling happens somewhere in the native code. Not necessarily LWJGL, but maybe driver.