Advertisement

Ensuring proper cleanup of GPU memory in OpenGL

Started by May 28, 2017 03:04 AM
6 comments, last by mikev 7 years, 8 months ago

I am wondering what are some good strategies to make sure I am definitely cleaning up all my GPU allocated memory when I exit a level. I plan to allocate/de-allocate on a per-level basis. I am using the OpenGL 4.x C++ API.

My thought was maybe:

1. measure GPU memory,
2. instantiate a level, then delete it
3. measure GPU memory again and verify that its the same amount.

I am not sure if functions exist to even accurately measure GPU memory used by a process.. I see there are some functions that I could use on my NVidia card, such as the one mentioned here: http://www.geeks3d.com/20100531/programming-tips-how-to-know-the-graphics-memory-size-and-usage-in-opengl/
but I think that only operates at the Kilobyte level...

Alternatively, I believe all the GPU memory allocated for my level will be local to my GL Context. So maybe I could delete and re-create the context, but I'd have to do this through SDL and wonder if this would be practical, or good practice to do between levels.

Suggestions and advice are appreciated!

It looks like, in theory, I could use:


    SDL_GL_DeleteContext(mainGLContext);
    mainGLContext = SDL_GL_CreateContext(mainWindow);

Between levels... not sure how common this approach would be...

Advertisement
Assuming that your code is correct and doesn't leak, this will have no benefit and only make your loading screens take longer.

I wrap up every GL function that allocates memory and convert them into my own handles. I can then place these handles into an internal list to keep track of active allocations. Whenever I call a GL function that deletes memory I assert that a matching handle is present in my list and then remove it.

Keep a list of all GL objects allocated for you level, during your level transitions delete all objects from that list - simple as.

How to verify that it actually has been deleted? You can't and you probably shouldn't worry about it.

A GL implementation may have it's own memory management strategies, and deleting a GL object (via a glDelete* call) is only guaranteed to make the object name available for immediate re-use.

If you want absolute control over memory then use Vulkan. Otherwise this is something that nobody worries about in GL.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

It looks like, in theory, I could use:


    SDL_GL_DeleteContext(mainGLContext);
    mainGLContext = SDL_GL_CreateContext(mainWindow);

Between levels... not sure how common this approach would be...

No! ... just ... no ...

It looks like, in theory, I could use:

SDL_GL_DeleteContext(mainGLContext);    mainGLContext = SDL_GL_CreateContext(mainWindow);
Between levels... not sure how common this approach would be...
Destroying and recreating the context is as much of a heavyweight operation as can be, only topped by rebooting the computer. I wouldn't advise doing that.

Keeping track of what objects exist is no magic (in fact, in a correct program it's pretty much a prerequisite that you know, not just about GL objects), so deleting what you no longer need shouldn't really be magic either. There is no verifying that your stuff has been deleted, and no reason why you should need that.
GL does an awful lot of management (and abstraction) for you, and while that's sometimes annoying when you want the bleeding edge, the good thing is that it frees you from worrying about such nitpicks. It also means for example that in the worst case you can just call exit(0) when your game exits. While morally wrong, this will work just fine with OpenGL, the driver will clean up behind you. Try doing that with Vulkan, good luck (on my machine, you do this a couple of times, then the display driver crashes).

So... deleting an object doesn't guarantee that the memory is freed, that's right. Just forget about it. It's somebody else's problem to make it work!

measure GPU memory

OpenGL deliberately doesn't let you do that (though some IHVs have extensions for that). You shouldn't know, nor want to know, how much GPU memory is free. Again, that's both a blessing and a curse, it depends on the situation. Measuring twice and making sure the amount of free memory is the same won't work anyway. That's almost guaranteed to fail.
Advertisement
On the original question, I think that if you capture a frame in Renderdoc with the "ref all initials" option ticked (or something like that), then it will let you view a full list of textures/buffers.
You could capture a frame before loading a level and after quitting that level, and then manually verify these lists are the same in both captures.

Thank you all for your input!

On the original question, I think that if you capture a frame in Renderdoc with the "ref all initials" option ticked (or something like that), then it will let you view a full list of textures/buffers.
You could capture a frame before loading a level and after quitting that level, and then manually verify these lists are the same in both captures.

Yes! Ideas like this are what I'm looking for. On my engine, I have been lazy about memory management on both GPU and CPU (hence a similar post on the general programming forum for C++ cleanup) and I'm paying the price for it now. Trying to make sure I have all my cleanup in place, and looking for a way to check that I have been thorough..

This topic is closed to new replies.

Advertisement