2012-05-13 71 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緩衝區未被正確刪除。這會導致性能在幾次推動後顯着下降,同時也是內存使用量增加的原因。

相關問題