我正在研究一個簡單的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函數在屏幕上繪製某些東西時調用的。 當上下文發生變化時,它似乎消耗更多內存......但我怎麼能避免這種情況?
我在UIScrollView上遇到了與EAGLViews類似的問題。即使在我第一次從UIScrollView中刪除EAGLView之後,它似乎仍然無法正確刪除幀緩衝區。你能告訴我關於如何正確刪除MSAA緩衝區的示例代碼嗎? –