4

Im learning opengl and wrote a simple program that uses buffer object(colors,positions, normals, element indices) to draw a shape like below. Even with the deleting and unbinding, GPU monitor program shows increasing memory usage after each button click. Memory is only released when I close app. If I click button many times, GPU ram fills to 2GB and starts spilling to host ram. How can I release the resources/buffers properly?

enter image description here

Program flow is like:

 When I click a button, the below program is executed:

 glControl1.MakeCurrent();
 GL.GenBuffers(4,buf)
 GL.BindBuffer(BufferTarget.ArrayBuffer,buf[0])
 GL.BufferData(BufferTarget.ArrayBuffer,......)

 same for buf[1]   buf[2] and buf[3](this one ElementArrayBuffer)
 Console.WriteLine(GL.GetError()); // no error 
 GL.Finish();

 [iteration loop]
 glControl1.MakeCurrent();
 GL.BindBuffer(BufferTarget.ArrayBuffer,buf[0])
 GL.ColorBuffer(....)

 GL.BindBuffer(BufferTarget.ArrayBuffer,buf[1])
 GL.VertexBuffer(....)

 GL.BindBuffer(BufferTarget.ArrayBuffer,buf[2])
 GL.NormalBuffer(....)

 GL.BindBuffer(BufferTarget.ElementArrayBuffer,buf[3])

 GL.EnableClientStates(.....)
 GL.DrawElements(.....) //draws the thing
 GL.DisableClientStates(.....)

 GL.BindBuffer(BufferTarget.ElementArrayBuffer,0) //is this unbinding?
 GL.BindBuffer(BufferTarget.ArrayBuffer,0)
 GL.BindBuffer(BufferTarget.ArrayBuffer,0)
 GL.BindBuffer(BufferTarget.ArrayBuffer,0) 
 GL.Finish();
 [loop end]

 //deleting buffers
 glControl1.MakeCurrent()
 GL.DeleteBuffers(4,buf)
 Console.WriteLine(GL.GetError()); // no error comes
 GL.Finish();
huseyin tugrul buyukisik
  • 11,469
  • 4
  • 45
  • 97

1 Answers1

3

As far as I can tell, you're generating and populating a new buffer when you click, and not deleting them. At the end you only delete the 4 buffers you created LAST.

When you call glGenBuffers it simply generates a new buffer and returns the handle, it does not detect whether a given handle is already in use or something similar. Thus when you give the same handles as you used before, it generates new handles, overwrites the ones you're currently keeping track off, effectively removing any reference to the old buffers. But it does not deallocate those buffers. Thus you continuously populate more memory.

Now, if you want to simply write new data to already existing buffers, you would simply call glBufferSubData. If you want to resize the buffer as well, you call glBufferData, which deletes previous data. But you don't have to generate new buffers, as you already have handles to buffers.

Lupus Ossorum
  • 450
  • 3
  • 16
Invalid
  • 1,870
  • 1
  • 16
  • 22
  • Then genBuffers+deleteBuffers are not as same as new+delete of C++ ? – huseyin tugrul buyukisik Aug 13 '13 at 13:57
  • You could consider them the same. But even in C++ you first have to delete before calling new again. Assigning a new value to a variable which already holds dynamically allocated memory, does NOT deallocate the previous memory, in the same sense that glGenBuffers does NOT deallocate the previous buffers. – Invalid Aug 13 '13 at 14:00
  • 1
    But there is a `deletebuffers` at the end of button1_click method which is executed before the next click event. – huseyin tugrul buyukisik Aug 13 '13 at 14:01
  • "Memory is only released when I close the app", seems rather contradictory? – Invalid Aug 13 '13 at 14:05
  • I was to tell memory usage is not decreasing :) – huseyin tugrul buyukisik Aug 13 '13 at 14:07
  • You wrote "at the end you only delete 4 buffers you created LAST" yes Im deleting them before the new ones created. I feel like Im not thinking right. Im generating only once per click so it should delete only the generated one? – huseyin tugrul buyukisik Aug 13 '13 at 14:09
  • If you are calling glDeleteBuffers properly for each buffer you create, it should deallocate all the memory. The only way it isn't doing that is either because of a driver bug (but I doubt it, as that would be a rather outstanding bug) or a bug in your program, somehow you're passing the wrong data. – Invalid Aug 13 '13 at 14:12
  • Im using WHQL 13.4 on HD7870. Some older drivers were buggy even for msi's benchmark programs. – huseyin tugrul buyukisik Aug 13 '13 at 14:17
  • I don't know about windows software. But if under the hood you're running proper AMD drivers, I doubt the problem is the driver. AMD cards are common modern GPUs with well tested drivers, such a huge bug wouldn't be released in the wild. – Invalid Aug 13 '13 at 14:24
  • Then that must be OpenTK's opengl wrapper. Latest version is from 2010 :( – huseyin tugrul buyukisik Aug 13 '13 at 14:49
  • OpenTK is a thin wrapper around the opengl functionality. Highly unlikely that it is the cause of such a dramatic memory leak. If it hasn't been updated recently, that merely means it isn't supporting newer features in newer versions of opengl. – ToolmakerSteve Oct 02 '15 at 19:24
  • The code looks correct; only explanation I can think of is the `DeleteBuffers` line is never executed, due to some uncaught exception. I would wrap most of that code in `try/catch/finally`, and do `DeleteBuffers` in `finally`. – ToolmakerSteve Oct 02 '15 at 19:30
  • BTW, `BindBuffer` merely assigns the given buffer id to a global variable, for use in following calls such as `BufferData`. `BindBuffer(BufferTarget.ArrayBuffer, 0)` merely clears that global variable, to ensure that any following calls do not accidentally refer to your buffer. You do it three times in a row, but only need to do it once. (Though it is harmless to do that multiple times.) `BindBuffer(..., 0)` has nothing to do with *freeing* memory. Multiple calls to `BufferData` don't leak, because each call frees any previous memory used by that target (once GL is done with drawing). – ToolmakerSteve Oct 02 '15 at 21:34