glGetError() не работает до следующего кадра

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

Это на iOS, и я использую GLKViewController, GLKView и EAGLContext для рисования.

Обобщенная версия цикла рендеринга выглядит примерно так:

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
   // At this point, GLKView's EAGLContext should be the active context

   checkGlGetError();

   if (!isTextureInit || geometryChanged)
   {
        setupRenderTextureAndRenderbuffer();
   } 
    glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_originalFramebufferId);
    glBindFramebuffer(GL_FRAMEBUFFER, _framebufferId);

    // a. Some complex operations
    // b. Some rendering on the texture framebuffer

    glBindFramebuffer(GL_FRAMEBUFFER, _originalFramebufferId);

    // c. Some additional complex operations
    // d. Render the texture on screen

    checkGlGetError();
}

Это приводит к сбою приложения. Проблема в том, что последний checkGlGetError() вызов первого отрендеренного кадра не выдает никакой ошибки (и ничего не отображается на экране).

Первый вызов checkGlGetError() второго визуализированного кадра дает загадочное GL_INVALID_ENUM, и вскоре после этого приложение аварийно завершает работу.

Если я заменю свой цикл рендеринга на это:

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    checkGlGetError();

    // a. Some complex operations
    // b. Some rendering on the screen

    checkGlGetError();
}

Все работает, ошибок не выдает. Но: почему glGetError() не перехватывает ошибку сразу после ошибочного вызова OpenGL? Почему он сообщает об этом только в начале следующего кадра?

Код с ошибкой довольно длинный, и без дополнительных указаний, где именно ошибка, отлаживать его довольно сложно.


ОБНОВИТЬ

Я загрузил весь код здесь. Это незавершенный порт Google CardboardSDK (decompiled) с Java на Objective-C++, который я пытаюсь выполнить.

Основной цикл рендеринга находится в классе CardboardViewController. Команда OpenGL, вызывающая сбой, должна относиться к классу DistortionRenderer (функция которого состоит в том, чтобы брать простые стереоскопические окна просмотра и отображать их на текстуре, чтобы применить искажение объектива к каждому).

Если вы установите distortionCorrectionEnabled CardboardViewController на NO, сбой исчезнет.


person Ricardo Sanchez-Saez    schedule 12.01.2015    source источник


Ответы (1)


Здесь недостаточно информации для отладки вашей проблемы, поэтому вместо этого общее примечание об отладке...

glGetError — это плохой способ отладки проблем GL в целом, но особенно в iOS, и тем более, когда вы используете GLKView или другие системы, в которых GL работает от вашего имени. Вполне возможно, вы устанавливаете какое-то состояние, которое не приводит к ошибке до тех пор, пока GLKView не начнет передавать данные в GPU (когда ваш drawRect:/glkView:drawInRect: вернется).

Попробуйте использовать Инструмент захвата кадра Xcode. Вместо того, чтобы требовать, чтобы вы вставляли glGetError проверок по всему коду (и удостоверились, что они отключены в релизных сборках), а затем пытались разобраться в результатах, он показывает вам ошибки (по крайней мере, с некоторым уровнем объяснения) для каждого вызов, в том числе сделанный от вашего имени в системном коде. И он показывает полный граф состояний и моментальные снимки кадра, отображаемого вызов за вызовом, поэтому вы можете заранее определить, устанавливаете ли вы какое-либо состояние, которое вызывает проблему.


Хорошо, одна мысль, которая может быть характерна для вашей проблемы: попробуйте использовать bindDrawable на GLKView вместо того, чтобы напрямую связывать его фреймбуфер с glBindFramebuffer.

person rickster    schedule 12.01.2015
comment
Спасибо, это в высшей степени полезно. Я думаю, что смогу отладить его самостоятельно, используя инструмент Xcode Frame Capture. Тем не менее, пока вы отвечали, я просто добавил к вопросу исходный код и более подробную информацию. - person Ricardo Sanchez-Saez; 13.01.2015
comment
Использование bindDrawable устранило одну проблему, связанную с отсутствием буфера глубины. Но как ни странно, теперь кадр OpenGL сообщает о недопустимых ошибках перечисления в обеих этих двух строках: glGetIntegerv(GL_CULL_FACE, &this->cullFaceEnabled); glGetIntegerv(GL_SCISSOR_TEST, &this->scissorTestEnabled);. Согласно документации OpenGL, они кажутся действительными. есть идеи? - person Ricardo Sanchez-Saez; 13.01.2015
comment
Хорошо, теперь я вижу, что вместо этих двух вы должны использовать glIsEnabled() (возможно, glGetIntegerv() работает для этих двух аргументов на Android, но не на iOS). Попытка исправить дополнительную проблему сейчас. - person Ricardo Sanchez-Saez; 13.01.2015