Асинхронная потоковая передача данных
Потоковая передача данных — это метод оптимизации, предназначенный для уменьшения скачков, вызванных загрузкой графических ресурсов и компиляцией шейдеров. При использовании этого метода не все данные загружаются в оперативную память (RAM) сразу. Вместо этого загружаются только необходимые данные, а все остальные загружаются постепенно, по запросу.
Ресурсы загружаются и передаются в GPU отдельными асинхронными потоками. После этого ресурсы синхронизируются и добавляются в виртуальную сцену на стороне CPU.
В UNIGINE асинхронная потоковая передача данных включена по умолчанию. Вы можете отключить асинхронную потоковую передачу данных в UnigineEditor или через консоль:
- В UnigineEditor откройте окно Settings и перейдите в раздел Streaming. Здесь вы можете переключить режим потоковой передачи текстур и/или мешей.
- В консоли запустите соответствующие команды, которые переключают режим потоковой передачи текстур и/или мешей.
Существует два основных режима потоковой передачи — асинхронный (Async) и принудительный (Force). Режим Force обеспечивает принудительную загрузку всех ресурсов, необходимых для каждого кадра одновременно (например, захват последовательностей кадров, рендеринг предварительного просмотра нод, прогрев и т.д.).
Для мешей существует дополнительный режим All, который отключает потоковую передачу меша и обеспечивает загрузку всех мешей, доступных в проекте, при запуске приложения. Этот режим хорош для небольших проектов с небольшим количеством мешей.
Система потоковой передачи обеспечивает асинхронную загрузку следующих данных в RAM:
- Все исполняемые файлы текстур и текстуры с включенной опцией Unchanged, включая кубические карты, карты воксельных проб и карты запеченных теней.
- Меши объектов ObjectMeshStatic, ObjectMeshClutter, ObjectMeshCluster, ObjectGuiMesh и DecalMesh.
Процедурно сгенерированные объекты, такие как ObjectMeshClutter, генерируются в отдельном потоке, что значительно снижает затраты на производительность.
Вы можете получить общую информацию о потоковых ресурсах, используя консольные команды render_streaming_meshes_info и render_streaming_textures_info.
Также можно вывести на экран список загруженных ресурсов и подробную информацию о них с помощью консольных команд render_streaming_meshes_list и render_streaming_textures_list.
Асинхронная компиляция шейдеров#
Помимо асинхронной загрузки мешей и текстур, система потоковой передачи обеспечивает асинхронную компиляцию и загрузку шейдеров.
Для шейдеров также есть 2 режима - асинхронный (Async) и принудительный (Force). Режим Force обеспечивает принудительную компиляцию и загрузку в RAM всех шейдеров, необходимых для текущего кадра одновременно, в текущем потоке. По умолчанию используется асинхронный режим.
Количество компилируемых в настоящий момент шейдеров, а также количество уже загруженных в память шейдеров доступно в Performance Profiler
Ограничения памяти#
Вы можете ограничить количество загружаемых и выгружаемых графических ресурсов на кадр, указав соответствующие бюджеты. Используйте их, чтобы найти баланс между скоростью загрузки/выгрузки и производительностью: имейте в виду, что увеличение бюджета увеличивает производительность потоковой передачи, однако также увеличивается потребление памяти.
Регулируемые ограничения памяти и время автономной работы позволяют избежать ситуаций, когда ресурсы остаются загруженными в оперативную память или видеопамять даже после того, как они больше не используются. Они определены для мешей, загруженных в RAM/VRAM, текстур и частиц отдельно в процентах от общего объема RAM/VRAM.
Ограничение памяти связано со временем существования (lifetime): ресурсы удаляются из оперативной памяти или видеопамяти только при превышении обоих значений.
Ограничения памяти и RAM/VRAM, занимаемые потоковыми ресурсами, доступны в инструменте Performance Profiler.
Ограничения разделены косой чертой: первое значение отображает текущее использование оперативной памяти / видеопамяти, а второе — предел.
Кэш текстур#
Система потоковой передачи использует кеш текстур, состоящий из минимизированных копий, созданных для всех текстур с определяемым пользователем разрешением и хранящихся в папке data/.cache_textures . Эти копии используются вместо оригиналов при загрузке.
Кеш текстур загружается при запуске движка и всегда остается в памяти после загрузки. Для обеспечения плавной загрузки и отрисовки ресурсов потоковые сущности имеют следующие приоритеты загрузки:
- Кеш текстур
- Геометрия
- Некешированные текстуры (вызывают скачки, поскольку кэш текстур генерируется для них на лету; материалы с некешированными и незагруженными текстурами отображаются черными)
- Полноразмерные текстуры
Кэш текстур может быть предварительно загружен или загружен после данных геометрии, флаг Texture Cache Preload управляет приоритетом загрузки кеша текстур.
Информацию об объеме видеопамяти, занятом в данный момент кешем текстур, можно посмотреть в инструменте Performance Profiler.
Потоковая передача мешей#
Меши могут быть загружены в оперативную память и видеопамять отдельно для более эффективной работы с геометрией. Это позволяет устранить утечки памяти: меши, участвующие в коллизиях и пересечениях, могут быть загружены в оперативную память только в том случае, если они в данный момент не отрисованы.
Существует 3 режима потоковой передачи мешей в RAM/VRAM:
- асинхронный режим, обеспечивающий асинхронную загрузку мешей;
- принудительный режим для одновременной принудительной загрузки мешей, необходимых для текущего кадра;
- режим загрузки всех мешей, доступных в проекте, при запуске приложения. На самом деле, этот режим вообще отключает потоковую передачу мешей.
Асинхронная загрузка в RAM и VRAM отличается. Даже если меш не был загружен в видеопамять вовремя, это не влияет на поведение приложения (вы можете заметить только некоторую задержку). Однако, если меш не был загружен в память вовремя, это может привести к неправильному физическому поведению объектов в сцене.
Прежде всего, мы настоятельно рекомендуем вам использовать формы (shape) для обнаружения столкновений и пересечений, поскольку это быстрее. Если по какой-то причине это вам не подходит, воспользуйтесь следующими способами:
- Загружайте меши и сохраняйте их в памяти, пока они существуют. В API некоторых объектов на основе меша эта функциональность предусмотрена. Это может частично решить проблему с некорректным поведением, однако загруженными могут оставаться только несколько мешей.
-
Используйте систему предварительной выборки, которая позволяет асинхронно предварительно загружать меши, участвующие в коллизиях и пересечениях, в память перед их использованием:
- Установите режим предварительной выборки Radius.
- Укажите физический радиус (для столкновений) и/или радиус, в пределах которого рассчитываются пересечения.
- Укажите радиус предварительной выборки, который должен превышать значения радиуса столкновения и пересечения.
Вы также можете предварительно загрузить все меши, для которых вычисляются коллизии и пересечения (режим предварительной выборки Full), однако это значительно увеличит использование оперативной памяти.
- API некоторых mesh-объектов, а также API класса MeshStatic предоставляют также методы, которые позволяют реализовать пользовательскую логику предварительной выборки для предварительной загрузки мешей.
Асинхронно передаваемые меши не должны изменяться. Единственный способ изменить такой меш — сделать его процедурным. Процедурный меш — это меш, созданный с помощью кода, такие меши имеют определенный режим потоковой передачи — они всегда сохраняются в памяти после создания и никогда не выгружаются, пока объект не будет уничтожен через код или меш не вернется в свой обычный режим (потоковая передача из исходного файла). API объектов на основе меша позволяет переключать меш в процедурный режим и применять изменения.