w23 / xash3d-fwgs

Vulkan Ray Tracing fork of Xash3D FWGS engine. Intended to be merged into master at some point in the future.
160 stars 16 forks source link

Modules API #714

Open nilsonragee opened 5 months ago

nilsonragee commented 5 months ago

Как мы знаем, все наши Vulkan-овские модули внутри ref/vk так или иначе имеют концепцию инициализации и деинициализации посредством вызова функций:

Данная концепция подразумевает, что перед тем, как использовать что-то из нужного нам модуля, мы сначала должны этот модуль инициализировать, а когда он нам не нужен, то мы вызываем деинициализацию, чтобы этот модуль сделал все необходимые действия для плавного возвращения всех ресурсов, которые он занял, обратно в систему.

Реализовано это у нас очень просто, но эта простота упускает реализацию достаточно важных деталей:

  1. Состояние инициализации

    Мы его просто напросто не знаем. То есть каждый раз перед тем, как использовать функционал модуля, мы должны либо инициализировать его, даже если он уже инициализирован, так как мы не знаем об этом, либо надеяться на то, что кто-то уже сделал это до нас.

  2. Зависимости

    Все они задаются вручную и никак не отслеживаются самим модулем. Нет какого-то определенного списка зависимостей, который мы просто можем взять и посмотреть, а также, чтобы это сделал сам модуль и проинициализировал их, если это еще не было сделано. "Списки" этих зависимостей нигде не хранятся, кроме как в самом коде в виде вызовов их функций инициализации, которые обычно идут списком внутри функции xxx_Init().

Этот PR является попыткой все это реорганизовать и вынести в отдельный, доведенный до ума API. Намеки на надобность такого рода API уже есть комментариях самого кода:

https://github.com/w23/xash3d-fwgs/blob/a0b36a4301fbd718a4c3ae85bbe06d9efa50d6df/ref/vk/vk_core.c#L680-L707

Осталось лишь понять как именно этот API реализовать и что конкретно мы от него хотим. Я выделил следующие критерии (за исключением всяких "простота в использовании", "понятность" и т.д. - берем это, как базовые критерии):

  1. Задание зависимостей - чтобы мы вручную не прописывали все Init-ы внутри других Init-ов.
  2. Автоматическая иниациализация всех заданных зависимостей - чтобы мы вызвали у модуля Init и были уверены в том, что все зависимости будут прогружены и модуль будет готов к работе.
  3. Результат инициализации - чтобы знать, что модуль инициализирован, а если нет, то в чем заключается ошибка.
  4. Отслеживание состояния - чтобы знать текущее состояние модуля: еще не инициализирован, инициализирован, деинициализирован и т.д.

Это был небольшой Specification, надеюсь мои мысли и идеи совпадают с первоначальными. Вот как примерно выглядит код инициализации и деинициализации модулей сейчас:

https://github.com/w23/xash3d-fwgs/blob/a0b36a4301fbd718a4c3ae85bbe06d9efa50d6df/ref/vk/vk_core.c#L765-L783

https://github.com/w23/xash3d-fwgs/blob/a0b36a4301fbd718a4c3ae85bbe06d9efa50d6df/ref/vk/vk_core.c#L838-L853

Первоначально хотел показать реализацию непосредственно внедрив ее сразу, но столкнулся с тем, что не все модули имеют простой Init без аргументов - некоторые ожидают параметры, которые создаются на этапе других модулей, которые зависят от других и так далее...

Такая проблема есть в vk_swapchain, где инициализация ожидает внешние параметры: https://github.com/w23/xash3d-fwgs/blob/a0b36a4301fbd718a4c3ae85bbe06d9efa50d6df/ref/vk/vk_swapchain.c#L184

Эти параметры потом сохраняются в глобальное состояние: https://github.com/w23/xash3d-fwgs/blob/a0b36a4301fbd718a4c3ae85bbe06d9efa50d6df/ref/vk/vk_swapchain.c#L196-L197

Если посмотреть саму структуру где они хранятся, то видим комментарий, что они тут быть и не должны: https://github.com/w23/xash3d-fwgs/blob/a0b36a4301fbd718a4c3ae85bbe06d9efa50d6df/ref/vk/vk_swapchain.c#L9-L12

Сам модуль vk_swapchain инициализируется в модуле vk_framectl (кстати не знаю что за framectl, понятно лишь то, что frame - значит связано с кадрами, #709): https://github.com/w23/xash3d-fwgs/blob/a0b36a4301fbd718a4c3ae85bbe06d9efa50d6df/ref/vk/vk_framectl.c#L420-L432

Идем в заголовок и видим, что и здесь это не должно быть: https://github.com/w23/xash3d-fwgs/blob/a0b36a4301fbd718a4c3ae85bbe06d9efa50d6df/ref/vk/vk_framectl.h#L13-L22

Если посмотреть чуть выше, то видим комментарий, что тут вообще всех этих глобальных переменных не должно быть: https://github.com/w23/xash3d-fwgs/blob/a0b36a4301fbd718a4c3ae85bbe06d9efa50d6df/ref/vk/vk_framectl.h#L8C1-L8C1

// TODO most of the things below should not be global. Instead, they should be passed as an argument/context to all the drawing functions that want this info

Такой вложенности мне хватило, чтобы понять, что сам я тут точно не разберусь... Наверно это надо в отдельную ишью вынести, ну ладно, написал значит написал, может потом создам, где сразу для всех модулей выпишу эти зависимости.

Жду отзывов на данное творение и возможные предложения/исправления.

nilsonragee commented 4 months ago

Выкатил первую рабочую версию, НО - проверял только в растере, в RT рендере скорее всего не работает. Возможно оно будет работать, если происходит запуск сразу на RT, но переключение между рендерами точно работать не должно из-за логики работы связанных с RT модулями - подробнее в комментариях ревью.

Пока что все сообщения инитов / деинитов пишутся в консоль, но скорее всего нужно будет добавить что-то, что будет это контролировать, т.к. спамит достаточно. Хотя сразу видно какой модуль когда включен, когда выключен. Как это реализовать пока что не знаю - сделать ручную проверку аргумента типа -vkdbgmod или как-то через vk_logs реализовать, я пока что не разобрался и у меня уже просто мозг кипит от этого, потому что работал над этим целую неделю практически без перерыва.

Если честно мне уже тошно от этого и пишу все это через силу, но я понимаю, что никто за меня ход моих мыслей и идей объяснять не будет, поэтому приходится. По сути большая часть работы сделана, осталось довести до конца, отполировать к финальному, готовому виду.

К сожалению коммиты читать очень тяжело, потому что они в спаме изменений из-за того, что я все функции инитов и деинитов перенес в конец файлов, т.к. они в разных файлах были в разных местах, плюс если они в конце файла, то никакие лишние форвард-декларации плодить не придется. Во всяком случае постарался писать комментарии в ревью под значимыми кусками кода, чтобы не потеряться в спаме.

На этом, наверно, пока все - буду ждать разбора на стриме. А до этого, я наверно немного развеюсь, потому что реально уже голова кипит мало того, что от комплексности самой проблемы и методов реализаций, так еще и от того, что это нужно все объяснять... В общем, надеюсь меня поняли.

nilsonragee commented 4 months ago

Мержить пока нельзя, есть еще косяки - просто жду ревью текущих изменений.

nilsonragee commented 4 months ago

Т.к. во вкладке измененных файлов будет много лишних коммитов, в том числе не моих из-за rebase до текущего состояний ветки, то вот небольшой гайд как выбрать конкретные коммиты:

image

Для этого нужно зайти во вкладку коммитов и пролистать в самый низ (новые коммиты начинаются снизу). Дальше советую выбрать коммиты от самого нового до vk: modules: distinguish all possible modules (99d3fc5): для этого нужно с зажатым шифтом сначала нажать на самый нижний коммит, а затем на тот, до которого будем смотреть изменения - во время выделения они будут подсвечиваться желтым.

image

w23 commented 4 months ago

Это гигантская работа, спасибо! У меня займёт сколько-то часов её переварить. Буду оставлять комментарии по мере того, как появляется время переваривать.

w23 commented 2 months ago

Йоу @nilsoncore чё каво? Я тут потихоньку восстанавливаюсь-выкарабкиваюсь, и думаю, что вот это всё тут через недельку-другую мне может понадобиться. Если у тебя нет времени на это глянуть, могу ли я взять твои наработки, и допилить их сам?

nilsonragee commented 1 month ago

Йоу @w23

Решил я таки добить этот PR, но в текущем виде скорее всего это уже невозможно - услышал где-то про элегантность ребейза и зафакапил тут все. Скорее всего придется создать новый и ссылаться на этот для истории обсуждения.

Если честно, придется заново пробежаться по всему, что я тут наплодил и вникнуть, благо комментарии вроде обширные оставлял. Комментарии все прочитал и учту в новом PR, постараюсь не раздувать лишним.

Я тут потихоньку восстанавливаюсь-выкарабкиваюсь, и думаю, что вот это всё тут через недельку-другую мне может понадобиться. Если у тебя нет времени на это глянуть, могу ли я взять твои наработки, и допилить их сам?

Как сказал выше, думаю все же допилить, но если сильно надо и есть прям четкое видение как все это реализовать, то конечно, я не против, могу заняться чем-то другим, потому что пока насчет финального вида я на 100% не уверен, плюс забыл все, надо вспоминать.

w23 commented 1 month ago

Решил я таки добить этот PR, но в текущем виде скорее всего это уже невозможно - услышал где-то про элегантность ребейза и зафакапил тут все. Скорее всего придется создать новый и ссылаться на этот для истории обсуждения.

Если честно, придется заново пробежаться по всему, что я тут наплодил и вникнуть, благо комментарии вроде обширные оставлял. Комментарии все прочитал и учту в новом PR, постараюсь не раздувать лишним.

Ага, мы тут все выпали и потеряли контекст.

Я тут потихоньку восстанавливаюсь-выкарабкиваюсь, и думаю, что вот это всё тут через недельку-другую мне может понадобиться. Если у тебя нет времени на это глянуть, могу ли я взять твои наработки, и допилить их сам?

Как сказал выше, думаю все же допилить, но если сильно надо и есть прям четкое видение как все это реализовать, то конечно, я не против, могу заняться чем-то другим, потому что пока насчет финального вида я на 100% не уверен, плюс забыл все, надо вспоминать.

Я всё ещё не смотрел на это внимательно, и абсолютно чёткого видения нет. Но емнип я тут в комментариях ревью накидывал примерный вектор движения, и там начинали вырисовываться очертания желаемого.

w23 commented 1 month ago

Так, пролистал комментарии, и ничего там не вырисовывается. Вернее, оно вырисовывается, но только у меня в голове, никуда напоказ я это не вывалил.

Предлагаю попробовать пройтись тут в комментах через лёгкое дизайн-ревью, т.е. прежде чем писать какой-то код, примерно накидать требования и обсудить апи. И только потом восстанавливать подходящие куски кода из этой ветки в свежую.

Например, сыро и тезисами, что хотим:

Зависимости

Времена жизни модулей

Валидация (опционально)

Аппендикс

Тут, кстати, можно озадачиться тем, чтобы перевести модули со статической модели (где у них есть static struct { .. } g;) на динамическую, где мы этот g маллочим во время инициализации.

Почему:

Как делать

  1. Придумать апи и согласиться <-- мы находимся здесь.
  2. Итеративно -- отдельными PR переводить модули на новую схему по одному. Зачем так: чтобы не плодить megachonker. Можно делать это отдельными PR в ветку с модулями, которая потом большим PR заедет в vulkan. Зачем может быть так нужно: в итеративном процессе может оказаться, что мы что-то придумали не так, и надо поменять. И можно будет это сделать, не ломая vulkan.