OpenGL-ES, iPhone and intermittent error: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES (0x8CD6)

倖福魔咒の 提交于 2020-01-01 06:36:30

问题


I have an app that uses OpenGL-ES and an EAGLContext within a UIView - very much like Apple's GLPaint sample code app.

It might be significant that I see this bug on my iPhone 4 but not on my iPad.

Mostly, this works very well. However, I am getting GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES from glCheckFramebufferStatusOES() within the createFrameBuffer method. The reason is that the backingWidth and backingHeight are both 0.

I am trying to understand the relation between )self.layer and its size - which is not (0,0) - and the values for backingWidth and backingHeight. My UIView and its CALayer both have the 'correct' size, while glGetRenderbufferParameterivOES() returns 0 for GL_RENDERBUFFER_WIDTH_OES and GL_RENDERBUFFER_HEIGHT_OES.

Here is my createFrameBuffer method - which works much of the time.

- (BOOL)createFramebuffer
 { 
 // Generate IDs for a framebuffer object and a color renderbuffer
 glGenFramebuffersOES(1, &viewFramebuffer);
 glGenRenderbuffersOES(1, &viewRenderbuffer);

 glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);

 glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);

 // This call associates the storage for the current render buffer with the EAGLDrawable (our CAEAGLLayer)
 // allowing us to draw into a buffer that will later be rendered to screen wherever the layer is (which corresponds with our view).
 [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(id<EAGLDrawable>)self.layer];

 glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);

 //DLog(@" backing size = (%d, %d)", backingWidth, backingHeight);
 glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
 glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
 DLog(@" backing size = (%d, %d)", backingWidth, backingHeight);


 err = glGetError();
 if (err != GL_NO_ERROR)
  DLog(@"Error. glError: 0x%04X", err);

 // For this sample, we also need a depth buffer, so we'll create and attach one via another renderbuffer.
 glGenRenderbuffersOES(1, &depthRenderbuffer);
 glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
 glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);

 glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);

 if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
  {
  NSLog(@"failed to make complete framebuffer object 0x%X", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
  return NO;
  }

 return YES;
 }

When backingWidth and backingHeight are non-zero, then there is no error returned from glCheckFramebufferStatusOES().


回答1:


I had this same problem. For me the fix was that in the opengl sample code of last year, Apple rebuilds the renderbuffer in every layoutSubviews call. Now, if you create an iPhone template opengl project, you will see that the layoutSubviews only destroys the renderbuffer. Then on every draw, if the render buffer is nil THEN create it. This is better cause when you are about to draw all CAlayers etc should be all shined up and ready to go.

I think that the render buffer in my case was trying to be built when the EagleView layer was not serviceable - i.e. in some tear down state. In any case when I changed my code to match it worked.

Also there are fewer calls to this code, which is likely faster. On startup there is a lot of scene loading and moving about, which generates 1/2 dozen layout sub view calls with my app.

Since the comments in Apple's code tend to be few and far between, the fact that there is one in the layoutsubviews call is significant:

// The framebuffer will be re-created at the beginning of the next 
   setFramebuffer method call.

--Tom




回答2:


I had this same problem also, using Apple's OpenGL-ES sample code that does a destroyFramebuffer, createFramebuffer then drawView with the layoutSubviews function.

What you want to do is create the frame buffer in the drawView call as Tom says above, but additionally, you also want to defer the call to drawView until the layoutSubviews function returns. The way I did this was:

- (void) layoutSubviews
{
 [EAGLContext setCurrentContext:context];

 [self destroyFramebuffer];

 // Create the framebuffer in drawView instead as needed, as before create 
 // would occasionally happen when the view wasn't servicable (?) and cause 
 // a crash. Additionally, send the drawView call to the main UI thread 
 // (ALA PostMessage in Win32) so that it is deferred until this function 
 // returns and the message loop has a chance to process other stuff, etc 
 // so the EAGLView will be ready to use when createFramebuffer is finally 
 // called and the glGetRenderbufferParameterivOES calls to get the backing 
 // width and height for the render buffer will always work (occasionally I 
 // would see them come back as zero on my old first gen phone, and this 
 // crashes OpenGL.)
 //
 // Also, using this original method, I would see memory warnings in the 
 // debugger console window with my iPad when rotating (not all the time, 
 // but pretty frequently.)  These seem to have gone away using this new 
 // deferred method...
 [self performSelectorOnMainThread:@selector(drawView) 
                        withObject:nil 
                     waitUntilDone:NO];
}

Ross



来源:https://stackoverflow.com/questions/4093434/opengl-es-iphone-and-intermittent-error-gl-framebuffer-incomplete-attachment-o

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!