2012-05-13 39 views
2

我正在研究一个简单的iOS游戏,并且遇到UINavigationController和EAGL-View的问题。 情况如下:我将一个EAGL-View与多个控制器结合使用。每当我推MainViewController(它执行所有自定义的OpenGL绘图)时,我最终会使用更多的内存(每次推送大约5MB!)。使用UINavigationController推送EAGL-View时iPhone内存使用量增加

的问题似乎是内[eaglView_ setFramebuffer] - 或者至少这就是几乎所有的分配似乎发生(我检查通过仪器现场字节 - 内存在70%左右都是在这个函数分配)。

EAGLView :: setFramebuffer:

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

     if (!defaultFramebuffer) 
      [self createFramebuffer]; 

     glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer); 
     glBindFramebuffer(GL_FRAMEBUFFER, msaaFramebuffer);   
     glViewport(0, 0, framebufferWidth, framebufferHeight); 
    } 
} 

和EAGLView :: createFramebuffer:

- (void)createFramebuffer 
{ 
    if (context && !defaultFramebuffer) { 
     [EAGLContext setCurrentContext:context]; 

     // Create default framebuffer object. 
     glGenFramebuffers(1, &defaultFramebuffer); 
     glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer); 

     // Create color render buffer and allocate backing store. 
     glGenRenderbuffers(1, &colorRenderbuffer); 
     glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer); 
     [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer]; 
     glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &framebufferWidth); 
     glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &framebufferHeight); 

     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer); 

     //MSAA stuff 
     glGenFramebuffers(1, &msaaFramebuffer); 
     glGenRenderbuffers(1, &msaaRenderBuffer); 
     glBindFramebuffer(GL_FRAMEBUFFER, msaaFramebuffer); 
     glBindRenderbuffer(GL_RENDERBUFFER, msaaRenderBuffer); 

     glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, 4, GL_RGBA8_OES, framebufferWidth, framebufferHeight); 
     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, msaaRenderBuffer); 

     glGenRenderbuffers(1, &msaaDepthBuffer);  
     glBindRenderbuffer(GL_RENDERBUFFER, msaaDepthBuffer); 
     glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, framebufferWidth, framebufferHeight); 
     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, msaaDepthBuffer); 

     if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 
      NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER)); 

    } 
} 

正如你所看到的 - 没有什么特别的存在。 将我ViewControllers是这样的:(在AppDelegate中)

- (void) swichToViewController: (UIViewController*) newViewController overlapCurrentView: (bool) overlap { 
    // get the viewController on top of the stack - popViewController doesn't do anything if it's the rootViewController. 
    if(!overlap) { 
    // clear everything that was on the eaglView before 
    [eaglView_ clearFramebuffer]; 
    [eaglView_ applyMSAA]; 
    [eaglView_ presentFramebuffer];   
    } 

    UIViewController* oldViewController = [navController_ topViewController]; 
    // see if the view to be switched to is already the top controller: 
    if(oldViewController == newViewController) 
    return; 
    // if the view is already on the stack, just remove all views on top of it: 
    if([[navController_ viewControllers] containsObject:newViewController]) { 
    [oldViewController setView:nil]; 
    [newViewController setView:eaglView_]; 
    [navController_ popToViewController:newViewController animated:!overlap]; 
    return; 
    } 
    // else push the new controller 
    [navController_ popViewControllerAnimated:NO]; 
    [oldViewController setView:nil]; 
    [newViewController setView:eaglView_]; 
    [navController_ pushViewController:newViewController animated:!overlap]; 
} 

最后我使我的精灵是这样的:(在我的MainViewController.mm):

- (void)drawFrame 
{ 
    // When I delete this line, I just get a white screen, even if I have called setFramebuffer earlier(?!) 
    [(EAGLView *)self.view setFramebuffer]; 

    glClearColor(1, 1, 1, 1); 
    glClear(GL_COLOR_BUFFER_BIT); 

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 


    GLfloat screenWidth = [UIScreen mainScreen].bounds.size.width; 
    GLfloat screenHeight = [UIScreen mainScreen].bounds.size.height; 

    glOrthof(0, screenWidth, 0, screenHeight, -1.0, 1.0); 
    glViewport(0, 0, screenWidth, screenHeight); 

    [gameManager_ playGame]; 


    //MSAA stuff 
    [(EAGLView *)self.view applyMSAA]; 

    [(EAGLView *)self.view presentFramebuffer]; 
    [(EAGLView *)self.view clearFramebuffer]; 
} 

的东西,可能是值得一提的是我每次推动视图时都不会分配视图,我会一直引用它们直到游戏结束。

[gameManager_ playGame]将精灵绘制到屏幕上 - 但我在另一个项目中使用了这个方法,没有任何内存问题。

任何帮助将非常感激,因为我一直停留在这2天:/

编辑: 我已经能够缩小问题到调用gldLoadFramebuffer。这是每当我尝试使用openGL函数在屏幕上绘制某些东西时调用的。 当上下文发生变化时,它似乎消耗更多内存......但我怎么能避免这种情况?

+0

我在UIScrollView上遇到了与EAGLViews类似的问题。即使在我第一次从UIScrollView中删除EAGLView之后,它似乎仍然无法正确删除帧缓冲区。你能告诉我关于如何正确删除MSAA缓冲区的示例代码吗? –

回答

1

我想我发现了这个问题。 对于任何感兴趣的人:在切换视图时,MSAA缓冲区未被正确删除。这会导致性能在几次推动后显着下降,同时也是内存使用量增加的原因。

相关问题