1.7.0 — первая версия движка, к которой прилагается редактор. Он пока на ранней стадии разработки, присутствуют только базовые возможности, и в самом Dagon пока нет встроенных инструментов для работы с файлами сцен, которые он создает (впрочем, это JSON с очень простой, интуитивно понятной структурой, которые легко адаптировать к любому проекту).
Что уже реализовано:
Загрузка/сохранение сцен
Браузер ресурсов с поддержкой миниатюр для изображений. Редактор видит папку, в которой находится файл сцены, и может импортировать ресурсы из нее. Ресурсы всегда вставляются как локальные ссылки, редактор их не конвертирует и не перемещает, так что при обновлении файлов другими программами все изменения будут подхвачены. Пока, правда, нет отслеживания и перезагрузки файлов в случае внешних изменений
Импорт моделей OBJ. Другие форматы пока не поддерживаются, но в перспективе редактор, скорее всего, будет понимать все популярные форматы благодаря Assimp
Импорт материалов
Базовые инструменты редактирования объектов: трансформация, изменение основных свойств. Для трансформаций поддерживаются отмена и возврат
Инспектор с деревом объектов сцены
Настройки материала
Настройки пост-процессинга.
В самом движке изменения косметические. Обновлен синтаксис языка конфигураций — я решил портировать улучшения, сделанные в рамках Dagon 2, а именно поддержку переменных (свойства могут ссылаться на другие свойства), интерполяции строк ("${propName}") и платформоспецифичных постфиксов (something.windows or something.linux). Добавлены новые свойства приложения Application.wintabLibraryPath, Application.loadedWintabSupport, свойство менеджера событий EventManager.autoExit для отключения автоматического выхода при закрытии окна. Исправлено падение при вызове Entity.setParent с параметром null. Исправлен забагованный колбэк отладочных сообщений OpenGL.
Попыток написать редактор сцен у меня было уже две — когда-то на Gtk, потом на Nuklear. Третья итерация использует ImGui. В данный момент уже готовы базовые фичи — инспектор, гизмо для трансформации объектов сцены, панель свойств, а также встроенный браузер ресурсов с отображением миниатюр для картинок.
Формат сцен находится в разработке, он скорее всего будет на основе JSON. Пока под вопросом совместимость с Dagon 2 и его форматом DAF — не исключено, что она тоже будет реализована.
Все мои сайты перестали открываться из России. Проясняю ситуацию, но предварительный вывод такой — IP, на котором они размещаются, заблокирован ТСПУ. Очередная волна закручивания гаек.
Retrolang похож на C, но сходство лишь базовое. В действительности я не собираюсь копировать C — не только потому что это фактически мне не нужно, но и потому что программирование под PSX требует весьма специфических возможностей языка, почти на уровне DSL (при этом я не стал их прибивать гвоздями к MIPS, они теоретически могут быть реализованы на системном уровне для любой архитектуры).
Во-первых, это, конечно, атрибуты размещения и инициализации статических данных. Я почти сразу сделал поддержку вшивания в бинарник файлов — это очень полезно, чтобы писать мини-игры, которым не требуется читать файлы с диска, а также чтобы встроить в программу bitmap-шрифт или какие-то другие данные.
uchar data[] @("file.bin");
На PSX слишком мало памяти, чтобы использовать динамический аллокатор, как в современных ОС. Программа должна заранее распланировать память, которую она потребляет. Если доверить эту задачу компилятору, то он может все проверять и не допускать коллизий (в то время как ручная работа с диапазонами адресов чревата ошибками). Для этого в Retrolang используются все те же атрибуты:
macro Region = (0x80050000, 2048);
int someData[512] @Region;
Это статически выделит 512*4 байт в регионе MyRegion. Для этого в кодогенераторе предусмотрена специальная таблица регионов и аллокаций.
Преимущество такого подхода перед выделением статической памяти в секции данных в том, что бинарник остается маленьким, а это иногда критично. Кроме того, регионы поддерживают Scratchpad:
int someData[64] @SCRATCHPAD;
Выделенную память можно затем использовать в качестве арены для создания в рантайме более мелких объектов.
Во-вторых, AST-макросы. Это киллер-фича, которая делает ненужным препроцессор C. Препроцессор в Retrolang все равно есть, но возможности его ограничены, и я не планирую их развивать. Другое дело — макросы. Они позволяют переиспользовать практически любые выражения и утверждения языка, параметризуя их. Это похоже не шаблоны, но шаблон обычно параметризуется типами, а макрос — константами, идентификаторами, выражениями и другими макросами. Как и шаблоны, макросы — тоже разновидность метапрограммирования, но их главное назначение — явный инлайнинг кода. C инлайнит непредсказуемо, а Retrolang — язык с предсказуемой семантикой, в котором каждая операция транслируется в машинный код буквально. Поэтому в условиях, когда вызов лишней процедуры — дорогое удовольствие, очень важно переиспользовать код статически. Например, вместо того, чтобы создавать функцию с командами GTE, можно сделать соответствующий макрос, и команды будут вставлены непосредственно в вызывающий код без оверхеда на движение по стеку:
Проект стартовал 9 октября 2016 года, ровно 10 лет назад. Конечно, это не первая моя разработка в сфере геймдева, и я начал писать движок далеко не с полного нуля — к тому моменту у меня был DGL, набор классов, упрощающий работу с OpenGL в D (а до этого я работал с OpenGL и писал разнообразные сопутствующие библиотеки на C++). Однако именно Dagon стал наиболее успешным.
Создание игрового движка — наверное, одна из самых интересных и нетривиальных задач в программировании. Есть устойчивое убеждение, что свой движок писать вообще не нужно, и я как-то раз написал статью о том, почему это скорее миф. Существуют примеры успешных проектов как на лицензированных движках, так и на эксклюзивных, оба варианта имеют свои плюсы и минусы. На мой взгляд, главное преимущество собственной технологии — независимость от чужих лицензионных условий и архитектурных решений. В современном мире большинство проектов делается на Unity и UE, в результате чего игры слишком похожи друг на друга. Собственный движок — это ваш уникальный почерк. Понятно, конечно, что с UE конкурировать практически невозможно — продукты, в которые вложены миллионы долларов, будут всегда впереди. Но UE — это движок-монстр, все возможности которого нужны далеко не каждому. Если речь об инди, то нелепо, когда рантайм игры весит, как все ее ресурсы (если не больше), а системные требования — как у AAA. Должны же быть и маленькие движки! Ну и, наконец, психологический фактор: игра на чужом движке воспринимается как не совсем твоя.
Я начал интересоваться геймдевом еще в далеком 2005 году, когда открыл для себя Game Maker, Blitz3D и другие популярные любительские технологии того времени. Затем я пробовал работать с Irrlicht, OGRE, Blender Game Engine, но с точки зрения архитектуры меня очень впечатлила GLScene, графическая библиотека для Delphi. Мои собственные разработки во многом вдохновлены классами GLScene, хотя напрямую я оттуда ничего не копировал. Я вообще почти не заглядываю в исходники чужих движков — не знаю, хорошо это или плохо, но у меня свое понимание того, что удобно, а что нет. Боже упаси создавать клон Unity или что-то подобное. Не мыслите шаблонами индустрии, изобретайте свои технологии!
Я никогда не писал на DirectX, как-то почти сразу освоил OpenGL и всю жизнь сидел на нем. В нулевых это были версии 1.x-2.x, еще с фиксированным конвейером, где шейдеры были необязательной частью. Потом — короткий период 3.x, и, наконец, к концу десятых — 4.x. Я проследил практически всю эволюцию OpenGL и использовал его до последнего, когда стало уже очевидно, что пора двигаться дальше и осваивать эксплицитные API. Я, однако, не фанат чистого Vulkan. На нем не надо писать приложения напрямую по той же причине, по которой не пишут напрямую на ассемблере. Vulkan — это машинно-ориентированный бэкенд, поверх которого нужна абстракция, удобная для человека. Я терпеливо ждал появления таких абстракций, они появились, и вот теперь можно со спокойной душой уходить с OpenGL.
Что еще могу сказать на основе десятилетнего опыта? Разрабатывая большую систему, такую, как игровой движок, рано или поздно приходишь к идее неизбежности компромисса между двумя силами, тянущими проект в две разные стороны — абстракцией и специализацией. Абстракция — это сокрытие деталей под высокоуровневым интерфейсом. Абстракция повышает удобство на стороне пользователя, но снижает гибкость и возможности оптимизации. Специализация, напротив, подразумевает, что пользователь сам должен предоставить реализацию некоего интерфейса — то есть, углубиться в детали и интегрировать в движок свое решение специфической задачи. Это дает гибкость и возможности оптимизации, но снижает удобство. Хорошая система включает в себя и то, и другое. Дзен в балансе: нужно постоянно решать, в какой степени система должна быть абстрактной, и в какой — специализированной. Например, один из первых 3D-движков, с которыми я работал — Xtreme3D для Game Maker 6 — имел очевидный приоритет абстракции над специализацией: в нем были готовые декодеры разных форматов 3D-моделей, но полное отсутствие возможности создать свой собственный (то есть, собрать модель вручную из вершин и индексов). А вот встроенный 3D-рендер Game Maker, наоборот, не включал практически никаких абстракций и вынуждал программировать графику на низком уровне, составляя списки отрисовки из отдельных полигонов. В первом случае удобно, но не гибко, во втором — гибко, но неудобно. Учтя эти особенности, я решил делать движок, который охватывает оба сценария использования. Если вам нужно просто загрузить glTF, то это легко. А если вы хотите создать свой формат сцен, то это, пусть и с оговорками и требованиями, но реализуемо. Я всегда подчеркиваю, что Dagon — это фреймворк, то есть, каркас игрового приложения. Его ядро включает только создание окна и контекста OpenGL, управление таймером главного цикла и очередью событий. Рендер — это уже надстройка; в Dagon можно не использовать встроенный рендер и написать свой. То же касается абсолютного большинства всех подсистем — они не прибиты гвоздями. Принципиальной основой работы в Dagon является инверсия контроля, как и во всех фреймворках, но ядро минималистично — оно не отвечает за все процессы, и вы можете заменить почти все, что угодно, на самописные компоненты.
Разработка не стоит на месте, я постоянно что-то улучшаю и переписываю, чему, главным образом, и посвящен этот блог. Не хочется загадывать, но надеюсь, что в следующем году доделаю Dagon 2.0 — начинается новая большая страница в истории движка.
PS1 — наверное, одна из самых культовых консолей всех времен. Количество часов моего детства, проведенных за ней, бессчетно. Я иногда даже вставал пораньше, чтобы часок поиграть перед школой) Классические части Need for Speed и Final Fantasy, Tekken и Soul Blade, Twisted Metal, Driver, TOCA, Crash Bandicoot, Spyro the Dragon, Medievil, Sim Theme Park — список моих любимых игр с первой «соньки» можно продолжать долго. В некоторые кроссплатформенные игры типа GTA, Quake 2, Myst я тоже впервые поиграл именно на PS. 3D-графика в то время сносила крышу и казалась совершеннейшей фантастикой — я ей увлекся как раз благодаря любимой консоли. А с появлением компьютера и Интернета я быстро освоил эмуляцию, стал качать образы игр, которые было не найти в магазинах, и записывать свои диски.
Надо ли говорить, что мне всегда хотелось научиться программировать под PS. Я редко пишу об этом, но этой темой я периодически занимаюсь с конца нулевых, и с тех пор скопил много информации, инструментов и исходников. Началось все с того, что я научился компилировать проги при помощи утекшего в Сеть старого официального SDK PsyQ, который использует C89. Именно на нем было создано большинство хитов. С ним работать довольно удобно, несмотря на то, что это древний софт, написанный еще в эпоху Windows 95. Но мне показалось, что как-то нехорошо зависеть от пиратского ПО, пусть и заброшенного. К тому же, он закрытый, его невозможно модифицировать. Поэтому я взялся писать собственную графическую библиотеку PSXLib. Дело пошло, я довольно глубоко погрузился в детали на уровне ассемблера, но мне ни один существующий ассемблер для консоли не понравился по ряду причин, о которых сейчас излишне рассказывать. Я решил сделать свой собственный, который назвал Retrolang, попутно изучив архитектуру MIPS-I и протокол загрузки PlayStation во всех деталях.
Недавно я взял этот проект и ради прикола скормил его Claude, чтобы он сгенерировал под это дело компилятор языка чуть ниже уровнем, чем C. Получилось лучше, чем я ожидал! Я добавил простейший препроцессор (#define, #include) плюс еще кое-какие расширения, и получилась вполне рабочая штука для низкоуровневых экспериментов. Недавно я допилил все это до состояния альфа-версии и выложил на GitHub:
Язык во многом похож на C, но поддерживает не все его фичи. Используется стандартный для 32-битной архитектуры набор целочисленных типов (char/uchar, short/ushort, int/uint). 64-битных чисел нет, как нет и float’ов. Поддерживаются указатели, массивы, строковые литералы, структуры (в том числе вложенные). Вызовы функций соответствуют ABI O32, за исключением аргументов на стеке — они пока не поддерживаются, поэтому функции могут принимать только по 4 аргумента.
В данный момент можно выводить текст в последовательный порт (местный аналог TTY), определять нажатия кнопок геймпада и рисовать простейшую графику, причем все это получается более-менее читаемо. Например, вот как выглядит Hello, World:
void main()
{
bios_a(0x13, "Hello, World!\n");
}
Вызовы BIOS являются интринсиками компилятора — это фича, которой не было ни в PsyQ, ни где-либо еще, такие вызовы раньше всегда делались через ассемблерные вставки.
Есть возможность встраивать файлы в бинарник — очень не хватало такого в C. Я для этого ввел специальный синтаксис атрибутов для глобальных переменных:
char* timFile @("assets/img.tim");
Кодогенератор интерпретирует это как обычный статический массив, данные которого нужно прочитать из внешнего файла. Таким образом можно легко запихнуть в игру ресурсы (если их совсем мало), вместо того, чтобы читать с диска в рантайме.
И, конечно, есть ассемблер, с которого проект и начался. Ассемблерные вставки добавляются в программу при помощи таких же атрибутов:
void asmFunc() @("asmFunc.s");
Код тела такой функции реализуется во внешнем ассемблерном листинге. При этом asmFunc — обычная функция с прологом и эпилогом.
Я работаю над стандартной библиотекой с собственным драйвером GPU, который отчасти основан на коде из PSXLib. Реализован как прямой рендеринг через GP0, так и непрямой через командные буферы и DMA. Есть начальная поддержка 3D-графики — трансформация вершин в экранное пространство и Z-упорядочивание. Правда, 3D там намного сложнее, чем 2D, и требует самых изощренных хаков, с которыми я сталкивался в своей жизни как графический разработчик. Это вам не в Unity кнопочки тыкать. Перед людьми, которые придумали, как рендерить 3D-модели на платформе с 1 мегабайтом видеопамяти и без Z-буфера, я снимаю шляпу (хотя имен их не знаю).
Трудно сказать, для чего все это сегодня нужно — эпоха 32-битных консолей давно в прошлом, и оценить подобные штуки могут лишь единичные любители ретрокомпьютинга и системного программирования. Это, конечно, в основном хобби для души. С другой стороны, MIPS отлично подходит в качестве учебной архитектуры — она довольно простая, можно на ее примере изучить работу процессора и то, как абстрактные логико-математические концепции отображаются на реальное железо. Опыт работы на таком низком уровне незаменим. Так что, надеюсь, мои наработки кому-нибудь пригодятся, хотя бы как референс.
Очередное крупное обновление dlib. Главной фичей релиза является поддержка декодирования прогрессивных JPEG — жуткий долгострой, который я не мог довести до ума чуть ли не все последнее десятилетие. dlib.image.io.jpeg — это теперь пакет, где все части декодера разнесены в отдельные модули. Также теперь поддерживаются одноканальные JPEG.
Добавлен новый модуль dlib.random.ziggurat и функция gaussian, которая генерирует псевдослучайные числа с нормальным распределением по алгоритму Зиккурат.
Добавлена новая функция rsqrt в dlib.math.base. Это тот самый легендарный быстрый обратный корень Джона Кармака с оригинальными комментариями из кода Quake 3 — я решил добавить эту функцию в dlib как своего рода пасхалку.
Все математические константы в dlib.math.base приведены к единой точности (количеству знаков после запятой).
Исправлена ошибка в методе Array.removeKey.
dlib теперь использует Coveralls вместо Codecov для отслеживания покрытия кода.
В связи с выходом RTLD, я слегка изменил планы на вторую версию dlib. dlib2 будет по большей части независима от Phobos и основана на RTLD. Это будет по-прежнему библиотека для Windows и POSIX, но появится также поддержка AArch64. Большинство модулей будут вынесены в RTLD, сохраняя, насколько это возможно, обратную совместимость.
Что будет вынесено в RTLD без изменений в первую очередь:
Почти все из dlib.core
Контейнеры
Аллокаторы, арена
Базовая математика
Пул потоков (возможно, с некоторыми улучшениями)
Функции для работы с текстом
Разграничение функций между RTLD и dlib будет не по степени независимости от Phobos, а по степени фундаментальности. Не все функции dlib имеет смысл выносить в RTLD (вследствие спорного дизайна API или ограниченной области применения). Что, скорее всего, так и останется в dlib:
Линейная алгебра и вычислительная геометрия (нужны далеко не во всех приложениях)
Абстрактные потоки ввода-вывода (архитектурно тяжелые, нужны не всегда)
Интерфейс файловой системы (имеет специфический, не очень удобный API; в RTLD будет свой)
Работа с изображениями и звуком (специфическая область применения).
Новые фичи dlib2:
dlib2.image. Новый API для работы с изображениями, без SuperImage. Старый API будет реализован в пакете dlib поверх нового. Все декодеры графических форматов пойдут в dlib2, также появится декодер DDS. Основная задача пакета — максимальное упрощение прослойки, необходимой для хранения загруженных изображений в памяти и передачи в другие API, а также поддержка сжатых GPU-форматов. Будет использоваться структура, аналогичная TextureBuffer в Dagon. Этот же пакет будет включать функции-хелперы для создания текстур OpenGL ES.
Встроенная поддержка OpenGL ES в RTLD позволит создать новый движок холста для рисования векторной графики — dlib2.canvas. Будут реализованы растеризация сплайнов, функции плоттера, вывод изображений, простого текста и т.д. Это будет не полноценный графический движок, но, как минимум, инструмент для визуализации данных, полезный для научных исследований и прототипирования.
Я задумал этот проект как простой способ скомпилировать хоть что-то под AArch64, но очень быстро понял, что можно не ограничиваться полумерами и сделать продвинутый рантайм вместо набора заглушек. Знал бы я изначально, какой портал в ад тем самым открываю… Когда я портировал криптографию с C на D, ощущения, как я уже писал, были как будто полез в трансформаторную будку, а тут — как будто изучаешь ядерный реактор!
Под капотом D устроен весьма интересно и очень не просто. Это не C, где все лежит на поверхности. Компилятор D мало что знает о рантайм-семантике языка — он только генерирует машинный код, используя внешние вызовы для всех нетривиальных механизмов. Выделение памяти, проверка границ массивов, классы, RTTI — все это опирается на специальные хуки, которые реализованы в druntime. Следовательно, все это можно переопределить. Если выкинуть druntime и использовать свою библиотеку без GC, то вам придется написать свои реализации нужных вам хуков. Задача это, безусловно, сложная, системная, но я уже много лет занимаюсь подобными вещами, поэтому к созданию RTLD я подошел во всеоружии. Одно потянуло за собой другое, и вот я уже обнаруживаю себя пишущим собственную _d_newclassT, которая реализует встроенный оператор new для классов!
Это дает большую власть, но я все же не замахиваюсь на полное переизобретение druntime. Моя идея состоит в том, чтобы RTLD подменяла его ровно в той степени, чтобы получилось реализовать библиотеку общего назначения уровня dlib и писать соответствующий идиоматичный код. Иными словами, я не планирую ничем заменять GC, но большинство других возможностей языка будут доступны. На сегодняшний день RTLD уже обеспечивает следующее:
Классы, интерфейсы;
Литералы массивов, а также оператор new для массивов и классов (под капотом — глобальный аллокатор rtld.core.memory, аналогичный dlib.core.memory). Я его, впрочем, не рекомендую использовать, потому что это создает семантическую путаницу — он все равно требует Delete, а это несовместимо с new при компиляции с druntime;
Автоматическая проверка выхода за границы массивов;
Вывод некоторых распространенных рантайм-ошибок.
Как гласит название, библиотека пригодна для разработки приложений реального времени — в том смысле, что все функции работают за предсказуемое время (druntime опирается на сборку мусора, поэтому в общем случае нельзя полагаться, что вызов функций Phobos не приведет к глобальной блокировке). Если вы пишете обычные приложения, не ограниченные по таймингам и памяти, то вы сможете использовать RTLD ситуативно, для каких-то отдельных задач, не отказываясь в целом от Phobos — обе библиотеки могут благополучно сосуществовать в одной программе. Полный переход на RTLD целесообразен в особых случаях, из которых я выделяю два главных сценария:
Системное программирование: если вы пишете низкоуровневую библиотеку с интерфейсом C, которая будет использоваться другими программами — драйвер, сетевой протокол, графический или звуковой API и т.д.;
Программирование встраиваемых систем и маломощных компьютеров. Сюда относятся одноплатные ARM-компьютеры вроде Raspberry Pi или Khadas. RTLD имеет минимальный отпечаток памяти, что позволяет использовать ее на самых слабых машинах, имеющих операционную систему.
Я начал разработку dlib в далеком 2011 году, когда писал на старом добром OpenGL 1.x под 32-битным Linux. Тогда я и не помышлял об альтернативных архитектурах и кросс-компиляции, мне даже в голову не приходило, что у D когда-нибудь появится поддержка такого количества разнообразных платформ. Но к началу 20-х уже стало очевидно, что грядет эпоха ARM, и старичку x86 придется потесниться, а сегодня AArch64 на устройствах мощнее телефона — уже не причуда и экзотика, а обыденная реальность. Стоит это принять и начать уже думать об ARM не как о мобильной, а как о второй десктопной архитектуре. Это необычное положение дел, потому что на десктопе x86 всегда царил монопольно. Но я вообще-то люблю изучать все новое, и для меня как графического разработчика освоение еще одной процессорной архитектуры — интересный вызов. Надо ли прямо сейчас всем кидаться портировать весь софт на ARM? Я думаю, нет, но какие-то базовые штуки, полезные библиотеки, фреймворки — желательно. Вот и я решил не оставаться в стороне.
Хорошая новость состоит в том, что D, в лице компилятора LDC, отлично поддерживает ARM. LDC — это неявный кросс-компилятор, он умеет генерировать код почти под все платформы, поддерживаемые LLVM, и это можно делать на любой хост-системе, не пересобирая тулчейн. ARM существует в разных аппаратно-программных вариантах, я под ним буду подразумевать aarch64-linux-gnu — то есть, платформу с процессором AArch64, ядром Linux и окружением GNU. Проще говоря, установив LDC, вы можете на x86 собирать приложения под десктоп или сервер на базе AArch64, о чем я уже писал в предыдущем посте.
Плохая новость состоит в том, что для компиляции под нестандартные таргеты нужны соответствующие версии Phobos и druntime. Я боюсь представить, что это за квест — собрать их, и не имею никакого понятия о статусе Phobos для AArch64. Мне это даже не очень интересно, потому что Phobos я считаю не самой удачной стандартной библиотекой, я ее почти не использую — она сильно перегружена, половину можно было бы оттуда вынести в дополнительные DUB-пакеты, многие модули откровенно устарели, некоторые функции работают странно, а шаблоны порой не компилируются. Для меня уже привычен хардкорный путь — игнорировать Phobos и писать все свое. К тому же, под маломощными одноплатниками с маленькой памятью вам все равно GC не друг, и лучше все делать на @nogc-компонентах.
Все эти измышления подвели меня к идее создания новой библиотеки общего назначения, более низкоуровневой, чем dlib. Я ее назвал RTLD — Real-Time Library for D. Она основана на модулях, которые я изначально писал для dlib2/dcore, а также на прямых портах из dlib 1.x. В отличие от dlib, это будет настоящая замена Phobos. RTLD предоставляет самую базовую функциональность, работая поверх libc, WinAPI, POSIX, системных вызовов Linux, а также динамически загружаемых функций — X11 и OpenGL ES. По сути, это библиотека для тех, кто хочет писать на D как на C, не используя ничего лишнего. Однако я намеренно не стал делать ее BetterC, в отличие от dcore. Взвесив все «за» и «против», я решил, что от BetterC на десктопе толку мало — от классов никуда не деться, они все равно потребуются на определенном уровне абстракции, поэтому зачем изначально себя их лишать?
На данный момент RTLD поддерживает Windows и Linux, компилируется под x86_64 и AArch64. Некоторые ее модули платформонезависимы, и их можно использовать в системной разработке, под bare metal.
Текущий список фич:
rtld.core — ключевые функции: работа с динамической памятью, загрузчик библиотек, потоки, мьютексы, создание окна
rtld.gl— биндинг к OpenGL ES 2/3 и создание контекста (поддерживаются Windows и Linux/X11)
rtld.libc — функции библиотеки C
rtld.math — элементарные математические функции
rtld.random — генератор псевдослучайных чисел
rtld.sys.windows — функции WinAPI
rtld.sys.posix — функции POSIX
rtld.sys.linux — функции Linux
rtld.text — текстовые кодировки
rtld.time — функции даты-времени, наносекундный таймер.
Закономерен теперь вопрос архитектуры будущей dlib2. Я склоняюсь к мысли отказаться от dcore в пользу RTLD — это будет базовый бэкенд dlib2, реализующий львиную долю функциональности, которая не зависит от GC. К сожалению, полный отказ от GC в dlib невозможен по ряду причин, но я надеюсь сильно сократить его присутствие.