使用UINavigationController推送EAGL-View时,iPhone内存使用量会增加

时间:2012-05-13 16:07:14

标签: ios opengl-es uinavigationcontroller

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

问题似乎在[eaglView_ setFramebuffer]之内 - 或者至少在几乎所有分配似乎都发生的地方(我已经通过仪器检查了实时字节 - 在此函数中分配了大约70%的内存)。 / p>

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函数在屏幕上绘制内容时,都会调用此方法。 当上下文改变时,它似乎消耗更多的内存......但是我怎么能避免这种情况?

1 个答案:

答案 0 :(得分:1)

我想我发现了这个问题。 对于任何感兴趣的人:切换视图时未正确删除MSAA-Buffers。这导致性能在几次推送后显着下降,并且还导致内存使用量的增加。