Оптимизация приложения OpenGL ES.Должен ли я избегать вызова glVertexPointer, когда это возможно? - PullRequest
3 голосов
/ 25 января 2011

Я разрабатываю игру для iPhone на OpenGL ES 1.1;У меня много текстурированных квадратов в структуре данных, где у каждого узла есть список дочерних узлов.Поэтому я просматриваю структуру от корня и выполняю рендеринг каждого четырехугольника, потом его потомков и т. Д.

Дело в том, что для каждого четырехугольника я вызываю glVertexPointer, чтобы установить вершины.

  • Должен ли я избегать называть его для каждого четырехугольника?Например, повысит ли производительность вызов только один раз?
  • glVertexPointer копирует вершины в память графического процессора или просто сохраняет указатель?

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

Спасибо.

1 Ответ

10 голосов
/ 25 января 2011

glVertexPointer сохраняет только указатель, но вызывает изменение состояния в драйвере OpenGL и явную синхронизацию, поэтому стоит довольно дорого.Обычно, когда вы говорите «вот мои данные, пожалуйста, рисуйте», графический процессор начинает рисовать и продолжает делать это параллельно с тем, что происходит на процессоре, так долго, как это возможно.Когда вы изменяете состояние рендеринга, он должен завершить все, что делал в старом состоянии.Таким образом, изменяя один раз на каждый квад, вы фактически заставляете то, что может быть одновременной обработкой, быть последовательным.Следовательно, отказ от glVertexPointer (и, по-видимому, glDrawArrays или glDrawElements?) Для каждого квада даст вам значительное преимущество.

Немедленная оптимизация состоит в том, чтобы просто вести подсчет общего количества квадов в структуре данных, выделить один целевой буфер для вершин, который по крайней мере такого размера, и все квады копируют свою геометрию в цельбуфера вместо вызова glVertexPointer каждый раз.Затем вызовите glVertexPointer и вызовы вашего рисунка (также, надеюсь, будут сжаты только до одного вызова) с одним большим массивом в конце.Это немного дороже на стороне ЦП, но параллелизм и отсутствие повторяющихся синхронизаций GPU / ЦП должны спасти вас очень много.

Хотя мы находимся на цыпочках по темам, которые в настоящее время находятся в NDA, я настоятельно рекомендую вам взглянуть на бета-версию Xcode 4,Среди других функций, которые Apple официально представила в качестве , является профилировщиком OpenGL ES.Таким образом, вы можете легко сравнить подходы.

Чтобы скопировать данные в графический процессор, вам нужно использовать объект буфера вершин.Это означает создание буфера с glGenBuffers, передачу данных на него с glBufferData и последующую отправку glVertexPointer с адресом, например, 0, если первый байт в загруженных вами данных является первым байтом ваших вершин.В ES 1.x вы можете загружать данные как GL_DYNAMIC_DRAW, чтобы пометить, что вы собираетесь обновлять их довольно часто и извлекать из них довольно часто.Вероятно, это стоит делать, если вы можете попасть в положение, в котором вы рисуете чаще, чем загружаете.

Если вы когда-нибудь переключитесь на ES 2.x, есть также GL_STREAM_DRAW, который, возможно, стоит изучитьно не имеет прямого отношения к вашему вопросу.Я упомянул об этом, поскольку он, скорее всего, появится, если вы Google для объектов буфера вершин, доступных на настольном OpenGL.Варианты для ES 1.x - только GL_STATIC_DRAW и GL_DYNAMIC_DRAW.

Я только недавно работал над приложением iPad ES 1.x с объектами, которые меняют каждый кадр, но рисуются дважды для используемого конвейера рендеринга.,На экране всего пять таких объектов, каждая из 40 вершин, но переход от начальной реализации к реализации VBO сократил на 20% мое общее время обработки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...