Хот-тейк: количество полигонов (почти никогда) не влияет на производительность

Развенчиваю популярный миф, рассказываю про устройство видеокарт и поясняю за оптимизации

Просчёт геометрии, тогда и сейчас

Давным-давно — во времена этак DirectX 7 и OpenGL 1 — видеокарты отрисовывали графику на так называемом фиксированном конвейере. Геометрия сцены просчитывалась по заложенному с завода алгоритму на специально выделенных для этого вычислительных блоках. Производительность блоков, очевидно, бесконечной не была, а потому фактически существовало и ограничение на количество полигонов на сцене. Больше полигонов — геометрия считается дольше — ниже FPS.

В середине нулевых произошла революция — ATI (ныне AMD) явила миру чип Xenos, разработанный для Xbox 360, где фиксированный конвейер заменился на программируемый (шейдерный). Вскоре это решение переняла и Nvidia с линейкой Tesla. Специализированные блоки были заменены на универсальные процессоры, и программист писал для них программы-шейдеры, одни из которых занимались просчётом геометрии (вершинные шейдеры), а другие — непосредственно растеризацией полигонов: наложением текстур, затенением, и так далее (фрагментные, они же пиксельные, шейдеры). То есть один и тот же чип может пиксель на экране отрендерить, а может и полигон посчитать — это задачи одного класса сложности. С тех пор никакого железного ограничения на количество полигонов не существует, ресурсы видеокарты динамически распределяются между этими задачами в зависимости от нужд конкретной сцены.

Производительность 40-го поколения Nvidia
Производительность 40-го поколения Nvidia

А ресурсы у современных видеокарт огромны. Производительность последних поколений измеряется десятками терафлопс — то есть они способны совершать десятки триллионов операций в секунду. Конечно, просчёт геометрии одного полигона — это не одна операция, а десятки, а то и сотни. К тому же вы, как геймер, естественно хотите, чтобы за эту секунду видеокарта успевала отрисовать порядка 60—120 кадров. Но даже принимая всё это во внимание, получается: чтобы ваш фпс упал на 1 %, вам надо добавить на сцену миллионы лишних полигонов.

Посмотрим на это с другой стороны. У любой современной игры есть пост-процессинг — цветокоррекция, размытие, хроматическая абберация, и прочее, и прочее. Технически, это огромный фрагментный шейдер, который проходится по всему экрану. А фрагментов у вас на экране миллионы. В случае минимального по современным меркам сетапа — FullHD-монитор (1920x1080 пикселей), отсутствие какого-либо сглаживания (один фрагмент на пиксель) — их примерно два миллиона. Опять получается, что нужно добавить на сцену миллионы лишних полигонов, чтобы нагрузить видеокарту задачей, сравнимой по сложности с цветокором — не с рендерингом!

Может, эти миллионы полигонов требуют слишком много памяти? Да опять нет, пару десятков мегабайт. Сравнимо с весом одной текстуры и пренебрежимо мало в мире, в котором среднебюджетные видеокарты поставляются с 8 гигабайтами памяти.

Предварительно подытожим: усложнение геометрии (в разумных пределах) оказывает пренебрежимо малое влияние на производительность. Если вы вернёте в Starfield лица из Fallout 4, вам потребуются сотни NPC на экране, чтобы увидеть прибавку в один фпс.

Растеризация и подводные камни

Теперь углубимся в архитектуру видеокарты. Поговорим о том, что происходит в видеокарте после обработки геометрии, на каком этапе проблемы всё же возникают, и зачем нужны оптимизации вроде LOD и Nanite. Я буду использовать терминологию AMD и рассказывать на примере архитектуры RDNA, поскольку опирался на их презенташку, но у видеокарт других архитектур, в том числе зелёных, всё работает плюс-минус так же. Тем более что лишние детали я буду опускать.

Стадия растеризации в архитектуре RDNA
Стадия растеризации в архитектуре RDNA

Итак, игра рендерит объект на экране. Процессор передаёт видеокарте информацию �� модели, код шейдеров и все необходимые данные вроде текстур. Вычислительные блоки двойного назначения (Dual Compute Unit) начинают исполнять вершинные шейдеры, которые берут вершины полигонов (треугольников) по одной и просчитывают, какой точке на экране она соответствует. Эти точки передаются в сборщик примитивов (Primitive Assembler), который объединяет их обратно в треугольники, невидимые выкидывает, а видимые передаёт дальше, в Сканнер-преобразователь (Scan Converter). Преобразователь определяет, какие точки на экране относятся к этому треугольнику, и отдаёт их на растеризацию обратно в вычислительные блоки, только, соответственно, уже для работы пиксельного шейдера.

Примеры разных полигонов. Раскрашенные клетки будут отрендерены вычислительными блоками: зелёные — полезная работа, красные — работа на выброс.
Примеры разных полигонов. Раскрашенные клетки будут отрендерены вычислительными блоками: зелёные — полезная работа, красные — работа на выброс.

Тут мы подходим к корню первой проблемы. Вычислительные блоки получают на обработку не один пиксель, а квадрат 2x2 (и это не особенность RDNA, у Nvidia то же самое). Даже если какой-то из этих четырёх пикселей не относится к полигону, вычислительный блок всё равно просчитает его, а потом результат этих вычислений будет отброшен. Если наш полигон относительно большой (#1), это не страшно — процент отброшенных пикселей будет пренебрежимо мал. Однако чем меньше или уже полигон, тем больший процент работы будет потрачен впустую. В худшем случае, когда полигон занимает меньше одного пикселя (#2), на помойку отправится 75 % работы видеокарты!

Зависимость времени рендера от размера полигонов
Зависимость времени рендера от размера полигонов

В блоге G-Truc, посвящённом OpenGL, как раз рассматривался вопрос, насколько размер треугольников влияет на скорость рендера. Была написана простенькая программа, которая заполняет экран разноцветными квадратами разного размера. Квадраты размера 32x32 отрисовывались столько же времени, сколько и один квадрат на весь экран, несмотря на то, что количество полигонов увеличилось в 2000 раз. Однако при дальнейшем уменьшении размеров время начало расти экспоненциально. Не от количества полигонов, а от их размера.

Три способа триангуляции круга, протестированных Эмилем «Humus» Перссоном: веером, полосками и с максимизацией площади
Три способа триангуляции круга, протестированных Эмилем «Humus» Перссоном: веером, полосками и с максимизацией площади

Другой интересный пост из блога Эмиля «Humus» Перссона, ведущего программиста графики Epic Games, рассматривал влияние формы полигона на производительность. Его программа тестировала три разных способа поделить круг на треугольники. Лучшим способом оказалось делить круг на треугольники максимальной площади (3) — этот способ не показывал существенного снижения фпс даже при увеличении количества полигонов до 50 тысяч. Два других способа показывали сравнимую производительность на малом (порядка сотни) количестве треугольников, но проседали в разы по мере его увеличения.

Есть и вторая проблема: скорость сборщика примитивов ограничена. Конкретные цифры разнятся от видеокарты к видеокарте, но, для примера, AMD хвасталась при анонсе RDNA 3, что она увеличила эту скорость с восьми до двенадцати примитивов за такт. Опять же, в нормальных условиях это никогда не будет бутылочным горлышком: речь идёт о гигагерцах, то есть о миллиардах обрабатываемых полигонов в секунду. Однако если видеокарта обрабатывает гору маленьких полигонов, для растеризации которых достаточно пары вычислительных блоков, она может просто не успевать загружать свои тысячи ядер работой.

Скандально известная зубная щётка из Yandere Simulator, приводящая к дропу фреймрейта. Содержит более 5000 полигонов (это фигня для видеокарты), большая часть из которых тоньше одного пикселя (а вот это не фигня, заставляет видеочип работать неоптимально).
Скандально известная зубная щётка из Yandere Simulator, приводящая к дропу фреймрейта. Содержит более 5000 полигонов (это фигня для видеокарты), большая часть из которых тоньше одного пикселя (а вот это не фигня, заставляет видеочип работать неоптимально).

Как видите, само по себе количество полигонов не особо влияет на производительность, а вот их форма и размер (в пикселях) — да. И именно с этой проблемой борются различные методы оптимизации.

Знаменитый баг релизного Киберпанка, из-за которого низкополигональные LOD’ы иногда появлялись даже в упор к игроку
Знаменитый баг релизного Киберпанка, из-за которого низкополигональные LOD’ы иногда появлялись даже в упор к игроку

Один из широко известных методов — Level of Detail, он же LOD. Для каждого ассета в игре создаются низкополигональные заглушки, которыми игра подменяет объекты, находящиеся на достаточно большом расстоянии от камеры. Существует популярное заблуждение, что прирост производительности обеспечивается за счёт снижения количества полигонов на сцене, а игрок не замечает разницы, поскольку объект настолько далеко, что эти полигоны занимают всего несколько пикселей. На самом деле всё наоборот: на количество полигонов видеокарте всё равно, а вот то, что они занимают считанные пиксели — это как раз проблема, которую оптимизация и адресует.

LOD используются повсеместно. Любой хоть сколько-нибудь крупный движок — Unity, Unreal Engine, и Creation Engine тоже — поддерживает их из коробки. И даже небольшие движки, вроде OGRE, содержат инструменты автоматической генерации LOD, не требующие участия художников. В играх без LOD любой взгляд на город с высоты или на лес на горизонте приводил бы к колоссальному дропу фреймрейта.

Проблему маленьких треугольников поднимали Epic Games в своей <a href="https://api.dtf.ru/v2.8/redirect?to=https%3A%2F%2Fadvances.realtimerendering.com%2Fs2021%2FKaris_Nanite_SIGGRAPH_Advances_2021_final.pdf&postId=3705469" rel="nofollow noreferrer noopener" target="_blank">презентации Nanite</a>
Проблему маленьких треугольников поднимали Epic Games в своей презентации Nanite

Другой подход к решению этой проблемы включён в нашумевший Nanite. В случае, если на сцене присутствует маленький полигон, Nanite использует софтверный рендерер и отрисовывает его с помощью процессора. И хотя номинально процессор на порядки слабее видеокарты, это повышает производительность — согласно тестам инженеров Epic Games, в три раза.

Развитие дисплеев

Итак, видеокарте всё равно на количество полигонов, в реальных условиях она никогда не упирается в просчёт геометрии. Однако слишком маленькие полигоны заставляют растеризатор работать неоптимально — в этом случае нормально написанные игры (не такие как Yandere Simulator) прибегают к использованию оптимизаций, включённых в движки со времён царя Гороха. А знаете, от чего зависит размер полигонов, помимо их количества? Правильно — от разрешения экрана.

Статистика дисплеев геймеров по годам. Данные по <a href="https://api.dtf.ru/v2.8/redirect?to=https%3A%2F%2Fstore.steampowered.com%2Fhwsurvey%2FSteam-Hardware-Software-Survey-Welcome-to-Steam&postId=3705469" rel="nofollow noreferrer noopener" target="_blank">Steam Hardware Survey</a>, сам график <a href="https://api.dtf.ru/v2.8/redirect?to=https%3A%2F%2Fwww.reddit.com%2Fr%2Fpcmasterrace%2Fcomments%2F1hp5el8%2Fmonitor_resolutions_over_time_based_on_the_steam%2F&postId=3705469" rel="nofollow noreferrer noopener" target="_blank">с Рэддита</a>.
Статистика дисплеев геймеров по годам. Данные по Steam Hardware Survey, сам график с Рэддита.

Когда разрабатывался Skyrim, актуальные консоли рендерили игры в 720p, а среди ПК-геймеров самыми ходовыми разрешениями были 1280x1024 и 1680x1050. Когда разрабатывался Fallout 4, FullHD активно захватывал мир. Starfield очевидно ориентировался уже на 4K — стандарт, задаваемым современными консолями, в том ч��сле Xbox Series X, эксклюзивом которого Starfield и являлся. Да, количество полигонов от игры к игре увеличивалось значительно, но вот их размер в пикселях на целевом разрешении менялся не так сильно, он оставался на комфортном уровне и для видеокарт, и для игрока. Золотая середина.

Из-за чего весь сыр-бор
Из-за чего весь сыр-бор

Чтобы современные игры вернулись к системным требованиям 2014—2016 годов, нужно не только и не столько снизить количество полигонов. Нужно вернуться к FullHD-геймингу, отказаться от рейтрейсинга, снизить качество текстур и эффектов. Полигоны тут не источник проблем, и даже не симптом, а лишь следствие развития потребительских дисплеев.

К слову, лица с 30 тысячами полигонов прекрасно переваривало и железо того времени. Так, у Кратоса из God of War для PS4 на лице тоже 30 тысяч полигонов, а у Элой из Horizon Zero Dawn — 100 тысяч только в волосах. Эти игры, очевидно, тоже разрабатывались с прицелом на 4K на PS4 Pro, но справлялась с ними и оригинальная PS4.

183
25
25
5
2
2
1
1
1
1
194 комментария