Jump to content
  • Advertisement
Sign in to follow this  
Prune

Which is faster: binding another shader program or another FBO (diff res)

This topic is 3159 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm wondering whether to organize my loop so that I loop over FBOs (with different resolution) in the outer loop and programs in the inner loop, or the other way around. Which is faster? Changing the bound shader or changing the bound FBO?

Share this post


Link to post
Share on other sites
Advertisement
You can always easily benchmark this yourself by creating an extreme test example, where you have 100+ FBOs and 100+ shaders.

Share this post


Link to post
Share on other sites
Quote:
Original post by Prune
I'm wondering whether to organize my loop so that I loop over FBOs (with different resolution) in the outer loop and programs in the inner loop, or the other way around. Which is faster? Changing the bound shader or changing the bound FBO?


Well, this is a question where it will be hard to get any satisfying answer at all.

So, to help you , try to think about what is more likely in your engine.
A) When you change the FBO, you need to activate an other shader ?
B) When you change the shader, you need to activate an other FBO ?

In my engine I use around 7-10 different render targets in 10-15 passes per frame, in most cases I need to change the shader, when I change the FBO, because I need to render other things (SSAO, lightning pass, geometry pass, blur, tonemapping, final composition, bloom,downsampling,particle pass etc.). There are two FBOs where I need to change the shaders quite frequently, on the other hand there is only one situation where I need to switch the FBO and keep the shader (downsampling).

Additionally FBOs can be reused in a single frame. If you have 18 passes, each pass using 1-4 unique FBOs of near screensize at a resolution of 1900x1080, you will run out of memory.

So, my advice would be to change the FBO in the outer loop and the shaders in the inner.

Share this post


Link to post
Share on other sites
The specific case I'm concerned with is creating the blurred set of decreasing-resolution FBOs to be combined into a bloom effect for HDR. Given the code below, I'm wondering if it's better to rearrange the process to first do the all the thresholding/copy into the set of FBOs and then do all the blurring:

int passWidth = _width / 2, passHeight = _height / 2;
for (size_t i = 0; i < _blur0FB.size(); ++i)
{
glViewport(0, 0, passWidth, passHeight);

glBindFramebuffer(GL_FRAMEBUFFER, _blur0FB);
if (i)
{
_copy.On();
glUniform1i(_copyTex, 0);
glBindMultiTextureEXT(GL_TEXTURE0, GL_TEXTURE_2D, _blur0Tex[i - 1]);
}
else
{
_bright.On();
glUniform1i(_brightTex, 0);
glBindMultiTextureEXT(GL_TEXTURE0, GL_TEXTURE_2D, _hdrTex);
}
glDrawArrays(GL_QUADS, 0, 4);
_blur.On();
glUniform1i(_blurTex, 0);
glUniform1fv(_coef, _kernel.size(), _kernel.data());
glBindFramebuffer(GL_FRAMEBUFFER, _blur1FB);
glBindMultiTextureEXT(GL_TEXTURE0, GL_TEXTURE_2D, _blur0Tex);
glUniform1f(_offx, 1.2f / static_cast<float>(passWidth));
glUniform1f(_offy, 0.0f);
glDrawArrays(GL_QUADS, 0, 4);
glBindFramebuffer(GL_FRAMEBUFFER, _blur0FB);
glBindMultiTextureEXT(GL_TEXTURE0, GL_TEXTURE_2D, _blur1Tex);
glUniform1f(_offx, 0.0f);
glUniform1f(_offy, 1.2f / static_cast<float>(passHeight));
glDrawArrays(GL_QUADS, 0, 4);
passWidth /= 2;
passHeight /= 2;
}

Share this post


Link to post
Share on other sites
glBindFramebuffer is said to be one of the slowest OpenGL calls, to the point where applications prefer to attach different renderbuffers/textures to the same FBO instead of changing FBOs. With that in mind, maybe it's best to keep FBOs in the outer loop and programs in the inner.

However, this should be easy to test. Try one approach, try the other and pick the faster of the two.

Share this post


Link to post
Share on other sites
Quote:
Original post by Prune
Is it valid to read from one render target and write to another of the same FBO?


It is said you get a performance increase if you have several RTT with the same size and you bind these to the same FBO. Of course, if you bind RTT 1 to FBO, then RTT2 becomes disattached. If you bind RTT 2, then RTT 1 becomes disattached.

Share this post


Link to post
Share on other sites
Suppose tex0 and tex1 are both attached to fbo. Then, although this is not technically legal, can I assume that it should work as long as I'm only writing to one?
glFramebufferDrawBufferEXT(_fbo, GL_COLOR_ATTACHMENT0);
glBindMultiTextureEXT(GL_TEXTURE0, GL_TEXTURE_2D, _tex1);
DrawSomething();
glFramebufferDrawBufferEXT(_fbo, GL_COLOR_ATTACHMENT1);
glBindMultiTextureEXT(GL_TEXTURE0, GL_TEXTURE_2D, _tex0);
DrawSomething();
if changing the draw buffer target is faster than rebinding an FBO, it should help, no? Indeed, I could just select the target in the shader and pass a uniform.

[Edit:] I noticed that glTextureBarrierNV() lets one read and write to the same texture, given certain conditions. Can I assume I don't need this call if I change the render target?

[Edited by - Prune on April 17, 2010 5:19:57 PM]

Share this post


Link to post
Share on other sites
That is for doing MRT and I don't have experience with that. You can check the spec but I don't know if you case is documented so you might get undefined behavior.

Share this post


Link to post
Share on other sites
Quote:
Original post by Prune
Suppose tex0 and tex1 are both attached to fbo. Then, although this is not technically legal, can I assume that it should work as long as I'm only writing to one?
glFramebufferDrawBufferEXT(_fbo, GL_COLOR_ATTACHMENT0);
glBindMultiTextureEXT(GL_TEXTURE0, GL_TEXTURE_2D, _tex1);
DrawSomething();
glFramebufferDrawBufferEXT(_fbo, GL_COLOR_ATTACHMENT1);
glBindMultiTextureEXT(GL_TEXTURE0, GL_TEXTURE_2D, _tex0);
DrawSomething();
if changing the draw buffer target is faster than rebinding an FBO, it should help, no? Indeed, I could just select the target in the shader and pass a uniform.

[Edit:] I noticed that glTextureBarrierNV() lets one read and write to the same texture, given certain conditions. Can I assume I don't need this call if I change the render target?


According to the specs, you can use an attached texture in a sampler, as long as you do not write to it. If you were to write to the texture, you'd get a so-called feedback loop that would result in undefined behavior.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!