Problem using same texture alternately with and without mipmaps

Please don’t flame me for posting this in the advanced forum. It’s an esoteric problem, and I haven’t found any references to it by searching here or elsewhere.

I’ve got a large number of (code) objects that might want to upload changing image data to a texture and render it. They all need the same size texture (1024x512). Having each object allocate and use its own texture wastes a lot of graphics memory.

So, they’re now sharing one texture. All’s well if none of them uses mipmaps. However, some objects scale the image down and want to use GL_GENERATE_MIPMAP, and some don’t.

So, I make sure to set GL_GENERATE_MIPMAP to GL_TRUE before creating the texture with glTexImage2D. Then when uploading and rendering the image data, I set GL_GENERATE_MIPMAP to either GL_TRUE or GL_FALSE, and set the GL_TEXTURE_MIN_FILTER correctly based on that. Then I use glTexSubImage2D to upload the data.

I thought this would work fine. Once the mipmaps are generated (by the original glTexImage2D call), I figured I could either use them or not.

Here’s what happens:
If I’ve uploaded to the texture without propagating the image data to the mipmaps, subsequent attempts to generate mipmaps fails completely. I don’t get the new data in the texture at all, and it’s really, really slow. Everything works fine without any mipmap generation at all.

I’m sure I can solve this by using one texture for mipmaps and another for no mipmaps, but I thought it was fine to use the same texture, and I’d like to understand the problem.

This is all on recent nVidia Quadro FX cards using the 84.26 driver.

Do you see any problem with what I’m trying to do?

Thanks,

  • LoopinFool

I personally don’t use GL_GENERATE_MIPMAP for generating mipmaps (surely comes from the fact I use gluBuild2DMipmaps).

Why don’t you change the TexEnv arguments when you don’t need mipmapping ? And best, use one unit enabling mipmapping and another one with mipmapping disabled.

That’s what I would do.

Thanks for the quick response.

By TexEnv, I assume you mean glTexParameter, and that’s exactly what I do, but it’s not working properly.

I will probably end up using a different texture ID for each (mipmapped and not) to work around this problem. But I really don’t like that OpenGL gets into a state where no errors are generated and glTexSubImage2D doesn’t get the image data into the texture, and is extremely slow!

As I said, I’m constantly uploading a new image (real-time video/movie application), so the only thing with enough performance for this is hardware-based GL_GENERATE_MIPMAP generation.

yeah TexParameter…

Other ways would be to use FBO, might be faster, but this won’t avoid the problem you have.

Your premise is invalid:

They all need the same size texture (1024x512). Having each object allocate and use its own texture wastes a lot of graphics memory.
This is false. The quantity of video memory it takes to have a texture object, the overhead per-texture, isn’t that significant. While I wouldn’t suggest trying to have 16,384 separate 32x32 textures, for 1024x512? Sure.

At most, that’s 32 textures fit into one. The overhead of 31 extra textures is negligable.

Perhaps you’re right in general, but in this case I don’t think so.

Once each of these textures gets used, the image data that was uploaded has to be kept around by the graphics driver. Unless I destroy the texture, the driver doesn’t know when I might render again using the same texture data.

I assume you use glTexSubImage2D to replace the whole image, not only part of it. Then I propose using two texture objects (with mipmap and without) to trade memory for speed or recreating the texture with glTexImage2D each time mipmap usage is changed to trade speed for memory.

If you have GL_GENERATE_MIPMAP as TRUE, according to the spec (p176 of 2.0) any changes to the interior region or border should regenerate all the mipmap levels.

**** happens!

Is the internal format of all the images the same?

Internal format of each mipmap level must be consistent to be mipmap complete.

Thanks again everyone for your input. I did have everything set up the right way for it to work.
It turned out to be a driver bug, though the cause was not exactly what I thought.

I checked by always having mipmap generation and filtering enabled. I still had the problem. I then replaced my glCopyTexSubImage2D calls with glTexSubImage2D (slower, but the same usage everywyere). That fixed it.
It turns out that mixing the two TexSubImage2D calls on the same texture combined with GL_GENERATE_MIPMAP(TRUE) causes this problem. After the CopyTexSubImage, the first TexSubImage would take a long time and not copy the image into the texture. If I immediately did another TexSubImage, that one would work normally.

Anyway, it’s fixed in the newer drivers (I checked with 91.36). However, I have to remain compatible with 84.26, so I made the code path that uses CopyTexSubImage use its own private textures, and all the TexSubImage-using objects share their textures. This only costs an extra 2MB in my case.

I also used the instrumented drivers (from NVPerfKit) and verified that using the shared textures does indeed save graphics memory in my application.

Didn’t mean to waste anyone’s time with a driver bug, but I was really scratching my head thinking this should work fine according to the specs. Guess I was right, and nobody else here had run into the same issue before. Hope this helps someone in the future.

  • LoopinFool