Подтвердить что ты не робот

Могут ли объекты вершинного массива (VAO) совместно использоваться в EAGLContexts в OpenGL ES?

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

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

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

Это прекрасно работает. Теперь я недавно узнал о Объектах вершинного массива в качестве способа кэширования состояния OpenGL, связанного с отображением содержимого определенных буферов. Он выглядит красиво и уменьшает код проверки и настройки состояния шаблона, необходимый для создания каждой сетки. Помимо всего этого, Apple также рекомендует использовать их в руководстве Рекомендации по работе с данными Vertex Data.

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

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

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

- (void)generate {

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

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

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

4b9b3361

Ответ 1

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

Если объекты массива вершин могут быть разделены на несколько OpenGL ES      контексты?

ПОСТАНОВИЛИ: Нет. Рабочая группа OpenGL ES взяла соломенный опрос и      согласились с тем, что совместимость с OpenGL и простота внедрения      были более важными, чем создание первого не общего общего объекта      в OpenGL ES.

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