Вопрос

Я пишу приложение для iPhone, которое использует UIView с CAEAGLayer в качестве слоя.Все в порядке и работает, за исключением 1 небольшой проблемы:иногда происходит сбой с 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 и layout:
В этом:

    ...
    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);
    ...

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

    - (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));
    }

Сам метод рисования выглядит следующим образом:

        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];

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

Это было полезно?

Решение

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top