PDA

View Full Version : GL_EXT_discard_framebuffer



aqnuep
09-08-2011, 11:54 AM
What about adding the following ES extension to desktop GL?

GL_EXT_discard_framebuffer (http://www.khronos.org/registry/gles/extensions/EXT/EXT_discard_framebuffer.txt)

It actually trivially adds the possibility to invalidate the content of framebuffer attachments. This can provide room for some optimizations.
Of course, this feature is more relevant for GPUs on embedded devices that's why it is an OpenGL ES extension, however I think it may provide possibility for optimizations on desktop as well.

What do you think? Is it pointless for desktop GL?

arekkusu
09-08-2011, 03:32 PM
Desktop implementations typically already implement something like this, by saying "the contents of the back buffer become undefined after swap" in their window system-specific layer.

This extension is most relevant to systems like iOS, where the only way to create a drawable is to create an FBO. In typical desktop use cases, if you create an FBO you certainly don't want to discard the contents immediately after rendering, because you will use the results as a texture in the future. It's only in the "use an FBO as the main system drawable" case that this extension is a big performance win.

Some desktop systems (i.e. Apple) also already have other mechanisms (i.e. APPLE_object_purgeable) to allow fine-grained discarding of object contents, which helps performance in memory-pressure situations.

kRogue
09-09-2011, 12:23 AM
Also in the EGL world, there is a bit/property that one sets when getting context (or was it surface) where the contents of the buffer can safely be discarded by the GL implementation at the start of each frame. Generally speaking, in the embedded world, even if the you are NOT doubled buffered this bit should be true (because it saves a read back into the GPU for all tile based renderers such as PowerVR SGX and ARM Mali).

aqnuep
09-09-2011, 01:36 AM
Thanks for the info, I know the main reason was to not have to read back the content of the framebuffer from the GPU's fast memory to the main memory, however was not thinking about double buffering actually makes this extension unnecessary (at least in most cases).

Actually the idea came into my mind after reading one of Eric Lengyel's posts on twitter:


It'd be really nice if OpenGL gave you a way (better than clearing) to indicate that FBO contents can be discarded on buffer swap.

... and actually this is what GL_EXT_discard_framebuffer is for, just maybe only Eric knows what he needed it for.

Alfonse Reinheart
09-09-2011, 02:38 AM
It'd be really nice if OpenGL gave you a way (better than clearing) to indicate that FBO contents can be discarded on buffer swap.

That makes no sense, as FBOs cannot be buffer swapped.

And really, I don't see the point of having an explicit invalidate method for FBOs only. If you're talking about invalidating images, then there should be methods for invaliding images, whether they happen to be part of an FBO or not. Associating it with FBOs makes no sense.

It should just be glTexInvalidate, which can invalidate either the whole image or just a mipmap (note: the latter would not be allowed for immutable textures).

aqnuep
09-09-2011, 03:19 AM
I think he just meant framebuffers when he used the term FBO, even though that's not really correct.

Actually your proposal about image invalidation is even better, however, unfortunately OpenGL does not expose yet the possibility to access the attachments of the default framebuffer (which may be the very last thing that is not supported by OpenGL compared to D3D).

Also, if we are talking about the details of a possible image invalidation command I think invalidating a single level of a texture wouldn't break immutable textures as it invalidates just the content, not the mip level (okay, I know you meant here the very same invalidation mechanism that allows in case of buffer object the reallocation of the buffer, or at least swapping between two or three buffers, as discussed at the buffer_storage topic, however, image invalidation may not necessarily go that far).

aqnuep
09-09-2011, 04:27 AM
Update on the topic from Graham Sellers:


@EricLengyel Call TexImage2D(..., NULL) on attachments. Driver tosses contents but won't reallocate. What are you trying to do?

Xmas
09-09-2011, 05:03 AM
And really, I don't see the point of having an explicit invalidate method for FBOs only. If you're talking about invalidating images, then there should be methods for invaliding images, whether they happen to be part of an FBO or not. Associating it with FBOs makes no sense.
The main purpose of the EXT_discard_framebuffer extension is to avoid unnecessary data copies on tile based renderers, especially writing out depth, stencil, or multisample data to external memory when these buffers will be cleared at the beginning of the next frame anyway.

Invalidating FBO attachments perfectly fits that use case. If you want to discard the contents of a texture you can already do so.

aqnuep
09-09-2011, 05:21 AM
The main purpose of the EXT_discard_framebuffer extension is to avoid unnecessary data copies on tile based renderers, especially writing out depth, stencil, or multisample data to external memory when these buffers will be cleared at the beginning of the next frame anyway.
Yes, we know that, it was already discussed above. The question was just whether there could be any benefits in case of desktop GL. Actually I can image a use case, particularly discarding the content of the depth buffer as in case Hi-Z is in use, storing the contents back to texture memory requires an implicit decompression step (however, using a depth renderbuffer instead a depth texture as attachment may already solve the problem).

Xmas
09-09-2011, 11:26 AM
Yes, we know that, it was already discussed above.
I was just explaining to Alfonse why it makes sense to discard FBO attachments instead of images.


The question was just whether there could be any benefits in case of desktop GL.
Tile based renderers are not limited to OpenGL ES. ;)

Alfonse Reinheart
09-09-2011, 02:15 PM
The main purpose of the EXT_discard_framebuffer extension is to avoid unnecessary data copies on tile based renderers, especially writing out depth, stencil, or multisample data to external memory when these buffers will be cleared at the beginning of the next frame anyway.

I don't care what the purpose of EXT_discard_framebuffer was; my point is that you can achieve the same functionality a better way. A way that allows you to do more than just avoiding unnecessary copies on tile-based renderers, while doing squat on non-TBRs.

Images you frequently upload to can be invalidated, for example. You shouldn't have to stick them in an FBO just to do that.


Tile based renderers are not limited to OpenGL ES.

Really? How much product does PowerVR sell on desktops these days?

Eric Lengyel
09-09-2011, 03:44 PM
My motivation for tweeting about this is related to SLI on desktop systems. I want to be able to tell the driver that I'm never going to use the contents of an FBO rendered during one frame as a texture in any subsequent frame, so don't ever waste time copying it to the other GPUs.

I know that the IHVs tell us to clear the FBOs every frame so the driver can infer that the contents will be replaced and avoid these copies, but I've had problems getting that to work reliably. Also, what if some FBOs aren't rendered to every frame (shadow maps, for example)? It wouldn't be optimal to keep clearing those anyway just so the driver knows not to copy them.

aqnuep
09-09-2011, 04:51 PM
Thanks for the explanation!

Now I would also say that it would be easier for the driver to determine when the contents of the framebuffer should be preserved if we would have something like GL_EXT_discard_framebuffer as I don't see that from driver implementation point of view invalidating the texture would be the most easy way to detect such situations.

Btw, isn't it bothering you that SLI for OpenGL is only available on Quadro cards due to NVIDIA's limitation of exposing the WGL_NV_gpu_affinity extension only on Quadro cards? At least we have GLX/WGL_AMD_gpu_association for linux and Windows for all ATI cards.

... and that goes back to the topic of cross-vendor multi-GPU support in OpenGL core :)

arekkusu
09-09-2011, 09:55 PM
I think APPLE_object_purgeable addresses both Alfonse's and Eric's examples.

Objects dirtied in VRAM (i.e. rendered to) can be marked purgeable. Then, if some event (like a page-out due to memory pressure, or a switch to another renderer aka SLI) occurs, the contents are simply discarded-- don't spend any time shuffling data around that the app will just re-generate next frame anyway.

Same API applies to textures/buffers/renderbuffers.

Eric Lengyel
09-10-2011, 09:08 AM
Now if only either EXT_discard_framebuffer or APPLE_object_purgeable was actually available on NV and AMD desktop hardware for PCs.

Xmas
09-12-2011, 03:50 AM
I don't care what the purpose of EXT_discard_framebuffer was; my point is that you can achieve the same functionality a better way. A way that allows you to do more than just avoiding unnecessary copies on tile-based renderers, while doing squat on non-TBRs.

Images you frequently upload to can be invalidated, for example. You shouldn't have to stick them in an FBO just to do that.
And why is using a NULL pointer for texture image data not enough?

I'd disagree that your suggestion is a better way for the common use case of discarding render targets.

Alfonse Reinheart
09-12-2011, 04:36 AM
And why is using a NULL pointer for texture image data not enough?

glTexStorage. Once you have immutable storage, you may need a way to "reallocate" it without it truly being mutable again.


I'd disagree that your suggestion is a better way for the common use case of discarding render targets.

It's not a "better way" for that use case. It is a better way overall, because you don't clutter the API with these things that are only useful in corner cases. You get the same effect by just invalidating all of the images bound to the buffer. It's slightly less convenient than the "common use case" (though I wonder at how common this would actually be), but it allows it to be much more useful in general.

What you absolutely don't want is to put EXT_discard_framebuffer in, then come along in a year's time and add a texture invalidate function. Because they do the same thing.

aqnuep
09-12-2011, 05:24 AM
What you absolutely don't want is to put EXT_discard_framebuffer in, then come along in a year's time and add a texture invalidate function. Because they do the same thing.

While after all I agree, I think GL_APPLE_object_purgeable could be a good thing to adopt as you can tell the driver up-front that it can discard the content of the object, but invalidation is done later thus the driver must let's just say "look-ahead" in order to be able to always make the right decision in the right time.

Let's just think about the following use case:
glBindFramebuffer (framebuffer with discardable attachments) draw something here glBindFramebuffer (another framebuffer) glTexImage (invalidate attachment textures)
In such a case most probably the image will be already saved back to the texture storage at the point the new framebuffer is bound (just think about the Z-decompression phase of Hi-Z as an example, but color buffer compression is not uncommon either) unless the driver looks ahead and figures out that there is no need for it.

However, with purgeable objects you can do it in the following way:
glObjectPurgeable (mark attachment textures as purgeable) glBindFramebuffer (framebuffer with discardable attachments) draw something here glBindFramebuffer (another framebuffer)
Here the driver will know up-front that the textures could be discarded so there will be no case when the decompression/store operations will take place.

Unfortunately GL_APPLE_object_purgeable is not enough either as far as I remember it defines object purgeability only for buffer objects but it should be extended to handle textures as well.

ScottManDeath
09-14-2011, 06:28 PM
D3D11.1 supports similar functionality:

http://msdn.microsoft.com/en-us/library/hh404562(v=VS.85).aspx#discard_resources_and_resou rce_views

aqnuep
09-15-2011, 05:24 AM
Yes, I've just read the same today. However, that API is no different than the already existing orphaning possibility provided by using glTexImage(..., NULL) or glBufferData(..., NULL).

Anyway, it seems that this topic is definitely one that has to be addressed.

skynet
09-15-2011, 07:57 AM
Yes, I've just read the same today. However, that API is no different than the already existing orphaning possibility provided by using glTexImage(..., NULL) or glBufferData(..., NULL).

Orphaning and marking objects as "purgable" are different concepts.

Orphaning says "I do not need this data anymore, I will never need it again."

Purgable objects are marked as "I don't mind if the driver throws this data away. I will regenerate the data if needed. But if the data can be kept around, fine."

aqnuep
09-15-2011, 08:19 AM
Okay, you're right. There is difference between orphaning and purgeability. However, I meant that both glTexImage(..., NULL) and D3D11.1 are post-actions, while purgeability has the advantage that it tells the information to the driver up-front.

Xmas
09-15-2011, 11:07 AM
(though I wonder at how common this would actually be)
In the vast majority of FBO usage cases you don't need to keep depth/stencil or multisample data around. Discarding the contents of these attachments should become a matter of course.


What you absolutely don't want is to put EXT_discard_framebuffer in, then come along in a year's time and add a texture invalidate function. Because they do the same thing.
If someone were to come up with such a function, you could keep DiscardFramebuffer as a convenience function and define it in terms of the new invalidate functions. No big deal.

By the way, you'd also need invalidate functions for renderbuffers and the default framebuffer.

aqnuep
09-15-2011, 12:10 PM
By the way, you'd also need invalidate functions for renderbuffers and the default framebuffer.

Yes, and we arrived to another thing that I still really miss from OpenGL: having the possibility to use the default framebuffer attachments as textures (btw that's possible in D3D).

Alfonse Reinheart
09-15-2011, 02:03 PM
By the way, you'd also need invalidate functions for renderbuffers and the default framebuffer.

Why would you need one for the default framebuffer? The act of swapping the buffer with a non-copy swap tell the driver that it can be discarded. That's what the non-copy swaps are for.

aqnuep
09-16-2011, 01:35 AM
Why would you need one for the default framebuffer? The act of swapping the buffer with a non-copy swap tell the driver that it can be discarded. That's what the non-copy swaps are for.

But what if you would like to discard only certain attachments? Actually I think it is pretty unlucky that we can handle the default framebuffer only with window system specific functions. It would be great if the default framebuffer would be no different than any other framebuffer object so that we can play around with its attachments.

Alfonse Reinheart
09-16-2011, 02:08 AM
But what if you would like to discard only certain attachments?

There's no such thing as "certain attachments," on the default framebuffer. If you mean "certain images", what does it matter? If you can invalidate textures/renderbuffers, then you don't really care about other default framebuffer parts like GL_AUXi and so forth.

I just don't see the need for having a special API for something so special case, when you can have a general API that covers that special case as well as others.