gpt4 book ai didi

iOS OpenGL ES 多次加载同一对象时崩溃

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

基本上,在我的 iOS 应用程序中,我有一个模态屏幕,我在其中显示了一些 OpenGL ES 图形。在应用程序崩溃之前,我能够进入和退出此模式屏幕 6 次。我假设这是一个内存问题,但我不知道是什么和/或在哪里。

非常感谢您就此事提供的任何帮助。

在我的 OGLViewController 中:

#define OPENGL_ERROR_CHECK {GLuint error = glGetError(); ((error == GL_NO_ERROR) ? :  NSLog(@"GL Error: %d", (error)));}

@interface OGLItemViewController : GLKViewController

@property (nonatomic) GLuint program;

// item ogl arrays + buffers
@property (nonatomic) NSInteger numOGLBuffers;
@property (nonatomic) GLuint* vertexArrays;
@property (nonatomic) GLuint* vertexBuffers;

// index buffer for ogl item vertices
@property (nonatomic) GLuint* indexBuffers;

@property (strong, nonatomic) EAGLContext *context;
@property (strong, nonatomic) GLKBaseEffect *effect;

@end

@implementation

- (void)viewDidLoad
{
[super viewDidLoad];

self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];

OPENGL_ERROR_CHECK
glFinish(); // put this in here to make sure all previous calls have been finished
OPENGL_ERROR_CHECK

if (!self.context)
{
NSLog(@"Failed to create ES context");
}

GLKView *view = (GLKView *) self.view;
view.context = self.context;
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
view.opaque = NO;

self.numOGLBuffers = 0;

self.vertexArrays = nil;
self.vertexBuffers = nil;
self.indexBuffers = nil;
}

- (void)setupGL
{
OPENGL_ERROR_CHECK
[EAGLContext setCurrentContext:self.context];
OPENGL_ERROR_CHECK

[self loadShaders];
OPENGL_ERROR_CHECK

self.effect = [[GLKBaseEffect alloc] init];
OPENGL_ERROR_CHECK
self.effect.light0.enabled = GL_TRUE;
OPENGL_ERROR_CHECK

self.effect.colorMaterialEnabled = GL_TRUE;
OPENGL_ERROR_CHECK

self.effect.lightModelTwoSided = GL_FALSE;
OPENGL_ERROR_CHECK

self.effect.light0.diffuseColor = GLKVector4Make(0.69f, 0.69f, 0.69f, 0.5f);
OPENGL_ERROR_CHECK

glEnable(GL_DEPTH_TEST);
OPENGL_ERROR_CHECK

Item *item = [GlobalStore sharedInstance].item

NSMutableArray *shells = item.geometry;

if (shells.count > 0)
{
_vertexArrays = malloc(shells.count * sizeof(GLuint));
_vertexBuffers = malloc(shells.count * sizeof(GLuint));
_indexBuffers = malloc(shells.count * sizeof(GLuint));
self.numOGLBuffers = shells.count;

for (int i = 0; i < shells.count; i++)
{
Geometry *geom = [shells objectAtIndex:i];
if (geom.vertexCount > 0)
{
GLuint vao = 0;
OPENGL_ERROR_CHECK
glGenVertexArraysOES(1, &vao);

OPENGL_ERROR_CHECK
glBindVertexArrayOES(vao);
OPENGL_ERROR_CHECK

_vertexArrays[i] = vao;

if (!geom.vertices)
{
[self displayError:-998]; // generic error codes that i've just canned in to see if any problems with these pointers
}
if (!geom.indices)
{
[self displayError:-997];
}

// create vertice buffer
GLuint vbo = 0;
glGenBuffers(1, &vbo);
OPENGL_ERROR_CHECK
glBindBuffer(GL_ARRAY_BUFFER, vbo);
OPENGL_ERROR_CHECK
glBufferData(GL_ARRAY_BUFFER, geom.vertexCount * sizeof(OGLVertices), geom.vertices, GL_STATIC_DRAW);
OPENGL_ERROR_CHECK

_vertexBuffers[i] = vbo;

// create index by buffer
GLuint ibo = 0;
glGenBuffers(1, &ibo);
OPENGL_ERROR_CHECK
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
OPENGL_ERROR_CHECK
glBufferData(GL_ELEMENT_ARRAY_BUFFER, geom.indexCount * sizeof(GLuint), geom.indices, GL_STATIC_DRAW);
OPENGL_ERROR_CHECK

_indexBuffers[i] = ibo;

// enable position, normal and colour attributes
glEnableVertexAttribArray(GLKVertexAttribPosition);
OPENGL_ERROR_CHECK
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(OGLVertices), (const GLvoid *) offsetof(OGLVertices, Position));
OPENGL_ERROR_CHECK
glEnableVertexAttribArray(GLKVertexAttribNormal);
OPENGL_ERROR_CHECK
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, sizeof(OGLVertices), (const GLvoid *) offsetof(OGLVertices, Normal));
OPENGL_ERROR_CHECK
glEnableVertexAttribArray(GLKVertexAttribColor);
OPENGL_ERROR_CHECK
glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, sizeof(OGLVertices), (const GLvoid *) offsetof(OGLVertices, Colour));
OPENGL_ERROR_CHECK
}
}

glBindVertexArrayOES(0);
OPENGL_ERROR_CHECK
}
}

- (void)tearDownGL
{
[EAGLContext setCurrentContext:self.context];
self.effect = nil;

[self deleteOGLData];
}

- (void)dealloc
{
[self tearDownGL];

if ([EAGLContext currentContext] == self.context)
{
[EAGLContext setCurrentContext:nil];
}
}

- (void) viewDidDisappear:(BOOL)animated
{
[self tearDownGL];
}

- (void)deleteOGLData
{
// delete ogl buffers and arrays
if (self.numOGLBuffers > 0)
{
if (_vertexBuffers)
{
OPENGL_ERROR_CHECK
glDeleteBuffers(self.numOGLBuffers, _vertexBuffers);

OPENGL_ERROR_CHECK
free(_vertexBuffers);
_vertexBuffers = nil;
}
if (_vertexArrays)
{
glDeleteVertexArraysOES(self.numOGLBuffers, _vertexArrays);
OPENGL_ERROR_CHECK
free(_vertexArrays);
_vertexArrays = nil;
}
if (_indexBuffers)
{
glDeleteBuffers(self.numOGLBuffers, _indexBuffers);
OPENGL_ERROR_CHECK
free(_indexBuffers);
_indexBuffers = nil;
}
}


self.numOGLBuffers = 0;

glDeleteProgram(self.program);
OPENGL_ERROR_CHECK

self.program = 0;

glFinish(); // again, just put this in here to check everything has finished
OPENGL_ERROR_CHECK
}

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
OPENGL_ERROR_CHECK
glClearColor(1.0, 1.0, 1.0, 0.0);
OPENGL_ERROR_CHECK
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
OPENGL_ERROR_CHECK

// Render the object with GLKit
[self.effect prepareToDraw];
OPENGL_ERROR_CHECK


NSMutableArray *shells = [GlobalStore sharedInstance].item.geometry;
if (shells && _vertexArrays && _vertexBuffers)
{
for (int i = 0; i < shells.count; i++)
{
Geometry *geom = [shells objectAtIndex:i];

if (geom.vertexCount > 0)
{
GLuint vao = self.vertexArrays[i];
glBindVertexArrayOES(vao);
OPENGL_ERROR_CHECK

if(geom.indexCount == 0)
[self displayError:-996];

glDrawElements(GL_TRIANGLES, geom.indexCount, GL_UNSIGNED_INT, 0);
OPENGL_ERROR_CHECK
self.initialised = YES;
}
}
}
}

- (BOOL)loadShaders
{
GLuint vertShader, fragShader;
NSString *vertShaderPathname, *fragShaderPathname;

// Create shader program.
self.program = glCreateProgram();
OPENGL_ERROR_CHECK

// Create and compile vertex shader.
vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"];
if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname])
{
NSLog(@"Failed to compile vertex shader");
return NO;
}

// Create and compile fragment shader.
fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"];
if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname])
{
NSLog(@"Failed to compile fragment shader");
return NO;
}

// Attach vertex shader to program.
glAttachShader(_program, vertShader);
OPENGL_ERROR_CHECK

// Attach fragment shader to program.
glAttachShader(_program, fragShader);
OPENGL_ERROR_CHECK

// Bind attribute locations.
// This needs to be done prior to linking.
glBindAttribLocation(_program, GLKVertexAttribPosition, "position");
OPENGL_ERROR_CHECK

glBindAttribLocation(_program, GLKVertexAttribNormal, "normal");
OPENGL_ERROR_CHECK

// Link program.
if (![self linkProgram:_program])
{
NSLog(@"Failed to link program: %d", _program);

if (vertShader)
{
glDeleteShader(vertShader);
OPENGL_ERROR_CHECK
vertShader = 0;
}
if (fragShader)
{
glDeleteShader(fragShader);
OPENGL_ERROR_CHECK
fragShader = 0;
}
if (_program)
{
glDeleteProgram(_program);
OPENGL_ERROR_CHECK
_program = 0;
}

return NO;
}

// Get uniform locations.
uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix");
uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix");

// Release vertex and fragment shaders.
if (vertShader)
{
glDetachShader(_program, vertShader);
OPENGL_ERROR_CHECK
glDeleteShader(vertShader);
OPENGL_ERROR_CHECK
}
if (fragShader)
{
glDetachShader(_program, fragShader);
OPENGL_ERROR_CHECK
glDeleteShader(fragShader);
OPENGL_ERROR_CHECK
}

return YES;
}

- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file
{
GLint status;
const GLchar *source;

source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String];
if (!source)
{
NSLog(@"Failed to load vertex shader");
return NO;
}

*shader = glCreateShader(type);
OPENGL_ERROR_CHECK
glShaderSource(*shader, 1, &source, NULL);
OPENGL_ERROR_CHECK
glCompileShader(*shader);
OPENGL_ERROR_CHECK

glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
OPENGL_ERROR_CHECK
if (status == 0)
{
glDeleteShader(*shader);
OPENGL_ERROR_CHECK
return NO;
}

return YES;
}

- (BOOL)linkProgram:(GLuint)prog
{
GLint status;
glLinkProgram(prog);
OPENGL_ERROR_CHECK

glGetProgramiv(prog, GL_LINK_STATUS, &status);
OPENGL_ERROR_CHECK
if (status == 0)
{
return NO;
}

return YES;
}

- (BOOL)validateProgram:(GLuint)prog
{
GLint logLength, status;

glValidateProgram(prog);
OPENGL_ERROR_CHECK
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
OPENGL_ERROR_CHECK
if (logLength > 0)
{
GLchar *log = (GLchar *)malloc(logLength);
glGetProgramInfoLog(prog, logLength, &logLength, log);
OPENGL_ERROR_CHECK
NSLog(@"Program validate log:\n%s", log);
free(log);
}

glGetProgramiv(prog, GL_VALIDATE_STATUS, &status);
OPENGL_ERROR_CHECK
if (status == 0)
{
return NO;
}

return YES;
}


-(void)displayError: (GLuint) err
{
NSString *msg = [[NSString alloc] initWithFormat:@"OpenGL Error: %d", err];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: @"Error"
message: msg
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil];

[alert show];
}


@end

现在 - 我不知道这样做是否正确,但在 viewdiddisappear 方法中,我确保删除所有 ogl 数据。我想确保当我退出 View 时,ogl 数据已从内存中删除。

因此,如果我进入模态视图,退出并重复 5 次以上,我将遇到黑屏崩溃,并会中断,并显示以下屏幕:

screen grab

我已确保一切都在适当的情况下在单个线程中完成。我试图确保删除所有对象和缓冲区。

所以我想知道我到底做错了什么导致它突然崩溃......分析器中似乎没有任何指示。我似乎没有任何内存泄漏或任何会导致内存耗尽的内容。

(我知道我会在不需要的时候渲染每一帧 - 我会在稍后解决这个问题。)

我拥有的全局存储包含我使用的一些对象的实例。这些应该始终有效(我已经检查过了)。

最佳答案

我需要做的是删除 GLKView 可绘制对象。

在 ViewDidDisappear 方法中(可能不是合适的地方,但它有效)添加以下内容:

GLKView *view = (GLKView*) self.view;
[view deleteDrawable];

关于iOS OpenGL ES 多次加载同一对象时崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18723082/

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