GL_EXT_discard_framebuffer

What about adding the following ES extension to desktop GL?

GL_EXT_discard_framebuffer

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?

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.

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).

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:

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

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).

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).

Update on the topic from Graham Sellers:

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.

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).

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. :wink:

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?

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.

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 :slight_smile:

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.

Now if only either EXT_discard_framebuffer or APPLE_object_purgeable was actually available on NV and AMD desktop hardware for PCs.

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.

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.

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:

[ul][li] glBindFramebuffer (framebuffer with discardable attachments)[] draw something here[] glBindFramebuffer (another framebuffer)[*] glTexImage (invalidate attachment textures)[/ul][/li]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:

[ul][li] glObjectPurgeable (mark attachment textures as purgeable)[] glBindFramebuffer (framebuffer with discardable attachments)[] draw something here[*] glBindFramebuffer (another framebuffer)[/ul][/li]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.

D3D11.1 supports similar functionality:

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

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.