Раз в сколько-то лет я создаю такую тему.
Начало разработки: периодически 2018-2022, с 2022 более активно.
Язык: C++17 (опционально часть фич из C++20)
Платформы: Windows, Android, Linux, MacOS, Emscripten (без графики).
GAPI: Vulkan, Metal.
Шейдеры: GLSL, MSL.
Архитектурно основан на публикациях idTech (Дум/Вольфенштейн) и REDEngine (киберпанк). Движок полностью асинхронный, с кастомными аллокаторами и тд.
Исходники: gitflic, github.
Бинарники в артефактах CI на github.
Фичи:
Планы
Нискоуровневые фичи сделаны, буду доделывать высокоуровневые: звук, репликация ECS и тд.
Редактор шейдеров
Используется для прототипирования различных техник. Расположен в 'AE/samples/res_editor'.
Примеры шейдеров + скриншоты на gitflic, github.
Фичи:
Моё имхо - асинхронный код в стиле .then это порождение сатаны затрудняющее и уничтожающее простоту понимания кода.
Поэтому изобрели асинхронные функции в языках что это поддерживают, иначе просто архисложно понимать что на трёх экранах кода у тебя происходит.
Имхо это очень опасно так вот делать огромную ставку на концепцию именно в таком стиле.
=A=L=X=
.Then() нужен для промисов, чтоб передавать ему входные данные. В С++20 это можно заменить корутинами, промисы автоматом конвертируются в корутину и возвращают значение.
Но под андроид корутины еще не поддерживаются.
Концепция это система тасков, а поверх них работают промисы, корутины, ассинхронное чтение и тд, пользователь сам может решить как передавать данные между тасков.
/A\
Мне именно что пришлось поработать с промисами в идиоме .then и это блевотина когда понять куда что, как и когда передалось по сравнению с однопоточной программой сложнее в 10-20 раз.
Если не будет асинхронных функций которые эти сложности хорошо прячут под капот, то прям нехорошо.
Можно будет запутываться просто в реализации нажатия кнопки на выход из игры когда будет промежуточный диалог YES/NO - это пипец, в концепции .then код начинает затмевать логику.
=A=L=X=
На корутинах другой код получается.
ImageMemView mem_view = co_await ctx.ReadbackImage(image, ReadbackImageDesc{} );
И промисы чаще всего с короткими цепочками:
auto task = AsyncTask{ctx.ReadbackImage(image, ReadbackImageDesc{} ) .Then( []( const ImageMemView &view) { })}; // запустить таск после .Then() Scheduler( ).Run< OtherTask >( Tuple{}, // конструктор Tuple{task} ); // зависимость таска
Еще сделана универсальная система ввода, клавиатура, мышь, джойстики, гироскопы все в коде видны как имя + данные.
Биндинги в скриптах выглядят так:
Исходники главное не пали, а то вдруг пацаны сп*дят и заработают на них миллионы баксов, а тебя оставят с носом.
v1c
> Исходники главное не пали
На гихабе по моему имени 2.7к файлов, я думаю хватит пока что, потом еще выложу)
Роннико похоже был прав.
Тут байт текста кода больше, чем байт в картинке, которую он обрабатывает )
раб вакуумной лампы
В движке 9.5Мб кода написаного мной)
Еще под 2Мб в демо и редакторе шейдеров.
Асинхронная загрузка текстур у тебя есть? Я тут недавно сделал на вулкане подобную, у меня получилось 6 очередей (+ 7 вулкановская) и пять потоков.
v1c
> Асинхронная загрузка текстур у тебя есть?
да
> у меня получилось 6 очередей и пять потоков.
Зачем? Можно в 1 поток и в 1 очередь.
Асинхронное чтение из файла и по частям каждый кадр заливать, чтоб не блокировать PCI надолго.
/A\
Например если у юзера стоит старый HDD, то открытие файла включает позиционирование головки на секторе диска, а это медленно. В это время другой поток может аллоцировать текстуру или декомрессить текстуру из сжатого формата (Zlib, Basis Universal и т.д). Идея такая если что-то можем делать параллельно - делаем, а не ждём пока какая-то стадия освободит поток. Таким образом пак текстур может грузиться быстрее.
v1c
Но это уже детали, в твоем первом вопросе не было каких-то намеков на ЦП-нагрузку, а значит можно в одном потоке все сделать при использовании асинхронных команд, которые не блокируют ЦП на позиционирование головки в диске и тд.
/A\
У меня загрузка текстуры разбита на такие стадии:
Setup -> Create -> Load -> Decompress -> Transfer Copy -> Submit
Каждая стадия занимает какое-то время, поэтому я разбил их на потоке чтобы декомпрессор одной текстуры не ждал загрузку с диска другой.