2015-04-09 4 views
1

Сегодня я проводил бенчмаркинг с использованием C# и OpenTK, чтобы увидеть, сколько я мог бы сделать до того, как частота кадров снизится. Числа, которые я получил, были довольно астрономическими, и я вполне доволен результатом моих тестов.Возможная оптимизация производительности рендеринга

В моем проекте я загружаю обезьяну блендера, которая составляет 968 треугольников. Затем я примеру его и делаю его 100 раз. Это означает, что я рисую 96 800 треугольников на кадр. Это число намного превосходит все, что мне нужно будет отображать во время любой сцены в моей игре. И после этого я толкнул его еще дальше и отобрал 2000 обезьян в разных местах. Я теперь получал колоссальные 1,936,000 (почти 2 миллиона треугольников на кадр), а частота кадров все еще была заблокирована со скоростью 60 кадров в секунду! Это число просто взорвало мой разум. Я подтолкнул его еще дальше, и, наконец, частота кадров начала уменьшаться, но это просто означает, что предел составляет примерно 4 миллиона треугольников на кадр с помощью instancing.

Мне было просто интересно, потому что я использую некоторые устаревшие OpenGL, если это еще может быть нажато еще дальше - или я должен даже беспокоиться?

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

modelMeshID = MeshGenerator.Generate(delegate { 
      GL.Begin(PrimitiveType.Triangles); 
      foreach(Face f in model.Faces) { 
       foreach(ModelVertex p in f.Points) { 
        Vector3 v = model.Vertices[ p.Vertex ]; 
        Vector3 n = model.Normals[ p.Normal ]; 
        Vector2 tc = model.TexCoords[ p.TexCoord ]; 
        GL.Normal3(n.X , n.Y , n.Z); 
        GL.TexCoord2(tc.Y , tc.X); 
        GL.Vertex3(v.X , v.Y , v.Z); 
       } 
      } 
      GL.End(); 
     }); 

, а затем вызвать этот список й количество раз. Мой вопрос, хотя, если бы я мог ускорить это, если бы я бросил объекты VAO (объекты вершинного массива) в список отображения вместо старого GL.Vertex3 api? Будет ли этот эффект вообще? Или он создаст тот же результат с отображением списка?

Вот захват экрана несколько тысяч:

enter image description here

Мои системные требования:

CPU: AMD Athlon IIx4(quad core) 620 2.60 GHz 
Graphics Card: AMD Radeon HD 6800 
+0

Какое оборудование вы используете? –

+0

Никогда не рисуйте 'GL' с вершинами, [если вы можете буферизировать] (http://www.opentk.com/doc/graphics/geometry/vertex-arrays) их ... –

+0

@RetoKoradi см. Мое обновление. – Krythic

ответ

3

Мой вопрос, хотя, если я мог бы ускорить этот процесс, если я бросил ВАО (в Vertex Array Objects) в список отображения вместо старого GL.Vertex3 api? Будет ли это вообще эффект? Или он создаст тот же результат с отображением списка?

No.

Основная проблема, которую вы собираетесь запустить в том, что списки отображения и Vertex Массивы не идут хорошо друг с другом. Используя объекты буфера, они видят работу, но сами списки отображения являются устаревшими, как API-интерфейс непосредственного интерфейса.

Однако, даже если вам удастся получить чертеж VBO из списка справа, будет небольшое улучшение: при компиляции списка отображения, который знает драйвер OpenGL, все, что прибывает, будет «заморожено», в итоге. Это позволяет провести некоторую очень агрессивную внутреннюю оптимизацию; все данные геометрии будут собраны в буферный объект на графическом процессоре, изменения состояния будут объединены. AMD не так хороша в этой игре, как NVidia, но они неплохие; списки отображения сильно используются в приложениях САПР, и до того, как ATI обратилась к рынку развлечений, они были сосредоточены на CAD, поэтому их реализация списка отображения неплохая. Если вы собрали все необходимые изменения состояния, необходимые для конкретного вызова чертежа в списке отображения, то при вызове списка отображения вы, скорее всего, перейдете в быстрый путь.

Я подтолкнул его еще дальше, и, наконец, частота кадров начала падать, но это означает, что предел составляет примерно 4 миллиона треугольников на кадр с инстансом.

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

Отображаемые списки впечатляюще эффективны. То, что они были удалены из современного OpenGL, главным образом потому, что их можно эффективно использовать только с командами рисования немедленного режима. Также недавние вещи, такие как преобразование обратной связи и условного рендеринга, было бы очень сложно интегрировать в списки отображения. Поэтому они были удалены; и это действительно так, потому что Дисплейные списки неловко работают.

Теперь, если вы посмотрите на Vulkan, необходимо создать так много команд рисования (изменения состояния, привязки ресурсов и т. Д.) В командных буферах и повторно использовать их для разных данных. Это похоже на то, что вы можете создать несколько списков отображения и заставить их делать детей.

+0

Это должен быть принятый ответ – Domi

+1

@ Domi А теперь это так. – Krythic

2

Использование списков вершин, begin и end вызывает геометрия обезьяны для отправки в GPU на каждой итерации, проходя через PCI-E, который является самым медленным интерфейсом памяти, который у вас есть во время рендеринга. Кроме того, в зависимости от вашей реализации GL каждый вызов GL может иметь более или менее накладные расходы на собственные. Если вы использовали объекты буфера, все эти накладные расходы исчезнут, потому что вы отправляете обезьяну только один раз, а затем все, что вам нужно, - это призыв на призыв на каждую итерацию.

Однако геометрия обезьяны крошечная (всего несколько килобайт), поэтому отправка ее по шине PCI-E (примерно на 16 ГБ/с?) Плюс несколько сотен итераций «петли геометрии», даже не принимать миллисекунды. И даже это не коснется вашей частоты кадров, потому что, если вы явно не synchronizing, он будет полностью поглощен конвейерной обработкой: копирование и вызов рисования будут выполняться, пока графический процессор все еще занят, показывая предыдущий кадр. В то время графический процессор начинает показывать следующий кадр, данные уже есть.

Именно поэтому я угадываю, учитывая, что у вас есть довольно оптимизированная реализация GL (хорошие драйверы), использующая буферные объекты, не приведет к ускорению. Обратите внимание, что в условиях большей и более сложной геометрии и операций рендеринга объекты буфера, конечно, станут решающими для производительности. Маленькие буферы могут даже оставаться в кеше на чипе между обратными вызовами.

Тем не менее, в качестве серьезного скоростно-урод, вы определенно хотите, чтобы перепроверить и подтвердить эти виды guesstimates :)

+0

Как вы думаете, вы могли бы привести пример в коде? Даже псевдокода было бы достаточно. – Krythic

+0

Я написал [кучу примитивов] (https://www.assembla.com/code/squishy-sim/git/nodes/master/Squishy.GL), чтобы немного облегчить ситуацию несколько лет назад (на C++) которые затем используются [этим примером кода] (https://www.assembla.com/code/squishy-sim/git/nodes/master/Squishy.GL.Samples/01_my_first_triangle/01_my_first_triangle.cpp), который иллюстрирует базовую программу макета приложения GL с поддержкой BO. Не уверен, что это вам поможет? Он включает в себя SDL (для простого графического интерфейса и клавиатуры, ввода мыши и т. Д.) И связей с GLSL, что делает его не минимальным, хотя ... – Domi

+2

Nitpick; вызов ничьей не требует кругового перехода к графическому процессору. –

Смежные вопросы