PDA

View Full Version : Use the Program or bind the FrameBuffer first?



emanuele3d
05-20-2015, 02:47 PM
I seem to remember reading somewhere that there is a difference in performance when calling glUseProgram() before or after binding a FrameBuffer. That is, I seem to remember that if glUseProgam() is used after the FrameBuffer is bound the FrameBuffer needs to be re-validated, as it had been validated alreading at binding time. This would suggest that glUseProgram() needs to be used -before- the FrameBuffer is bound so that the FrameBuffer is validated only once.

Can anybody confirm and ideally provide a link to the relevant literature?

Kind regards,

Manu

Osbios
05-22-2015, 07:15 AM
Well, drivers cache a lot of the commands before they actually do anything.
Changing the FBO normally is the most expensive action. And then you often switch between many shaders during rendering to that one FBO. Which would make your "optimization" kind of pointless anyway.
I would expect to see no difference at all.

emanuele3d
05-22-2015, 02:02 PM
Thank you for your reply Osbios.

I'm currently refactoring some OpenGL 2.1 legacy code that I have not originally authored and the original author has moved on. In this context a number of rendering passes follow the pattern "bind an FBO, enable the shader" or viceversa. Differently from the scenario you portray, the code I'm dealing with has somewhere between 15 and 20 FBOs and most post-processing passes (i.e. light shafts, tone mapping, bloom filter, depth of field...) all have their own shader and their own FBO.

As you say binding the FBO is the most expensive operation, and I've read elsewhere this is due to the FBO being validated for completeness every time it is bound. But I also seem to remember that enabling a shader via glUseProgram also triggers the current FBO to be re-validated. If this is the case (perhaps I just dreamed about it!) perhaps it's appropriate to first enable the shader and then bind the FBO. That been said, I guess there's always an FBO bound at any given time, i.e. the default framebuffer, so I guess if glUseProgram does trigger a revalidation it always will, no matter where I put it.

Can anybody confirm?

Alfonse Reinheart
05-22-2015, 03:03 PM
Thank you for your reply Osbios.

I'm currently refactoring some OpenGL 2.1 legacy code that I have not originally authored and the original author has moved on. In this context a number of rendering passes follow the pattern "bind an FBO, enable the shader" or viceversa. Differently from the scenario you portray, the code I'm dealing with has somewhere between 15 and 20 FBOs and most post-processing passes (i.e. light shafts, tone mapping, bloom filter, depth of field...) all have their own shader and their own FBO.

If you have between ~20 FBO binds, but also only ~20 shaders, then it's probably not going to be a problem. Or rather, the cost of changing FBOs that often will dwarf the added cost of also changing shaders.

That being said, you could probably consolidate some of those changes, using different images in the same framebuffer via glDrawBuffers. Of course, whether that would improve speed or not is something you'd have to profile.

Changing shader state isn't cheap, but it isn't as expensive as FBO changes.


As you say binding the FBO is the most expensive operation, and I've read elsewhere this is due to the FBO being validated for completeness every time it is bound.

Really, framebuffer completeness is the least of the issues with framebuffer binding. It's more about how the GPU has to clear all of its caches, swap a bunch of memory pointers, stall the rendering pipeline (so that the old stuff is finished processing), and so forth.

Framebuffer completeness is a drop in the bucket compared to that.

Also, completeness checking can be done ahead of time; it is a property of the framebuffer itself and is unaffected by other state. So unless the FBO's state is changed, it will always be complete, so there's no need to check it.

emanuele3d
05-22-2015, 03:35 PM
That being said, you could probably consolidate some of those changes, using different images in the same framebuffer via glDrawBuffers.


I've considered it. Most FBOs have different image sizes, which is why the original author of the code used so many FBOs. I seem to understand modern OpenGL versions have relaxed the need for FBO attachments of the same size, but the project I'm working on is still OpenGL 2.1 and in that context I'd be able to reduce the number of FBOs by only a little. I might eventually head that way nevertheless.



Really, framebuffer completeness is the least of the issues with framebuffer binding. It's more about how the GPU has to clear all of its caches, swap a bunch of memory pointers, stall the rendering pipeline (so that the old stuff is finished processing), and so forth. Framebuffer completeness is a drop in the bucket compared to that.
Thank you for clarifying this. Where can one get more information on these issues? I've gone through a number of OpenGL books but there was little in terms of costs of operations and performance tips.