#performance #opengl #stream #vbo
#Производительность #OpenGL #поток #vbo
Вопрос:
Я немного поэкспериментировал и теперь могу отображать на экране около 3 миллионов GL_QUADS с помощью
glDrawArrays(GL_QUADS, 0, nVertexCount);
Я также использую множественную буферизацию, циклически перебираю 18 объектов вершинного буфера по 1 миллиону вершин каждый. Каждая позиция вершины вычисляется с использованием сжатых данных, хранящихся в куче, и простых вычислений. Я использую
ptr = (float*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
и
glUnmapBuffer(GL_ARRAY_BUFFER);
для записи каждой отдельной вершины в объекты буфера в каждом кадре. Когда объект буфера заполнен, я разархивирую его, вызываю glDrawArrays и связываю и сопоставляю следующий VBO для потоковой передачи дополнительных данных вершин. Когда все 18 были использованы, я логически связываю первый и начинаю заново.
По моему опыту, использование сопоставления VBO почти в два раза быстрее, чем использование массивов кучи для данных вершин. Откуда я знаю? Потому что, поскольку я рендерю 3 миллиона GL_QUADS, частота кадров значительно ниже 30 кадров в секунду. Я просто могу наблюдать своими глазами, как частота кадров увеличивается в два раза для VBO.
Я также сделал замечание, что вызов glDrawArrays дважды подряд для каждого заполненного объекта буфера вершин (что приводит к удвоению количества отображаемых квадратиков, но после попытки потоковой передачи данных вершин) — будет лишь незначительно медленнее, чем рендеринг только один раз. Поэтому я предполагаю, что основным узким местом является потоковая передача данных вершин в объекты буфера вершин (двухъядерный процессор с частотой 2 ГГц занят этим на 60% !!).
Прямо сейчас каждая вершина принимает 3 поплавка плюс 2 поплавка для координации текстуры. (Всего 20 байт). Думаю, я мог бы сократить это количество до 3 GL_SHORT плюс 2 GL_SHORT для координации текстур. использование матриц перевода (всего 5 байт), но это ускорило бы только в 4 раза. (И каким-то образом sizeof(GL_SHORT) дает 4 в моей системе, поэтому я тоже не уверен в этом.)
В любом случае, есть игры, которые даже уже довольно старые, но отображают на экране гораздо больше, чем 3 миллиона примитивов в каждом кадре afaik (и им неизбежно приходится транслировать эти вершины, потому что ни один графический процессор не может вместить столько данных) и при этом получают приличную частоту кадров более 100 кадров в секунду!
Я уверен, что мне все еще не хватает какого-то важного момента в процессе, но я просто не могу понять, что это такое. Есть предложения?
РЕДАКТИРОВАТЬ: это свободные квадратики, как в системе частиц. (Или, скорее, потому, что у каждого может получиться своя текстура (текстуры взяты из подтекстов одной, поэтому нет обширной привязки ;)))
Комментарии:
1. Являются ли эти свободные квадратики (каждый квадратик имеет вершины, которые не зависят от других квадратиков, например, в системе частиц) или это сетка, состоящая из квадратиков?
2. Кстати: «… они уже довольно старые, но отображают гораздо больше, чем 3 миллиона … » . Я бы действительно сомневался в этом. Тот факт, что мир состоит из более чем 3 миллионов треугольников, не означает, что все они отображаются в каждом кадре. Подумайте о отбраковке усеченного представления, отбраковке портала, PVS, …, чтобы назвать несколько методов, которые, несомненно, применяются в этих играх. Но это не значит, что это помогает в вашем случае, просто чтобы уточнить, что вы не можете просто проводить такие простые сравнения между сложностью сцены и производительностью.
3. @Nicol Bolas: свободные квадратики. Смотрите мою правку. у Кристиана Рау: у меня есть отбраковка усеченного числа, но его использование отнимает больше ресурсов процессора, чем просто запись 20 байт. В моем случае я пытаюсь нарисовать даже более 3 миллионов квадратиков. Если 15 из 40 миллионов будут эффективно удалены позже, это здорово, но мне все равно нужно будет отрендерить более 3 миллионов…
4. @Fejwin В настоящее время, во времена чрезмерной пакетной обработки и рендеринга экземпляров, такие методы, связанные с процессором, такие как отбраковка усеченного конуса и тому подобное, не всегда дают желаемый прирост производительности (как в вашем случае, кажется). Вот почему вы не можете проводить такие простые сравнения с другими приложениями, которые были созданы с учетом совершенно других целей оптимизации, не говоря уже о том, что предположение, что они отображают более 3 миллионов треугольников за кадр, вероятно, в любом случае было неверным.
5. @ChristianRau Они отображают меньше примитивов, чем 3 миллиона? Честно говоря, я не знаю точно, сколько в среднем. Возможно, вы можете дать мне подсказку? В принципе, я понимаю, что мой подход не оптимизирован. Любые предложения, что я мог бы сделать?
Ответ №1:
Я уверен, что мне все еще не хватает какого-то важного момента в процессе
Вопрос должен быть в том, нужно ли мне рисовать 3 МБ треугольников?, а не как я могу преодолеть аппаратный предел?
Ограничение, которое вы должны признать, должно быть аппаратным. Скорости передачи, тактовая частота графического процессора и тактовая частота памяти являются характеристиками, которые невозможно переопределить без более нового оборудования. Действительно, вы должны попытаться эффективно использовать текущее оборудование.
Насколько я понимаю, вам необходимо обновлять буферы вершин во время рендеринга; таким образом, вы сопоставляете объект буфера, обновляете данные, разархивируете и визуализируете. Я полагаю, вы делаете это повторно. В этом случае вы должны учитывать скорость передачи данных с CPU на GPU; можете ли вы уменьшить объем данных, необходимых для рендеринга сцены? Может быть, интерполяция позиций ключевых вершин?
Например, если мне нужно отобразить местность, я могу отправить миллиарды треугольников для рендеринга идеальной местности. Но, конечно, я могу достичь того же результата, используя только самый важный. Использование меньшего количества треугольников без искажения хорошего результата позволяет мне делать все больше и больше.
При разрешении 1920×1080 количество пикселей составляет 2 МБ… Мне нужно использовать 2 МБ треугольников для его рисования? Возможно, фрагментный шейдер будет работать лучше.
Существует множество технологий, используемых для снижения нагрузки на обработку (как на CPU, так и на GPU) и скорости передачи:
- Отбраковка
- уровень детализации
- Инстанцированный рендеринг
- Анимация ключевых кадров
- скелетная анимация
Комментарии:
1. Только сейчас я понял, что вы совершенно правы! Я поместил все свои вершины в VBO и визуализировал их без обновления — результат все еще был очень медленным. Следовательно, это аппаратное ограничение! =) Сейчас я сосредоточусь на переходе от квадратиков к треугольникам, поскольку они не устарели и, надеюсь, немного повысят производительность. С этого момента я буду хранить все свои вершины в VBO навсегда без чрезмерного обновления, поскольку графический процессор все равно не может освободить всю свою память от задержек. Я узнал об этом сегодня! Большое вам спасибо! =)
Ответ №2:
На самом деле есть довольно много вещей, которые вы можете сделать (или которые сделаны для увеличения пропускной способности). Я просто просматриваю несколько, так как это может (и делает) заполнить (или больше) книги (книг).
- Рисуйте треугольники, а не квадратики. В конечном итоге квадратики все равно будут разделены на три (графическое оборудование оптимизировано для обработки треугольников).
- Когда у вас есть большие объекты, состоящие из такого большого количества треугольников, вы будете использовать полосы и веера везде, где сможете (уменьшает количество передаваемых данных вершин с 3N до N 2).
- Умное кэширование данных (особенно при рендеринге больших сцен) имеет жизненно важное значение. Как вы заметили, передача данных является узким местом в системе. Таким образом, в основном каждый движок сильно оптимизирован, чтобы избежать ненужной передачи данных. Однако это зависит от приложения. Об этом также можно написать много книг (и было написано).
Я могу рекомендовать эти книги в качестве вступления к теме:
Комментарии:
1. Почему «Рисовать треугольники, а не квадратики»? это было бы просто крайне неэффективно, не так ли? Квадратик разделяет свои последние 2 вершины. так же, как это делает треугольная полоса. просто используйте одну вершину для следующего tri. я не думаю, что они были бы настолько глупы, чтобы обманывать последние две вершины для каждого треугольника, тратя тонны памяти gpu, как будто каким-то образом индексация будет быстрее. я точно знаю, что больше памяти делает это намного медленнее. пример, один цвет int, против 3 плавающих rgb. если бы opengl выполнял какую-либо автоматическую оптимизацию для заданных данных вершин, они наверняка преобразовали бы числа с плавающей точкой в байты. они этого не делают.
2. и причина в том, что вы определяете, как будет использоваться загружаемая вами память vbo.
3. также вся причина индексации vbo заключается в экономии памяти вершин при использовании треугольников. казалось, что quads просто реализует это автоматически.
Ответ №3:
Каждая позиция вершины вычисляется с использованием сжатых данных, хранящихся в куче, и простых вычислений.
Может быть, вместо этого это может сделать вершинный или геометрический шейдер?
В любом случае, есть игры, которые даже уже довольно старые, но отображают на экране гораздо больше, чем 3 миллиона примитивов в каждом кадре afaik (и им неизбежно приходится передавать эти вершины, потому что ни один графический процессор не может хранить столько данных)
3000000 * 20 bytes = 60 megabytes
это легко доступно даже для старых графических процессоров.
Комментарии:
1. Это всего лишь простые операции добавления и сохранения, возможно, 30 байт для данных вершин объемом до 240 байт. Мой пример с 3 миллионами вершин, безусловно, довольно мал. Если вы возьмете 30 миллионов, никакая видеокарта не смогла бы справиться с этим 3 года назад.
2. @Fejwin: Вы забываете, что большая часть того, что вы видите на экране, — это повторно используемые данные. Вы можете, например, иметь только небольшое количество моделей человеческих персонажей, но путем изменения текстур и настройки нескольких матриц скинов придать им очень четкий вид. Также 3 года назад видеокарты с объемом памяти> 512 МБ были довольно распространены. Например, я все еще работаю и разрабатываю GeForce8800GTX с 768 МБ оперативной памяти, которую я купил в ноябре 2006 года, то есть почти 5 лет назад. До этого у меня был GeForce7800 с 256 МБ оперативной памяти, а до этого Radeon9800 с 256 МБ тоже купил 2003.
3. @datenwolf: Кажется, я пытаюсь работать на видеокарте 2008 года, которая отстает от вашей 2006 года! =) (Не стоит ожидать многого от ноутбука на графическом процессоре). Я думаю, вы, ребята, правы! Я мог бы хранить все необходимые данные на графическом процессоре. Потому что даже тогда графический процессор не мог отобразить все это за один раз с хорошей производительностью, так что это аппаратное ограничение.