2010-07-08 3 views
3

Я пишу приложение iPhone, которое использует UIView с CAEAGLayer в качестве своего слоя. Все отлично и работает отдельно от 1 небольшая проблема: иногда она падает с EXC_BAD_ACCESS и следующие трассировки стека:сбой glDrawArrays с EXC_BAD_ACCESS

[EAGLView draw] 
    glDrawArrays_Exec 
    PrepareToDraw 
    DrawFramebufferMakeResident 
    AttachmentMakeResident 
    TextureMakeResident 
    memmove 

она падает на линии:

glVertexPointer(3, GL_FLOAT, 0, vertexCoordinates); 
    glTexCoordPointer(2, GL_FLOAT, 0, textureCoordinates); 
    glBindTexture(GL_TEXTURE_2D, textures[kActiveSideLeft]); 
    glDrawArrays(GL_TRIANGLE_STRIP, 0, totalPoints); //<--Crash here 

Применение разобьет только при изменении поворота интерфейса (что также является единственным случаем, когда изменяется рамка просмотра). Он часто не падает; большую часть времени для воспроизведения этой проблемы требуется 3-5 минут вращающегося устройства.
Я считаю, что ошибаюсь, что связано с инициализацией CAEAGLLayer/сменой фрейма, так как в этом случае он сбой (я считаю).
Так вот инициализации и компоновщик подвиды метода:
Init:

... 
    CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;  
    eaglLayer.opaque = TRUE; 

    context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; 
    if (!context || ![EAGLContext setCurrentContext:context]) 
    { 
     [self release]; 
     return nil; 
    } 

    glGenFramebuffersOES(1, &defaultFramebuffer); 
    glGenRenderbuffersOES(1, &colorRenderbuffer); 
    glGenRenderbuffersOES(1, &depthRenderbuffer); 
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer); 
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer); 
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer); 
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer); 
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer); 
    ... 

На множестве кадра я только набор GL_MODELVIEW и GL_POJECTION матрицы, поэтому я не думаю, ничего плохого может произойти там.
LayoutSubviews:

- (void)layoutSubviews 
    { 
     [EAGLContext setCurrentContext:context]; 

     glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer); 
     [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer]; 
     glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth); 
     glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight); 
     glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer); 
     glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight); 

     NSAssert1(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) == GL_FRAMEBUFFER_COMPLETE_OES, @"Failed to make complete framebuffer object: %X", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)); 
    } 

метод Draw сам выглядит как:

 if ([EAGLContext currentContext] != context) { 
      [EAGLContext setCurrentContext:context]; 
     } 

     glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer); 
     glViewport(0, 0, backingWidth, backingHeight); 

     ...//drawing different triangle strips here 

     glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer); 
     [context presentRenderbuffer:GL_RENDERBUFFER_OES]; 

Я бы признателен за любые замечания по указанному коду или предложения о том, как я могу узнать причину этой ошибки.

ответ

3

Я бы с подозрением относился к переменной totalPoints, передаваемой в drawArrays, или, может быть, к вашим значениям для vertexCorrdinates или textureCoordinates, если эти массивы не являются статическими. Ваша авария подразумевает, что вы уходите с конца памяти при рисовании массивов. Я менее подозрительно отношусь к вашей настройке GL и больше беспокоюсь о вашем управлении памятью и о том, что вы рисуете во время вращения.

(Кроме того, FWIW, я не думаю, что вы должны называть RenderBufferStorage каждый раз, когда вы связываете буфер визуализации. Вам нужно сделать это только один раз, когда вы их создадите. убедитесь, что вы не должны фактически уничтожать буферы, когда вы меняете их размер и просто воссоздаете их с нуля.)

+0

Ну, все массивы статичны (по крайней мере, его размеры никогда не меняются), а totalPoints - это константа #define , В любом случае, я в конечном итоге воссоздал opengl вид с нуля каждый раз, когда устройство вращается, и это помогло. Я не уверен, что это хороший способ решить проблему, но по крайней мере она работает =) – Alexey

Смежные вопросы