2012-05-13 8 views
2

簡単なiOSゲームで作業していて、UINavigationControllerとEAGL-Viewに問題があります。 状況は次のとおりです。複数のコントローラと1つのEAGL-Viewを使用します。 MainViewController(すべてのカスタムOpenGL描画を行います)を押すたびに、より多くのメモリ(プッシュごとに約5MB!)が使用されてしまいます。UINavigationControllerを使用してEAGL-Viewを押したときにiPhoneのメモリ使用量が増加する

問題は[eaglView_ setFramebuffer]の中にあるようです - あるいは、ほとんどすべての割り当てが起こっているようです(Instrumentsのライブバイトをチェックしました - メモリの約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切り替えます(私の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]; 
} 

言及する価値があるかもしれない何か(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]; 
} 

最後に、私はこのような私のスプライトをレンダリング私はそれらをプッシュするたびにビューを割り当てないことです、私はゲームが終了するまでそれらの参照を保持します。

[gameManager_ playGame]はスプライトを画面に描画しますが、メモリの問題がなく別のプロジェクトでこのメソッドを使用しています。

私は2日間、この上で立ち往生してきたとしてすべてのヘルプは本当にいただければ幸いです:/

編集: 私はgldLoadFramebufferへの呼び出しに問題を絞り込むことができました。これは、openGL関数を使って画面上に何かを描画しようとするたびに呼び出されます。 コンテキストが変わったときにもっと多くのメモリを消費するようです...しかし、どうすればそれを避けることができますか?

+0

私はUIScrollViewのEAGLViewsと同様の問題を抱えています。私は最初にUIScrollViewからEAGLViewを削除しても、フレームバッファを正しく削除できないようです。 MSAA-Buffersを正しく削除したサンプルコードを表示できますか? –

答えて

1

問題が見つかりました。 興味のある人は:MSAA-Buffersはビューの切り替え時に正しく削除されませんでした。そのため、数回押すとパフォーマンスが大幅に低下し、メモリ使用量も増加しました。

関連する問題