Могут ли объекты Vertex Array (VAO) использоваться совместно с EAGLContexts в OpenGL ES? - PullRequest
19 голосов
/ 19 августа 2011

Спойлер: Я вполне уверен, что ответ NO, но это только после дня очень расстроенной отладки. Теперь я хотел бы знать, так ли это на самом деле (и если да, то как я мог знать), или я просто делаю что-то совершенно неправильно.

Вот ситуация. Я использую OpenGL ES 2.0 для рендеринга некоторых мешей, загружаемых из разных файлов (.obj, .md2 и т. Д.). Ради производительности и пользовательского опыта я делегирую фактическую загрузку этих мешей и связанных с ними текстур фоновому потоку с помощью GCD.

За Инструкции Apple , в каждом фоновом потоке я создаю и устанавливаю новый EAGLContext с тем же shareGroup, что и основной контекст рендеринга. Это позволяет объектам OpenGL, таким как объекты текстуры и буфера, которые были созданы в фоновом потоке, немедленно использоваться контекстом в основном потоке.

Это прекрасно работает. Теперь я недавно узнал о объектах Vertex Array как способ кеширования состояния OpenGL, связанного с рендерингом содержимого определенных буферов. Это выглядит красиво, и сокращает проверку состояния шаблона и код установки, необходимый для рендеринга каждой сетки. Кроме того, Apple также рекомендует использовать их в своем руководстве Best Practices для работы с данными вершин .

Но у меня были серьезные проблемы с тем, чтобы заставить ВАО работать на меня вообще. Как и при любой загрузке, я бы загружал сетку из файла в память в фоновом потоке, а затем генерировал все связанные объекты OpenGL. В первый раз, когда я пытался дозвониться до glDrawElements() с помощью VAO, приложение вылетает с EXC_BAD_ACCESS. Без ВАО это хорошо.

Отладка EXC_BAD_ACCESS - это боль, особенно когда NSZombies не поможет (что они, очевидно, не помогут), но после некоторого времени анализа захваченных кадров OpenGL я понял, что при создании VAO на заднем плане поток работал нормально (без GL_ERROR и ненулевого идентификатора), когда пришло время связываться с VAO в основном потоке, я получил бы GL_INVALID_OPERATION, что в состоянии docs случается при попытке привязки к несуществующей VAO. И, конечно же, при просмотре всех объектов в текущем контексте во время рендеринга не видно ни одного VAO, , а всех VBO, которые были сгенерированы с помощью VAO AT THE. ЖЕ ВРЕМЯ присутствуют . Если я загружаю VAO в основной поток, он работает нормально. Очень расстраивает.

Я перевел код загрузки в более атомарную форму:

- (void)generate {

    glGenVertexArraysOES(1, &_vao);
    glBindVertexArrayOES(_vao);

    _vbos = malloc(sizeof(GLuint) * 4);
    glGenBuffers(4, vbos);
}

Когда вышеописанное выполняется в фоновом потоке с допустимым EAGLContext с тем же shareGroup, что и основной контекст, основной контекст будет иметь 4 VBO, но без VAO. Если я выполню его в главном потоке с основным контекстом, у него будет 4 VBO и VAO. Это приводит меня к выводу, что существует некоторое странное исключение из природы совместного использования объектов EAGLContext s при работе с VAO. Если бы это было на самом деле, я бы действительно ожидал, что документы Apple заметят это где-то. Это очень неудобно, чтобы открывать маленькие лакомые кусочки вручную. Это тот случай, или я что-то упустил?

1 Ответ

21 голосов
/ 19 августа 2011

Согласно this , OpenGL-ES явно запрещает совместное использование объектов VAO:

Должны ли объекты массива вершин быть доступными для нескольких OpenGL ES контексты?

РЕШЕНО: Нет. Рабочая группа OpenGL ES провела опрос и согласился, что совместимость с OpenGL и простота реализации были более важны, чем создание первого не общего объекта с именем в OpenGL ES.

Как вы заметили, VBO по-прежнему доступны для совместного использования, поэтому вам просто нужно создать VAO для каждого контекста, связывающего общий VBO.

...