3

When I run my app, OpenGL Driver Monitor says the Textures count is rapidly increasing — within 30 seconds the Textures count increases by about 45,000.

But I haven't been able to find the leak. I've instrumented every glGen*() call to print out every GL object name it returns — but they're all less than 50, so apparently GL objects created by glGen*() aren't being leaked.

It's a large, complex app that renders multiple shaders to multiple FBOs on shared contexts on separate threads, so reducing this to a simple test case isn't practical.

What else, besides glGen*() calls, should I check in order to identify what is leaking?

smokris
  • 11,740
  • 2
  • 39
  • 59

1 Answers1

3

Funny thing, those glGen* (...) functions. All they do is return the first unused name for a particular type of object and reserve the name so that a subsequent call to glGen* (...) does not also give out the name.

Texture objects (and all objects, really) are actually created in OpenGL the first time you bind a name. That is to say, glBindTexture (GL_TEXTURE_2D, 1) is the actual function that creates a texture with the name 1. The interesting thing here is that in many implementations (OpenGL 2.1 or older) you are free to use any random number you want for the name even if it was not acquired through a call to glGenTextures (...) and glBindTexture (...) will still create a texture for that name (provided one does not already exist).

The bottom line is that glGenTextures (...) is not what creates a texture, it only gives you the first unused texture name it finds. I would focus on tracking down all calls to glBindTexture (...) instead, it is likely you are passing uninitialized data as the name.

UPDATE:

As datenwolf points out, if you are using a 3.2+ core context then this behavior does not apply (names must be generated with a matching glGen* (...) call starting with OpenGL 3.0). However, OS X gives you a 2.1 implementation by default.

Community
  • 1
  • 1
Andon M. Coleman
  • 42,359
  • 2
  • 81
  • 106
  • 1
    I just want to throw in, that the above is correct only for OpenGL-2.1 and before. Since OpenGL-3 names *must* be acquired using `glGen…` – datenwolf Nov 27 '13 at 19:16
  • @datenwolf: Indeed, this is OS X though so I felt I had to include that information (with the "many implementations" bit). You can get a 2.1 implementation or a 3.2+ core, and the OP didn't mention which. I'll definitely re-write that though to be more clear. – Andon M. Coleman Nov 27 '13 at 19:23
  • Thanks, @AndonM.Coleman and @datenwolf. I'm using OpenGL 2.1 (since I need to support clients back through Mac OS 10.6) — I didn't realize that version of OpenGL permitted using names that weren't produced by `glGen*()`. _Interesting._ So I instrumented every `glBind*()` call, but every name is a small integer (less than 200) — so the problem doesn't seem to be due to using uninitialized data for names. Any other ideas? – smokris Nov 27 '13 at 21:32
  • @smokris: How about the FBOs? How many of them do you have? GL texture data will continue to persist if you delete the texture while it is still bound to an FBO attachment point. Other than that, I am at a loss for explaining this - it could be something quirky in the driver since you're monitoring the driver itself rather than your application. – Andon M. Coleman Nov 27 '13 at 21:46
  • My current test involves 4 threads. During each render cycle, each thread creates a texture (on a shared context), creates an FBO, renders, and deletes the FBO. Then, all 4 resulting textures are composited onto a window, and the 4 source textures are deleted. – smokris Nov 27 '13 at 22:35
  • @smokris: Yeah, this is prime candidate for objects not deleting properly. Objects are only **fully** deleted when no references to them exist any longer. This gets really tricky when you're dealing with multiple contexts, because ordinarily calling `glDeleteTextures (...)` will implicitly unbind them and this helps to satisfy the no references condition. But if the object is bound in a different context from the one where `glDelete* (...)` was called, it remains bound there. Is there any way you can trace which threads have textures bound versus which thread actually deletes them? – Andon M. Coleman Nov 27 '13 at 22:43
  • There don't seem to be any stale bindings at the time each thread gives up its context. ([Here's the code I used to check.](https://gist.github.com/smokris/7685817)) Hmm. – smokris Nov 28 '13 at 01:14
  • I think I found the leak, but I can't figure out why it's leaking. Continued here: http://stackoverflow.com/questions/20257845/how-to-fully-unbind-a-gl-element-array-buffer – smokris Nov 28 '13 at 04:40