gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:51:29 25 4
gpt4 key购买 nike

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

问题似乎出在 [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:(在 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];
}

最后,我像这样渲染我的 Sprite :(在我的 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];
}

可能值得一提的是,我不会在每次推送时都分配 View ,我会一直引用它们直到游戏退出。

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

任何帮助将不胜感激,因为我已经坚持了 2 天:/

编辑:我已经能够将问题缩小到对 gldLoadFramebuffer 的调用。每当我尝试使用 openGL 函数在屏幕上绘制某些内容时,都会调用此方法。当上下文发生变化时,它似乎会消耗更多内存……但我该如何避免呢?

最佳答案

我想我找到了问题所在。对于任何感兴趣的人:切换 View 时未正确删除 MSAA 缓冲区。这导致几次推送后性能显着下降,并且也是内存使用量增加的原因。

关于ios - 使用 UINavigationController 推送 EAGL-View 时 iPhone 内存使用量增加,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10573179/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com