Для первого релиза в Стиме критически важным является стабильность программы. Как известно, SE никогда этим не блистал. Поэтому пришлось атаковать главного виновника: ландшафтный движок. Исторически в SE реализовано динамическое перераспределение памяти между разными подсистемами, в зависимости от ситуации: ландшафт, звёзды, модели галактик и туманностей, корабли. Это было необходимо, когда объёмы видеопамяти были 1-2 гигабайта. Сейчас же видеокарты с объёмом меньше 3 гигабайт и так с трудом тянут SE. Поэтому можно отказаться от динамического распределения и перейти к более эффективному, быстрому и стабильному статическому. Вместо того, чтобы выделять память под текстуру каждый раз, когда она требуется, нужно заранее, при старте программы, выделать большой массив пустых текстур, и больше его не менять. Когда движку нужна новая текстура, менеджер памяти просто выдаёт индекс первой свободной текстуры из массива. Вместо удаления текстуры с возвращением памяти из-под неё в систему, её индекс просто помещается в список свободных, и может быть выдан в следующий раз.

Переделка принципа хранения текстур в видеопамяти (текстурные массивы OpenGL), мешей (вообще практически без них, рельеф строится на лету в вершинном шейдере по текстуре высот), и данных в оперативной памяти (полустатический пул) привела к следующим результатам:

1) Стабильность – 100%. SE больше не падает на генерации ландшафтов, в первую очередь из-за статического использования памяти.

2) Оперативной памяти на ландшафты нужно не более 100-150 Мб, видеопамяти – не более 2 Гб (если включено сжатие текстур). Выделенный объём фиксирован и никогда не меняется. Движок определяет, сколько может выделить под текстуры, при запуске, по объёму доступной видеопамяти.

3) Скорость генерации ландшафта увеличилась в десятки раз! Лучше посмотреть видео (сорри за глючный автофокус, снимал на телефон, чтобы видеозахват не повлиял на fps):

(На видео заметны глюки с геометрией ландшафта в момент загрузки, уже исправлено).
Это благодаря устранению оверхеда на динамическое выделение текстур. Оно было очень медленным! На LOD 0 полная генерация – за 5 секунд, на LOD 1 – за 30 секунд. Правда, это на RTX 2080, но и разрешение дисплея 4k. Слайдер “Скорость загрузки” в настройках позволяет разменять скорость загрузки на плавность рендера (частоту кадров). При значениях “скорости” до 8, частота кадров не уменьшается ниже 60, при значении 20 она просаживается до 18 fps, зато ландшафт на LOD 1 полностью генерируется за 12 секунд.

4) Теоретически, производительность выросла, потому что устранён оверхед на переключение текстур для каждого нода ландшафта (благодаря текстурным массивам). В то же время она немного уменьшилась (на 5-10 fps) из-за чтения текстур в вершинном шейдере для построения рельефа. Сложно сравнить точно, но первое очень существенно перевешивает второе. И это ещё не реализован инстансинг (это следующий шаг, почти всё для этого готово).

5) Неожиданно, но полезно: устранён эффект, когда в момент появления (при быстром подлёте или при открытии wiki) астероид сначала круглый, и только через некоторое время появляется рельеф. Потому что рельеф теперь строится по карте высот прямо в шейдере.

6) Бонус – халявный, практически бесплатный дисплейсмент маппинг детальных текстур (т.е. камней). Т.к. основной рельеф и так фактически строится дисплейсмент маппингом, добавить ещё один сэмпл в вершинный шейдер – не проблема. В итоге получаем вот что:

Original Image Original
Modified Image Modified
Original Image Original
Modified Image Modified

Практически бесплатные 3D камни! Надо сказать, в ВР смотрится настолько круто, что я сам там зависаю на полчаса каждый раз при тестовом запуске 🙂 Надо теперь подобрать качественный арт для них (комплект текстур).

Из недостатков можно отметить следующее:

1) Т.к. текстурный кэш в памяти теперь фиксированного объёма, невозможно загрузить больше текстур, чем в него вмещается. LOD 1 – это предел на дисплеях 1920×1080, а на 4k предел – LOD 0. При повороте камеры вбок и обратно, рельеф перезагружается, т.к. текстурный кэш заполнен почти полностью. Впрочем, перезагрузка настолько быстрая, что не напрягает. При увеличении LOD сверх этого предела, ландшафт будет постоянно перезагружаться (какие-то дальние ноды будут мигать, эффект циклической перезагрузки устранён). Предел вместимости кэша – 2048 текстур (каждого типа), это ограничение OpenGL на размер текстурных массивов. Впрочем, удачно вышло, что этого достаточно как для большинства дисплеев, так и для VR. В дальнейшем можно будет наращивать разрешение самих текстур, не меняя вместимость кэша.

2) Движок теперь не поддерживает текстуры планет с произвольным разрешением тайлов. Теперь они обязаны быть 256*256. Это значит, что мне придётся переделать все 45 гигабайт текстур планет Солнечной системы. Такие моды, как Гранд Каньон, тоже потребуют переделки. Не-кубические текстуры (в простой цилиндрической проекции) тоже больше не поддерживаются, разве что 256*256. Текстурами реальных планет я пока не занимался, в планах существенно ускорить так же и их загрузку.

3) Теперь нет динамического перераспределения видеопамяти между ландшафтом и другими системами (звёздами, моделями галактик и кораблей). На слабых машинах это может стать серьёзной проблемой. Уже сейчас одного гигабайта видеопамяти катастрофически мало для SE. Я сделал настройку в конфиге, которая отключает детальные текстуры – это позволяет ужать кэш ландшафта до 300-400 Мб. Возможно, придётся сделать автоконфигурирование для слабого железа.

И всё же, достоинства с лихвой перевешивают указанные недостатки. Стабильность и скорость работы прежде всего! Системные требования… SE всегда был к ним суров.

На завершение переделки ландшафта нужно не менее месяца. Как всегда, работает правило 80/20: 80% работы я сделал за неделю, значит, оставшиеся 20% растянутся на месяц…

Форум.