Изначальной задачей было написать две рисовалки для библиотеки Legend используемой в проекте Uninav:
- основная: для OpenGL(когда есть GPU и OpenGL)
- запасная: для AGG(Anti-Grain Geometry)
Они должны уметь рисовать полилинии, полигоны, текст, растровые и векторные изображения
Их главными преимуществами перед уже имеющимися аналогичными рисовалками, должна была стать меньшая загрузка CPU (например: рисование двух следов корабля за день могло потреблять порядка 30% загрузки главного потока и 200+ Мб памяти, это был хорошо оптимизированный алгоритм).
Засчет чего они должны быть лучше:
- Долгий перевод гео координат на проекцию(меркатор на данный момент), осуществляется в другом потоке.
- Это statefull рисовалки, данные лучше батчатся, и реже обновляются, чем в текущих stateless рисовалках.
После того как рисовалки будут написаны нужно перевести на них слои Uninav(слои это обьекты отвечающие за рисование какого-то функционала)
- Cлой трека(описан выше)
- Cлой logbook(бортовой журнал)
- Cлой AIS и ARPA целей
- Возможно и некоторые другие слои на вроде AIM
Я реализовал асинхронные версии этих рисовалок, но пока еще не добавил программное кроссплатформенное сглаживание в opengl версию.
Также я перевел слой трека на новые рисовалки:
- В OpenGL использование новой рисовалки дало выигрыш в уменьшении нагрузки главного потока этим слоем с 30% до менее 1%.
- В AGG примерно в 1.5 - 2 раза повысило FPS, также благодаря новому stateless клиппингу были устранены зависания на аллокациях для boost::geometry::intersection для всех AGG рисовалок.
- Благодаря другой модели хранения данных (SoA) удалось снизить потребление этим слоем памяти c ~200Мб до ~20Мб
Главные трудности связаны с тем что код библиотеки Legend(сурс рисовалок) довольно плохого качества и без сложных манипуляций не собирается под linux (я работаю именно под ним, проект и библиотека кросплатформены), а также Legend все еще в процессе перехода со Scons на CMake(я пользуюсь CLion). В целом меня выручает grep и vscode, но работа над библиотекой все еще сильно утомительнее чем над проектом.
Также я все еще испытываю сложности с алгоритмом программного кроссплатформенного сглаживания для OpenGL. У меня есть пару идей, но пока это только dev branch.
Из успешно преодоленных:
- Использование SoA привлекло к незаметному на взгляд, но ощущаемом на производительности баге, в итоге я несколько дней улучшал производительность AGG рисовалки, хотя на самом деле это не было необходимо, но в итоге производительность AGG возросла, а я пофиксил несколько других багов.
- Еще так как GL-контекст нельзя трогать из разных потоков реализация этой рисовалки нетривальна. Я использовал классический паттерн с очередью gl задач которые затем исполняются в gl треде. В процессе я выявил баг в thread pool нашего проекта, его деиницилизация вызывалась раньше, чем у некоторых обьектов, которые отправляли в него задачи. Так как до этого не было задач на которых было заметно, что мы ждем не в деиницилизации обьекта, а в деиницилизации пула, этот баг выявился только с очередью, которую при ожидании в gl потоке нужно явно прокручивать.
Проект Uninav и библиотека Legend полностью написаны на C++, и на данный момент компилируются с поддержкой C++14.
Помимо уже упомянутых библиотек, в своих задачах я использовал boost, qt, thrift.
Я много взаимодействовал с командой Legend Core, так как это был почти новый для меня код, обсуждал архитектурные решения, которые были приняты в дальнейшем. Пару раз просил помощь с профилированием под windows.
С командой Uninav Core в которой я состою, в основном обсуждал требования к рисовалкам, и баги возникшие в ходе переписывания слоя.