Finding out whether OpenGL objects cannot be deleted due to dangling reference

I have to debug a large OpenGL application with too much memory usage. Cause might be that buffers might not be deleted because their internal reference count is > 1. Is there a way to check the internal reference count of OpenGL objects at glDeleteBuffers?

apitrace doesn’t work for me because it produces tons of errors on my desktop machine.

Regards

That seems like a problem you should fix first. The fastest way to figure out what’s going on is to instrument your use of OpenGL like this, so if you can’t do that because of some other problem, it’s best to fix that other problem.

In any case, there’s usually no reason to actually care about this. Even if the reference count were 0, there is no way to force the implementation to immediately delete the resources behind an object anyway.

Not OpenGL Errors, but random crashes or errors that only occur with apitrace and nothing else.

Problem is the resources are not deleted delayed but apparently never.

There are other tools that can instrument OpenGL.

How do you know that?

There is a debug log by the driver manufacturer that shows ever increasing vram usage despite glDeleteBuffers. My only explanation is that the internal ressources are not removed due to still existing references.

The OpenGL specification says nothing that guarantees memory will be released at any time. Your implementation is free to keep memory allocated permanently so that it can more quickly satisfy future requests, particularly if it’s internal heuristics determine that you’re creating and deleting a lot of GL objects at runtime.

From your initial description and further discussion, it sounds like creating and deleting resources at runtime is exactly what you’re doing, and your problem isn’t that your OpenGL implementation isn’t freeing memory, your problem is that your program is leaking like a sieve.

I cannot rule out that the program is leaking but I cannot see a deficit in glDeleteBuffers calls at the moment. I can observe several calls to glDeleteBuffers that should free at least 30 MBs worth of VRAM but the consumed VRAM doesn’t go down. So my assumption is that something else is keeping the memory from getting freed and to be sure I want to know the reference count of the buffers.

There are other possible explanations.

What GPU and GPU driver is this?

Why I ask:

If memory serves, you’re porting an OpenGL ES engine to Vulkan. In OpenGL ES (and likely OpenGL), one of the things the driver does to avoid synchronization and maximize throughput is “ghost” textures and possibly buffer objects as well, depending on the driver (see links below for related reading).

This can, for example, happen when uploading new texel contents for a GPU texture from the CPU draw thread. If there is still a draw in the pipeline which will need to read from the old texture contents before your update, the driver has a choice:

  • block your CPU app until the GPU/driver catches up,
  • serialize the texels into the command-buffer (if supported) and update the texture later, or
  • ghost the texture (aka “resource renaming” aka “multibuffering”).

I know for sure that some OpenGL ES drivers on mobile do this, and I’d be surprised if desktop drivers didn’t do it too. The thing with mobile is though, the GPU RAM sizes are much smaller typically and the access speed is much lower. So it’s much easier to blow out all of your memory with the GPU driver ghosting textures all over the place that you didn’t know about. I’ve done this myself, and at the time I recall being completely surprised initially at what was really going on under-the-covers in the driver. But when you stop and think about it, it makes perfect sense why it happens.

With Vulkan by contrast, the driver washes its hands of all of this ghosting nonsense. If your application wants ghosting/multibuffering behavior for performance, your application has to implement it. And because it knows what’s going on, it can frequently do it much more efficiently.

https://www.imgtec.com/blog/how-to-improve-your-renderer-on-powervr-based-platforms/

This is not about my vulkan port but something entirely different with GLES.

I cannot rule out that the program is leaking but I cannot see a deficit in glDeleteBuffers calls at the moment. I can observe several calls to glDeleteBuffers that should free at least 30 MBs worth of VRAM but the consumed VRAM doesn’t go down. So my assumption is that something else is keeping the memory from getting freed and to be sure I want to know the reference count of the buffers.

Your misunderstanding is that you’re expecting glDeleteBuffers to free VRAM. It doesn’t. All that glDeleteBuffers does is make the buffer object name (i.e. it’s integer handle) available for reuse by a future call to glGenBuffers. There is no OpenGL call for freeing VRAM; your implementation will free it behind-the-scenes when it determines that it’s suitable to do so. Or it may not free it at all if it determines that it’s best to not do so.

There’s a heavily refactored version of the program that doesn’t have these problems so I assumed it isn’t how the driver behaves usually.

I would question that assumption. If it’s heavily refactored, it’s probably using the driver differently.

Anyway, you have several likely guesses here:

  1. Driver memory pooling (big mem blocks alloced by the driver for sub-allocs which aren’t freed until app exit)
  2. Deferred resource deletion (due to resource still in-use)
  3. Buffering space allocated by the driver for internal purposes.

You can gradually pair back your program or selectively disable sections to figure out which, if any of these, is the cause of your problem. That’ll suggest what your options are for dealing with it. Or at least give you a specific questions to ask about here.

You should also consider wrapping the buffer alloc/delete GL calls in your app to see what resources aren’t explicitly freed by the end of your program. With this you can print your own report of what’s out there. This should help point out runaway allocs w/o deletes as well.

Good. That gives you a tool to nail down which part(s) of your program are instigating this behavior.

Questions:

  1. What do you mean by “too much memory usage”? Just evidence of mem growth in driver log? Seeing GL_OUT_OF_MEMORY errors? etc.
  2. Which GPU and GPU driver are you working on?

How do you know this for sure (or do you)?

There is no GL_OUT_OF_MEMORY as of yet. But the VRAM usage keeps growing and in a shared memory environment that’s bad.

I currently make tests where i have to unbind a VBO from a VAO. Is it right that in order to unbind a VBO from a VAO I have to

glBIndVertexArray (myvao );
glBindBuffer ( target, 0);
glVertexAttribPointer ( …, 0 );

?

You say you have to do this, but it’s not clear what you’re doing it for. However, the code you posted is generally the right way to do this, though you should also disable that attribute array.

1 Like

Not sure why you use a variable there; target needs to be GL_ARRAY_BUFFER.

For 4.5+, you can use glBindVertexBuffer or glVertexArrayVertexBuffer to manipulate attribute buffer bindings directly. If you’ve been using glVertexAttribPointer, the mapping between attribute indices and binding indices will be the identity mapping (i.e. attribute i maps to binding point i).

You don’t need GL 4.5 to do that. glBindVertexBuffer comes from GL 4.3.