# OpenGL Error when using blitFramebuffer

## Recommended Posts

Hi, I'm copying textures using glBlitFramebuffer like this:

glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, src->handle(), 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst->handle(), 0);
glBlitFramebuffer(0, 0, src->size().x, src->size().y, 0, 0, dst->size().x, dst->size().y, GL_COLOR_BUFFER_BIT, mode);


The framebuffer is freshly created and has no other attachments. src is 512x512 and dst is 256x256 and mode is set to linear filtering.

I got an error callback that says

GL_INVALID_FRAMEBUFFER_OPERATION error generated. Framebuffer bindings are not framebuffer complete.

So after setting the attachments I checked both READ and WRITE fb with glCheckFramebufferStatus. The WRITE fb returns GL_FRAMEBUFFER_COMPLETE, but to my surprise the READ fb returns GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT (I'm not even using this old extension).

I managed to workaround the issue by first setting src attachment to both READ and DRAW fb and then replacing the draw:

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, src->handle(), 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst->handle(), 0);


but this seems unnecessary to me. The curious thing is that if I first set both buffers to dst and then change only READ I still get the error in the READ fb.

I'm using OpenGL 4.5 context (beta NVidia driver on GTX780).

I thought I should be able to set READ and WRITE buffers to different dimensions since OpenGL 3.something without such issues?

Could this be a driver bug or am I missing something about the framebuffer setup?

##### Share on other sites

Im a little confused with the use of glFramebufferTexture2D to do a blit, unless those two lines are from the fbo setup. glFramebufferTexture2D attaches a texture to a framebuffer attachment point allowing you to render into the texture.

To blit:

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstID)        // draw/write to this buffer

glDrawBuffer(GL_COLOR_ATTACHMENT0)                          // specifically this attachment

glBlitFramebuffer(...)                                                              // do the blit

by calling glFramebufferTexture2D, youre doing attachments and possibly detaching, which is sometimes needed depending on what youre doing, Im just not sure if you need it here.

Edited by NumberXaero

##### Share on other sites

glFramebufferTexture2D attaches a texture to a framebuffer attachment point allowing you to render into the texture.

I omitted the binding code but I have a single FBO with one texture attached to the READ buffer attachment point 0 and another to the WRITE buffer attachment point 0.

This is a nice setup for fast copying and it works (worked actually :/ ) great, except for that weirdness I mentioned.

The whole code with a binding looks something like this:

void Effects::copyTexture(GameTexture* src, GameTexture* dst, GLenum mode)
{
glBindFramebuffer(GL_FRAMEBUFFER, copyFbo->handle());
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst->handle(), 0);
glBlitFramebuffer(0, 0, src->size().x, src->size().y, 0, 0, dst->size().x, dst->size().y, GL_COLOR_BUFFER_BIT, mode);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}


I vaguely remember that it worked like that without errors some time ago (an older driver). That's why I asked if this could be a driver bug.

Hm, upon further inspection of the spec I see that GL_FRAMEBUFFER is equivalent to GL_DRAW_FRAMEBUFFER (I thought it's both read and write), so I'm wondering how the whole thing worked at all... but it did! Oh well, I need to rewrite this correctly I guess...

##### Share on other sites

Ok, turns out because I thought that binding to the GL_FRAMEBUFFER binds to both READ and WRITE buffers I was actually trying to attach the texture to a null READ buffer.

The fixed code looks like this:

void Effects::copyTexture(GameTexture* src, GameTexture* dst, GLenum mode)
{
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, copyFbo->handle());
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst->handle(), 0);
glBlitFramebuffer(0, 0, src->size().x, src->size().y, 0, 0, dst->size().x, dst->size().y, GL_COLOR_BUFFER_BIT, mode);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}


and now it works as expected without errors. Gosh, I'm making stupid mistakes. I need a coffee...

Sorry for bothering you.

##### Share on other sites
How does this even work?

You have one single FBO, you bind it to both targets, then you attach the source texture to GL_COLOR_ATTACHMENT0 of that FBO and then you overwrite it with the destination texture (same FBO) - so you are basically blitting from the destination texture to the destination texture which has undefined behavior.

There is no separate READ and DRAW attachment inside the (single) FBO container.

##### Share on other sites

Sure there is. If they weren't separate why even bother to specify different targets for them in glFramebufferTexture2D call?

The way I see it READ and WRITE locations are totally separately configurable. It just so happens that for most cases you don't even care about the READ attachments, because there's no programmable way to read them in the shaders (this would give us for example programmable blending stage which we sadly don't have yet :( ). It's only for the "fixed" functions like the glBlitFramebuffer or such.

Anyway, I didn't bother to look it up in the spec but It's perfectly reasonable for me to assume that if I can specify different targets(READ or WRITE) then it's used to actually make a distinction. As far as I can tell it indeed works on hardware I could get access to, so either there's a global driver makers misunderstanding (aligned with what I think) or... well I don't know what's the other option.

##### Share on other sites

Ok, I'm starting to be really hang up on the issue. I've re-read your comments, read the spec and did some more search on the topic and I can't seem to arrive at a common conclusion.

On one hand the READ and WRITE targets can be viewed like I described them - as a sort of 2 different objects inside an FBO having different attachments. This seems reasonable in the scenario of a single FBO and seems to be backed up by the working example.

The other view is that there's a single attachment point 0 (or any other) on an FBO targeted for both reading and writing. In that case READ and WRITE targets seem to make sense in case of two different FBOs, one of which is targeted for reading and another for writing. This interpretation is backed up by the fact that the new bindless syntax doesn't allow to specify different attachment 0 for reading and writing. The glNamedFramebufferTexture* functions take only an FBO id.

I'm really confused now. Spec is unclear on this (or I can't find relevant part). Is it a spec defect? A driver bug? An undefined behavior? Or perfectly valid (though uncommon) code?

##### Share on other sites

The first argument of the glFramebufferTexture functions is the target framebuffer you want to be manipulating.

There are two framebuffer bindings - the draw framebuffer, which is used for drawing to, and the read framebuffer, which is where you read from. When you call glBindFramebuffer(GL_FRAMEBUFFER, fbo);  you bind 'fbo' to both the draw framebuffer and the read framebuffer. Alternatively, you can bind specifically to the draw or read framebuffer by specifying GL_DRAW_FRAMEBUFFER or GL_READ_FRAMEBUFFER respectively.

Coming back to glFramebufferTexture, when you do glFramebufferTexture2D(GL_READ_FRAMEBUFFER, ...); you modify the framebuffer which is currently bound as the 'read framebuffer'. With GL_DRAW_FRAMEBUFFER, you modify the framebuffer which is currently bound as the 'draw framebuffer'. If the draw and read framebuffers are the same (if you used GL_FRAMEBUFFER when binding) then in both cases you're modifying the same framebuffer.

Ok, turns out because I thought that binding to the GL_FRAMEBUFFER binds to both READ and WRITE buffers I was actually trying to attach the texture to a null READ buffer.

The fixed code looks like this:

void Effects::copyTexture(GameTexture* src, GameTexture* dst, GLenum mode)
{
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, copyFbo->handle());
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst->handle(), 0);
glBlitFramebuffer(0, 0, src->size().x, src->size().y, 0, 0, dst->size().x, dst->size().y, GL_COLOR_BUFFER_BIT, mode);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}


and now it works as expected without errors. Gosh, I'm making stupid mistakes. I need a coffee...

Sorry for bothering you.

As far as I know, the driver is free to do whatever it wants in this case because you're reading from and writing to the same framebuffer texture. Some drivers will be clever enough to spot this and allocate new texture memory to draw to (so that the original is kept), and once the blit is finished, destroy the old texture and swap in the new one. However, it could be that the driver doesn't do anything and screws you over by corrupting the texture :P

If all you are using the FBO for is to copy the texture then you can use glCopyTexImage2D instead.

##### Share on other sites

Thanks for the patience. I think I understand now. So this code is of "hey, works on my machine" variety. I'll fix that.

Btw. it seems inconsistent that for glBindFramebuffer GL_FRAMEBUFFER means both read and write targets, but for glFramebufferTexture it means only the draw target. Or am I missing something again?

glCopyTexImage2D only lets me copy a rectangle portion 1:1. I need to resize the texture (with filtering) in the process sometimes, so that's why I'm using FBO. Is there a faster way?

Edited by chrisaverage

##### Share on other sites

Btw. it seems inconsistant that for glBindFramebuffer GL_FRAMEBUFFER means both read and write targets, but for glFramebufferTexture it means only the draw target. Or am I missing something again?

It's just an inconsistency unfortunately :(

glCopyTexImage2D only lets me copy a rectangle portion 1:1. I need to resize the texture (with filtering) in the process sometimes, so that's why I'm using FBO. Is there a faster way?

I'm not sure on this but maybe you could attach one texture to GL_COLOR_ATTACHMENT0 and another to GL_COLOR_ATTACHMENT1. And then set the read attachment using glReadBuffer(GL_COLOR_ATTACHMENT0); the draw buffer using glDrawBuffer(GL_COLOR_ATTACHMENT1); and then perform the blit. Failing that, you would need to create two FBOs, one for drawing to, one for reading from.

##### Share on other sites

According to the OpenGL 4.5 spec on chapter 18.3 Copying Pixels:

... For all such commands, if the source and destination are identical or are different views of the same underlying texture image, and if the source and destination regions overlap in that framebuffer, renderbuffer, or texture image, pixel values resulting from the copy operation are undefined.

So copying between the same FBO should work, as long as the regions do not overlap (which should not be the case between attachment 0 and 1 (each with own texture)).

There is also the function glCopyImageSubData, but again without general-purpose conversions.

Edited by Maus

## Create an account

Register a new account

• ## Partner Spotlight

• ### Forum Statistics

• Total Topics
627682
• Total Posts
2978614
• ### Similar Content

• Both functions are available since 3.0, and I'm currently using glMapBuffer(), which works fine.
But, I was wondering if anyone has experienced advantage in using glMapBufferRange(), which allows to specify the range of the mapped buffer. Could this be only a safety measure or does it improve performance?
Note: I'm not asking about glBufferSubData()/glBufferData. Those two are irrelevant in this case.
• By xhcao
Before using void glBindImageTexture(    GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format), does need to make sure that texture is completeness.
• By cebugdev
hi guys,
are there any books, link online or any other resources that discusses on how to build special effects such as magic, lightning, etc. in OpenGL? i mean, yeah most of them are using particles but im looking for resources specifically on how to manipulate the particles to look like an effect that can be use for games,. i did fire particle before, and I want to learn how to do the other 'magic' as well.
Like are there one book or link(cant find in google) that atleast featured how to make different particle effects in OpenGL (or DirectX)? If there is no one stop shop for it, maybe ill just look for some tips on how to make a particle engine that is flexible enough to enable me to design different effects/magic
let me know if you guys have recommendations.
• By dud3
How do we rotate the camera around x axis 360 degrees, without having the strange effect as in my video below?
Mine behaves exactly the same way spherical coordinates would, I'm using euler angles.
Tried googling, but couldn't find a proper answer, guessing I don't know what exactly to google for, googled 'rotate 360 around x axis', got no proper answers.

References:
Code: https://pastebin.com/Hcshj3FQ
The video shows the difference between blender and my rotation:

• By Defend
I've had a Google around for this but haven't yet found some solid advice. There is a lot of "it depends", but I'm not sure on what.
My question is what's a good rule of thumb to follow when it comes to creating/using VBOs & VAOs? As in, when should I use multiple or when should I not? My understanding so far is that if I need a new VBO, then I need a new VAO. So when it comes to rendering multiple objects I can either:
* make lots of VAO/VBO pairs and flip through them to render different objects, or
* make one big VBO and jump around its memory to render different objects.
I also understand that if I need to render objects with different vertex attributes, then a new VAO is necessary in this case.
If that "it depends" really is quite variable, what's best for a beginner with OpenGL, assuming that better approaches can be learnt later with better understanding?

• 13
• 12
• 10
• 12
• 22