My OpenGL wrapper is pretty extensive so it's possible I'm missing something very trivial elsewhere. In fact, I'm very strongly inclined towards this, although I've gone over my own code with a pretty fine tooth comb. However, this behavior confounded me for a full day before I finally found the (apparent) root cause and I'm still not convinced why it would occur.
The problem has to do with texture updates via glMapBuffer(). In my case I needed to update two textures side by side - one continuously, one on demand. The former updated properly, the second one behaved in a most peculiar way.
As I tried to update the second texture and use it in two different places (eg rendering two quads with it in slightly different places in my code) I found that one of the calls drew the updated texture while the other one, despite the fact that everything was identical, drew the original texture, no matter what I did.
For the longest time this made absolutely no sense so I decided to dig deep and dismantle my entire texturing pipeline to make sure I wasn't accidentally changing it back, creating a duplicate or whatnot. Everything checked out. Until I compared how I was initializing either of the textures: I was generating the continuous one without any default data; the other one I provided with a default buffer.
Frankly I'm out of ideas as to why one should work as expected and the other should behave so seemingly irrationally, other than suspecting that the driver was quietly restoring the original texture data without me implicitly telling it to do so. Except that it makes no sense for the texture data to be persistent. The PBO update is asynchronous and identical in both cases. Additionally, since I'm still not finished on the driver wrapper, I have a tendency to check each and every GL call for errors and they all pass with flying colors.
Unless I'm blind, this is the only thing the docs have to say about the data pointer for glTexImage2D():
data may be a null pointer. In this case, texture memory is allocated to accommodate a texture of width width and height height. You can then download subtextures to initialize this texture memory. The image is undefined if the user tries to apply an uninitialized portion of the texture image to a primitive.
This specifies nothing about the behavior of a texture with default data.
Is this normal? Was I missing something incredibly trivial all these years and somehow just managed to get lucky with my textures? Or am I just not reading between the lines?
Incidentally, just to be sure I also updated my Nvidia drivers and the behavior is identical on current drivers and drivers from 7 months ago.