Случайный сбой в приложении iPhone OpenGL при навигации - PullRequest
10 голосов
/ 04 ноября 2010

Я работаю над приложением для iPhone, которое представляет собой гибрид OpenGL ES и обычный пользовательский интерфейс iPhone. Это означает, что EAGLView приветствует пользователя, затем некоторые обычные UIView s, которые надвигаются на него (есть UINavigationController в качестве корневого контроллера).

У меня случайный (но очень частый) сбой при переходе назад из подпредставления. Вот трассировка стека (... censored ...) из сборки Release, но в Debug она вылетает точно так же.

#0  0x006863d0 in GetFBOBuffers ()
#1  0x00660120 in TerminateScene ()
#2  0x00660314 in FlushScene ()
#3  0x00660cd4 in FlushHW ()
#4  0x0066a6a0 in GLESPresentView ()
#5  0x323533a4 in -[EAGLContext presentRenderbuffer:] ()
#6  0x000026c0 in -[EAGLView presentFramebuffer] (self=0x11ce60, _cmd=<value temporarily unavailable, due to optimizations>) at (...)/Classes/EAGLView.m:157
#7  0x00004fdc in -[(...)ViewController drawFrame] (self=<value temporarily unavailable, due to optimizations>, _cmd=<value temporarily unavailable, due to optimizations>) at (...)    ViewController.m:380
#8  0x336ebd9a in __NSFireTimer ()
#9  0x323f54c2 in CFRunLoopRunSpecific ()
#10 0x323f4c1e in CFRunLoopRunInMode ()
#11 0x335051c8 in GSEventRunModal ()
#12 0x324a6c30 in -[UIApplication _run] ()
#13 0x324a5230 in UIApplicationMain ()
#14 0x0000214c in main (argc=1, argv=0x2ffff568) at (...)/main.m:14

Вот список вещей, которые я знаю:

  • Мое приложение не получает предупреждение о памяти.
  • Мое приложение не обнаружило утечек в разделе "Инструменты".
  • Нет сбоя на симуляторе, но иногда очень заметное отставание.
  • В инструментах / OpenGL / ResourceBytes имеется значительное количество выпущенных данных непосредственно перед сбоем.
  • Я использую как VBO, так и массивы vertex / texcoord / normals.

Так что я знаю, что это должны быть какие-то данные, которые выпускаются или уничтожаются, но я не знаю, как найти какие. Любые советы и рекомендации будут оценены; -)

ОБНОВЛЕНИЕ:

После установки некоторых точек останова, перемещения по стеку и поиска переменных, я нашел причину сбоя, но источник пока не найден.

В EAGLView, в методе presentFramebuffer, где и когда происходит сбой, ivar colorRenderBuffer равен 0, если я могу поверить gdb, хотя попытка установить точку останова, когда она равна 0, не работает.

Кажется, что deleteFrameBuffer вызов от layoutSubviews не соответствует createFramebuffer.

ОБНОВЛЕНИЕ 2:

Много точек останова позже ... Я обнаружил неправильную ситуацию: [EAGLView layoutSubviews] вызывают в середине drawFrame! Таким образом, буферы удаляются во время использования ... BAM!

Теперь, как мне исправить , что ?

Ответы [ 4 ]

3 голосов
/ 04 ноября 2010

Я еще не нашел «правильного» исправления, но я добавил обходной путь.

В presentFramebuffer я установил логическое значение для рендеринга:

if (context)
{
    isRendering_PATCH_VARIABLE = YES;

    [EAGLContext setCurrentContext:context];

    glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);

    success = [context presentRenderbuffer:GL_RENDERBUFFER_OES];

    glBindRenderbufferOES(GL_RENDERBUFFER_OES, 0);

    isRendering_PATCH_VARIABLE = NO;
}

и в deleteFramebuffer я проверяю это логическое значение:

if (isRendering_PATCH_VARIABLE)
{
    NSLog(@"GOTCHA - CRASH AVOIDED");   
}

if (context && !isRendering_PATCH_VARIABLE)
{
    // ...
}

Похоже, у него нет побочных эффектов (например, неработающий дисплей и т. Д.), Поэтому я пока оставлю это так.

3 голосов
/ 10 ноября 2010

Вот дикое предположение, основанное на том, что я недавно сделал.

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

Мой первый шаг был похож на пример OpenGL ES, предоставленный с Xcode, в котором я вызвал init на ES? Renderer. Но после этого я остановил процесс, чтобы загрузить другие ресурсы.

Короче говоря, из-за моей перестановки кода [EAGLView layoutSubviews] никогда не вызывался после моей инициализации. У меня не было сбоев, но после этого ничего особенного не произошло.

Что мне нужно было сделать, так это то, что после того, как я завершил инициализацию контекста OpenGL и загрузил все мои данные, мне пришлось вручную вызвать [EAGLView layoutSubviews]. Это, казалось, исправило вещи для меня.

Может быть, вам нужно попробовать что-то подобное. После того, как вы инициализируете свой контекст и данные OpenGL, позвоните по номеру [EAGLView layoutSubviews], прежде чем приступить к процедурам рисования. Может быть, это остановит этот вызов, снова появляясь на вашем этапе рендеринга и вылетая.

1 голос
/ 29 августа 2012

У меня была эта проблема, и я некоторое время использовал вашу работу.Однако недавно я заметил, что сбой произошел только при изменении ориентации.

Я изменил свой контроллер корневого представления, чтобы приостановить отображение ссылки в WillRotate ... и возобновить его в DidRotateFrom ... Делегатские функции.

Это решило проблему, и мне больше не нужна работа по взлому.

К сожалению, похоже, что ваша проблема немного отличается, но я решил опубликовать это простов случае.

1 голос
/ 04 ноября 2010

Удар в темноте: на вашем устройстве недостаточно памяти, приложение получает предупреждение о памяти, а контроллер, отвечающий за представление GL, освобождает представление, с чем вы не считали? Устранена ли проблема при подавлении значения по умолчанию didReceiveMemoryWarning?

- (void) didReceiveMemoryWarning { /* nothing we can do, sorry */ }

… или, может быть, вы вызываете OpenGL из другого потока, у которого нет контекста?

...