PDA

View Full Version : Destroy Mipmaps



hlewin
01-04-2015, 04:12 AM
Hello, I've got a question.

What is the most appropriate way to free the mipmaps of a texture?
For example I've a texture-object that frequently changes and is just occasionally used with a mipmap-filter.
So I generate the mipmaps on demand and want to free the mipmaps of the texture below the base-level after use.
This should transition the texture back to a state as if the mipmaps would never have been initialized.
I see calling TexImage with an appropriate level and zero-dimensions but does this really free all memory? For sure it does not necessarily reset all tex-level paramters.

Thanks in advance
Heiko

Alfonse Reinheart
01-04-2015, 08:29 AM
If you really want to make such a fundamental change in the texture's storage, the only way to do so is to destroy the texture object and create a new one.

That being said, I would strongly advise against trying to do this. The only reason you should care whether a texture has mipmaps that you aren't using is due to memory concerns. And if memory is a concern, then your memory budget should assume the worst-case scenario (ie: that all dynamic textures like this will simultaneously need their mipmaps).

hlewin
01-04-2015, 08:51 AM
Is dropping and allocating a mipmap-level that slow? I'd have guessed copying a texture is more expensive.

Alfonse Reinheart
01-04-2015, 09:18 AM
Since there's no way to "drop" a mipmap level, then I'd say it's a pretty fast process to not call an API that doesn't exist ;)

More importantly, there's ARB_texture_storage (https://www.opengl.org/registry/specs/ARB/texture_storage.txt). That's a (relatively) recent bit of OpenGL functionality that allows you to allocate all of the storage for a texture in one function call (https://www.opengl.org/wiki/Texture_Storage#Immutable_storage), rather than the somewhat ridiculous current notion of allocating each mipmap level separately.

This is relevant because the very existence of this extension (and the issues section of the specification) strongly suggests that IHVs don't want you allocating and deallocating individual mipmaps. They want you allocating the entire thing at once. And since using this functionality also makes the texture's storage immutable (you can upload new data with SubImage calls, but you can't reallocate the storage), this strongly suggests that IHVs see what you want to do as being rather bad. So bad that they have explicitly forbidden it.

For more evidence of this, consider ARB_direct_state_access (https://www.opengl.org/registry/specs/ARB/direct_state_access.txt). There are APIs for allocating mutable storage for buffer objects, but also for immutable storage. That is, DSA supports both mutable and immutable buffer objects.

DSA does not have equivalents to glTexImage. At all.

IHVs clearly don't want you to do this kind of thing. Maybe you should listen to them.


I'd have guessed copying a texture is more expensive.

My point is that you should leave those mipmap levels where they are. Stop trying to deallocate them; that memory will be right there when you want to use those mipmaps again.

hlewin
01-04-2015, 10:00 AM
I'm sorry to say this, but I don't care enough about the IHVs enough to force the potential users of my software to buy a card with GL4+ functionality. Nor with more memory to keep the mipmaps. But this is politics.

Alfonse Reinheart
01-04-2015, 12:08 PM
I'm not sure what that has to do with what I said, since texture_storage functionality is not restricted to 4.x graphics cards. According to GL Viewer's database, it is supported on pretty much all OpenGL 3.x cards. The extension itself is written against GL 3.2, but it is stated to be able to be functional all the way back to GL 1.2.

More importantly... I did not tell you to use ARB_texture_storage. My point in bringing it up is that IHVs know what's fast for their hardware. They designed this API for the sole purporse of preventing users from being able to treat a texture's mipmap levels (and texture storage in general) as optional, disposable, or ephemeral.

And that's advice which is irrespective of hardware versions and so forth. D3D similarly doesn't let you add/drop mipmaps post-creation; with D3D, a texture's allocation has always been immutable. Again, likely at the request of IHVs.

My point being that what you're wanting is not something IHVs want to support. And they don't want to support it probably for very good reasons. So you're going to have to destroy the entire texture and recreate a new one if you want to drop mipmaps.

That's not "politics" of any kind; that's just good API design.

hlewin
01-04-2015, 01:05 PM
So you're going to have to destroy the entire texture and recreate a new one if you want to drop mipmaps.
No, I just call TexImage on every level, although it does not reset the texlevel-parameters and might leave some bytes of overhead per level.


My point being that what you're wanting is not something IHVs want to support. And they don't want to support it probably for very good reasons.
Monopolism? This sounds like it has to do with use-cases for me, so I take your there won't be an API-call for this.

mhagain
01-04-2015, 01:19 PM
Monopolism?

None of the IHVs support what you want. Multiopolism would be more like it.

Frankly, what you're talking about here is micro-optimizing memory usage. Adding miplevels to a texture only adds one third more memory compared to having no miplevels. Are you really using that much memory that this is an issue?

What you're also doing is going to be a performance impact, because destroying and creating resources at runtime is slow. So even if the API did support it, reallocating memory for miplevels as required is going to slow your program down. So you'd be in the hypothetical situation where you've reduced your memory usage by 25% (for a single texture) at the expense of a larger performance loss. Is that something you actually want?

So just create the full mipmap chain and use glTexParameter (or preferably switch sampler objects) to disable mipmapping when you don't need it.

hlewin
01-04-2015, 01:59 PM
Multiopolism would be more like it.
Yes? How naive. I bet there is hardware out there that would be capable of freeing a mipmap-level.


Is that something you actually want?
This depends very much on the setting like how often the mipmap is needed. My guess still is that destroying the mipmap-levels is a lot cheaper than copying the texture. On the other hand the performace hit isn't that dramatic in such settings. But don't come me with "that will be too slow".


So
?


just create the full mipmap chain and use glTexParameter (or preferably switch sampler objects) to disable mipmapping when you don't need it.
I guess I'll leave things as they are.
Thank you.

Osbios
01-05-2015, 08:39 AM
Completely agree with mhagain here.
As long as you are not using resident memory (for bindless textures) the driver will take care of stuff that is not used in case of memory constrains.

You also could use Sparse Textures and have full control over the memory. But that feature won't be available on any drivers/hardware lower then GL4.0.

Alfonse Reinheart
01-05-2015, 09:24 AM
No, I just call TexImage on every level, although it does not reset the texlevel-parameters and might leave some bytes of overhead per level.

OK, let's say you have a 128x128 texture, which has a total of 7 mipmap levels. Now, you want to reallocate it to being a 128x128 with only 1 mipmap level. So you call glTexImage on the base level of 0. Then you call glTexImage on all of the others with... what?

If you think that passing NULL for the pixel data is "destroying" the mipmap in some way... no, that's not how it works (https://www.opengl.org/wiki/Texture_Storage#Direct_creation). If you think passing 0 for the sizes will "destroy" the mipmap, you'd be more likely to be correct. However, absolutely nothing in OpenGL guarantees that the driver will deallocate the old memory. It could simply keep that memory around, since it would be appropriately sized for that mipmap level. And you have to change the minimum mipmap level anyway, since the texture won't be complete if you don't. So the driver would be perfectly justified in just keeping the memory around.


Monopolism?

... I fail to see how the IHV's forbidding a practice that leads to poor performance behavior is considered "monopolism (http://en.wikipedia.org/wiki/Monopoly)". It's not like the IHVs are competing with makers of software; how would they be advantaged in the marketplace by denying software makers an API? Unless that API is a bad idea, of course.

Also, there's more than one IHV, so it would be oligopolism (http://en.wikipedia.org/wiki/Oligopoly) ;)


Yes? How naive. I bet there is hardware out there that would be capable of freeing a mipmap-level.

It's not a question of "could". The fact that ARB_sparse_texture exists proves that drivers can make individual mipmap levels somewhat ephemeral. There's every reason to believe that drivers could allow a function to explicitly deallocate a mipmap level.

The question is more of when, how, and whether it's a good idea. Sparse Textures are a use case that IHVs want to support; yours is not. There's probably a good reason for that.


This depends very much on the setting like how often the mipmap is needed.

Not necessarily. If every time you delete or allocate texture memory, you drop a frame, then it doesn't really matter how often it happens. You lose smoothness whenever the user does whatever he does to cause it to happen.

That's bad.


My guess still is that destroying the mipmap-levels is a lot cheaper than copying the texture.

Or you could just keep the mipmaps around and unused until you need them again.

Like mhagain said, let the driver do its job of paging things into and out of video memory as needed.

hlewin
01-05-2015, 01:53 PM
However, absolutely nothing in OpenGL guarantees that the driver will deallocate the old memory. It could simply keep that memory around, since it would be appropriately sized for that mipmap level.
It could. But since there is no mipmap filter set then, it would be a pretty stubborn procedure to keep the memory.


If every time you delete or allocate texture memory, you drop a frame, then it doesn't really matter how often it happens.
If... Your arguments are beyond good and evil sometimes. If this happened I would simply not free the mipmaps, you see...


The question is more of when, how, and whether it's a good idea. Sparse Textures are a use case that IHVs want to support; yours is not.
You see, passing 0 as texture-dims has been around since when? This is why


Also, there's more than one IHV, so it would be oligopolism
I would call this syndicalism, I'm happy you corrected me, as this is in no ways limited to the IHVs - it is the whole conglomerate of leading software and hardware developers. What to expect? You see there are no API calls for some quite basic tasks. Why? If having a sufficient budget they just aren't needed. Let's say I wanted to implement the sparse-texture thingy. I'd have to read the specs, implement the whole thing, get rid of errors - I'd approximate a few hours of work time. Say I work cheap until release: all in all 50 bucks + taxes. Too much for my taste. This of course is the iron rule of capitalism. And this is why I made that little mistake of calling this monopolism. You know, Karl Marx and Friedrich Engels would already have been proven all too right in their sentence that "monopolism is the necessary and highest form capitalism" if gouvernments wouldn't stay on their half-assed course of trying to prevent monopolies under capitalist rule.
This is always good for a laugh.

mhagain
01-05-2015, 03:22 PM
That's all well and good but I'll just come right out and directly ask the question I hinted at earlier.

Have you actually benchmarked the memory that you're using and determined that this is a problem?
Do you have the numbers to prove it?