Cheb's Game Engine

Планы, идеология, архитектура и т.п.

Модератор: Модераторы

Re: Cheb's Game Engine

Сообщение Cheb » 22.06.2019 09:17:38

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

Зандронум предлагает два варианта выравнивания, оба в той или иной мере уродливые, оба дают артефакты.
1. спрайты всегда вертикальны в экранном пространстве. Нет артефактов при движении, но вертикальные колонны по краям экрана оказываются сильно отклонены от той вертикали, что у стен. Ибо перспектива жеж. Большие спрайты видимо разворачиваются относительно мира когда крутишь камерой. Особенно проявилось, когда я делал спрайтовые версии огромных скал в скайбоксе.
2. спрайты в мировом пространстве, всегда развёрнуты на камеру. Убирает проблемы предыдущего, но приводит к артефактам вблизи: когда идёшь, например, сквозь высокую траву - её спрайты слишком резко разворачиваются за камерой, когда проходишь сквозь них.
Я хочу попробовать гибридно-хитрожопый способ, объединяющий плюсы этих двух, но не имеющмий минусов второго. Но для этого нужна более изощрённая формула, которую хрен запихнёшь в вершинный шейдер. Поэтому надо на цпу.
Но Брутал Дум срёт и спамит спрайтами: когда монстра разносит в клочья, из одного спрайта получаются десятки. Теперь представляем, что монстров на уровне - тысячи.
А я как раз стремлюсь избавиться от ограничений, чтобы огромные карты с ордами монстров летали даже на малине.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 728
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение Cheb » 16.08.2019 21:58:08

Провёл изыскания, выяснил: InterlockedIncrement - та ещё дрянь, по тормознутости практически равна квадратному корню (в полтора раза медленнее деления флоатов).
На основе этого сделал выбор архитектуры с далеко идущими последствиями (фактически однотредная физика, делегирующая дополнительным тредам только самые тупые расчёты). То есть, например, просчёты столкновений в других тредах - будет, но изменение состояния игровых объектов на их основе будет возможно лишь в главном логическом треде.
Последствия - потолок масштабируемости и в лучшем случае ~60% кпд использования остальных ядер.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 728
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение runewalsh » 17.08.2019 04:37:26

>по тормознутости практически равна квадратному корню (в полтора раза медленнее деления флоатов)
Скорее эти операции быстрые, чем InterlockedIncrement медленный. А вообще какой смысл сравнивать тёплое с мягким.

Сейчас проверил, у меня простой инкремент выигрывает у InterlockedIncrement в 10 раз только при инкрементировании ячеек, тесно уложенных рядом. Если же инкрементировать слова с разных кэш-линий (общий случай), разница с простым инкрементом всего в пару десятков %. Это в общем-то и объясняется тем, что основная работа процессора при выполнении атомарной операции — обеспечить когерентность кэша.
Аватара пользователя
runewalsh
постоялец
 
Сообщения: 428
Зарегистрирован: 27.04.2010 00:15:25

Re: Cheb's Game Engine

Сообщение Cheb » 17.08.2019 09:41:29

Ага! Понятно, спасибо, я чуть не облажался.

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

Хммм... Я уже придумал хак, как не дёргать счётчики ссылок базового слоя при расслоении: просто ввести общую на всех дельту и в методе CopyOnChange сравнивать счётчик не с единицей, а с единицей плюс эта дельта, а у ново создаваемых выставлять не в единицу, а в единицу минус дельта.
..хотя нет, бред написал. Это всё хряпнет ся, когда дополнительный слой удалится. Нужно или нормальный инкремент *всем* объектам мира при отпочковывании частичного слоя, либо проходить по *всем* объектам базового слоя и править им счётчик, оказавшийся меньше единицы, при удалении частичного слоя, если я использую общую дельту.

Сделаю-ка сначала строго однотредовое с заложенной возможностью многотредовости - и посмотрю, как полетит.

P.S. Подозреваю, замеренное тобой отсутствие замедления всего лишь переносится в другое место и выстрелит, когда другой участок кода обратится к тому участку памяти. Тормоза ведь образуются за счёт сброса линейки кэша в память, так?

Дано: DDR3 666 (10.3 Гб/с)
InterlockedIncrement выдаёт 0.119 миллиарда операций в секунду. Если при каждой пишется 64-байтная линейка кеша, то получается 7.616 Гб/с
Очень похоже, учитывая, что на ноутбуке пропускная способность памяти отжирается ещё на встроенное видео.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 728
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение Cheb » 22.08.2019 08:58:21

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

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

Хотя сохранятор я таки сделаю классом (сейчас - куча отдельных функций: затачивалось под расширяемость пользователем, которая была впоследствии похерена) и возможность матрёшечно вложенных сохранений тоже будет.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 728
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение Alex2013 » 22.08.2019 15:41:22

Cheb писал(а):...и возможность матрёшечно вложенных сохранений тоже будет.

:shock: Это вообще как ? ( Если про сохранение класса то понятно ... но если про сэйвы в игре то тут даже мое больное воображение точно отказывает )
Изображение
Alex2013
энтузиаст
 
Сообщения: 1473
Зарегистрирован: 03.04.2013 11:59:44

Re: Cheb's Game Engine

Сообщение Cheb » 22.08.2019 23:47:46

Допустим, посреди сохранения одному из объектов приспичило запустить ещё одно сохранение субсета по маске флагов в другой поток, начиная с другого корня.
Пример из практики - ассеты, сохраняющиеся в TMemoryStream матки, чтобы перезапуск длл не вызвал перезагрузку текстур.
Сейчас это реализовано эпическими городушками в отдельной не-класовой системе функций сохранения, где, фактически, две операции сохранения идут одна за другой. А можно будет запихать в метод BeforeSaving основного класса логики, да ещё с возможностью расширения.

Варианты возможны самые разные. Сохранить персонажа в отдельный контейнер для экспорта. Упаковать кусок мира в массив со сжатием, прежде, чем сохранять его. И т.п.

Добавлено спустя 9 часов 45 минут 52 секунды:
Условно,
класс МойКласс (ЧеперсиКласс) //где ЧеперсиКласс имеет поле Индекс: целое, в норме нуль но при сохранении туда пишется порядковый номер объекта
Фитюльки: баклуши;
Следующий: МойКласс;
Сепульки: баклуши;
конец;
переменная А, Б, В: МойКласс;
...
А:= МойКласс.Создать;
Б:= МойКласс.Создать;
В:= МойКласс.Создать;
А.Следующий:= Б;
Б.Следующий:= В;
В.Следующий:= А;

Предположим, Чеперси сохраняет их в поток с А в качестве корня. Тогда в потоке будет:
- А.Индекс (-1)
регистрационный № класса МойКласс
А.Фитюльки
- Б.Индекс (-2)
регистрационный № класса МойКласс
Б.Фитюльки
- В.Индекс (-3)
регистрационный № класса МойКласс
В.Фитюльки
А.Индекс (1)
В.Сепульки
Б.Сепульки
А.Сепульки

- как видим, крайне не рекомендуется использовать длинные цепочки объектов, соединённые ссылками: Чеперси справится, но может потребовать конский размер стека из-за глубокой рекурсии в сохраняторе.

Один из плюсов обновлённого механизма будет отсутствие необходимости чистить индексы в ноль после каждого сохранения. Этот второй проход был чудовищно недружествен кешу, поскольку *каждый* инстанс трастревоживался на запись из-за того, что индекс хранился внутри инстанса, как обычное поле.
Теперь эта память ведётся мемори менеджером и будет просто освобождаться посредством SetLength(, 0)
И это - то, что позволит матрёшечные сохранения, т.к. индексов может быть более одного.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 728
Зарегистрирован: 06.06.2005 15:54:34

Пред.

Вернуться в Разработки на нашем сайте

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1

Рейтинг@Mail.ru