# Нативный порт Bloodborne: что сделано и что дальше Основной текст — состояние на 2026-09-26; ниже первым разделом — что изменилось к 30.09. Самый подробный срез: [CURRENT_STATUS_2026-09-29.md](history/CURRENT_STATUS_2026-09-29.md). Отчёт о работе 30.09–01.10 (конвейер GPU, апскейлер, падение, лаунчер, AppImage): [SESSION_2026-09-30.md](history/SESSION_2026-09-30.md). Подробности по отдельным темам: [parallel_gpu.md](parallel_gpu.md) (многопоточность GPU, подтормаживания при подгрузке), [upscaler.md](upscaler.md) (анализ кадра игры, константы сцены). ## Обновление 30.09 - Сделано после 26.09: FSR 4 INT8 (v07), векторы движения объектов, смена пресета без перезапуска (уменьшенные цели сцены; глубина D32S8 копируется шейдером), LTO и PGO, масштабирование подготовки draw под число потоков (Steam Deck тоже). - Проблемы из раздела «Известные проблемы» ниже: пункт 3 (перезапуск при смене пресета) решён; пункт 1 (векторы объектов) реализован, у FSR 4 остаётся гостинг на персонаже при Ultra Performance; пункт 2 (мыльный интерфейс) — UI рисуется в 1920×1080. - Ограничение: уменьшенный рендер сцены (`SceneTargets::Eligible`) требует цель 1920×1080, то есть работает только при выводе 1080p. - Распараллеливание потока GPU-команд (шаг 2 [parallel_gpu.md](parallel_gpu.md)): текстуры на отдельном потоке параллельно с буферами работают корректно, но прироста не дают — данные каждого draw переезжают между ядрами. Узкое место — поток GPU-команд: 91% на CPU, ~9% ожидания мелких копий гостевой памяти перед fence. Дальше — двухстадийный конвейер (второй поток владеет текстурным кешем и записью draw, копия регистров из дельт сканера) или мемоизация привязок текстур между кадрами; см. «What would scale» в parallel_gpu.md. - **Двухстадийный конвейер draw** (`vk_draw_pipe.h`): поток GPU-команд декодирует PM4 и выбирает пайплайн, второй поток (`bb:DrawRec`) со своей копией регистров привязывает ресурсы и записывает draw. +19% FPS на 16 потоках, +18% на 8 (как Steam Deck). Включён по умолчанию при 8+ потоках (`BB_DRAW_PIPE=0/1`). Узкое место теперь — вторая стадия; подробности и план — в parallel_gpu.md. - Пресеты и нагрузка GPU: сцена на RX 7800 XT стоит мало, поэтому пресет меняет время GPU лишь на ~0.5 мс, а сам FSR 4 при выводе 1080p — ~1.4 мс (FSR 4 Ultra Performance дороже нативного рендера без апскейлера). Исправлено: проходы освещения оставались в 1920×1080 при любом пресете (проверка смотрела на чужие слоты целей); уменьшенные цели теперь сэмплируются напрямую, без ресэмплинга в натив (кэш шейдеров пересобирается один раз). Следующее для Steam Deck — гостевая копия памяти целей рендеринга `3d5ebf4e` (см. parallel_gpu.md). - **Исправлено падение с конвейером** (порча гостевой кучи, guest offset `0x263b8e7`, через 13–17 минут): прерывание «GPU простаивает» уходило раньше меток EOP, отложенных в поток записи Vulkan, и игра освобождала объекты с этими метками. Теперь перед ним конвейер и отложенные метки дожидаются; 2 прогона по 30 минут без падений (до исправления — 7 из 7 падений). - **Разрешение вывода 1440p/2160p** (меню «Разрешение вывода», bbport.ini `output_res`, после перезапуска): сцена рисуется в разрешении пресета от выхода, апскейлер (FSR 3 или FSR 4) дорисовывает кадр, интерфейс растеризуется в выходном разрешении. Эффекты игры (аберрация, DoF, размытие, SSAO, сглаживание игры, динамические тени, SSR, заставки, LOD) — там же. - **Лаунчер** (`launcher/bb-launcher.sh`, GTK4/libadwaita) и **AppImage** для Steam Deck (`bash packaging/appimage.sh` → `dist/`; данные в `~/.local/share/bbport`, `--play` — запуск без окна лаунчера). - Инструменты: `BB_PAD_FILE` (скриптовый ввод геймпада), `ab.sh` (A/B битов `BB_TOGGLE_FILE` в запущенной игре), в `Frame stats` — простой и блокировки потока GPU. ## Как устроен порт - Оригинальный eboot (CUSA03173 v01.09) исполняется напрямую на x86-64. Системные библиотеки PS4 заменены своим HLE-рантаймом на C (`runtime_*.c`, `probe.c`). - Графика: видеоядро и рекомпилятор шейдеров shadPS4 (GPL), собранные в `libbbgpu.so` (`gpu/`), с собственными доработками. Эмулятор shadPS4 целиком не используется. - Патчи игры (FPS, разрешение и др.) — XML сообщества (`patches/Bloodborne.xml`), компилируются `patches.py` и накладываются загрузчиком при старте. ## Сделано ### Производительность и плавность | Что | Результат | |---|---| | Запись команд Vulkan в отдельном потоке, кеши текстур/буферов, rwlock вместо мьютекса | 26 → 64 FPS в одной сцене | | Подготовка draw-вызовов на 4 потоках (`bb:DrawPrep`), проверка на потоке GPU | +11.5% | | Окно снятия защиты 256 КиБ при записи игры в память (меньше page fault) | +22% | | Кеш описаний текстур, быстрый путь для тех же render target | до ~94 FPS на улице | | Копирования гостевой памяти на пуле потоков, пул staging-буферов | фризы при подгрузке 60–170 мс → 40–50 мс | | Ожидание копий перед видимыми игре fence | убрано мерцание интерфейса | | Режим «Readbacks Relaxed» | нет «взрывов вершин» (FaceGen) | | Vblank 480 Гц + лимит кадров до min(монитор, 120), вывод сразу по флипу | ровная подача кадров; бег не замедляется выше 120 FPS | Всё переключается во время игры через `BB_TOGGLE_FILE` (битовая маска) для A/B-сравнений. Статистика: `BB_FRAME_STATS=1`. ### Звук, ввод - Вывод звука с правильным темпом (раньше щелчки каждые 10.7 мс). - Геймпад через SDL3, запасная раскладка клавиатуры. ### Анализ кадра - `BB_CAPTURE_TRIGGER=<файл>` записывает один кадр: проходы, цели, шейдеры, текстуры, константы, режимы смешивания. - Разобрано устройство кадра Bloodborne (G-buffer, свет, цвет сцены RGBA16F, туман, пост-обработка, тонмаппинг, сглаживание игры, интерфейс) и 864-байтные константы сцены (матрицы вида и проекции). ### Временной апскейлер (FSR 3.1) - **Векторы движения камеры**: из глубины сцены и матриц текущего и прошлого кадра (`vk_camera_motion.cpp`, `camera_motion.comp`). Проверены перепроецированием прошлого кадра: статичная геометрия совпадает. - **Jitter**: субпиксельный сдвиг геометрии сцены через viewport, последовательность Halton(2,3); число фаз 8·(вывод/рендер)². Интерфейс и пост-обработка не сдвигаются. - **FSR 3.1** (FireBurn/FSR-Vulkan, нативный Vulkan, подмодуль `gpu/third_party/fsr-vulkan`): - *Native AA*: на HDR-цвете сцены перед пост-обработкой, 1:1. - *Пресеты Quality/Balanced/Performance/Ultra Performance* (x1.5/1.7/2/3): игра рендерит в пониженном разрешении (патч разрешения, который `patches.py` выводит из патча 720p сообщества), FSR увеличивает готовый кадр до 1920x1080 перед первым проходом интерфейса. Интерфейс и проход вывода перенаправлены в изображения полного размера, презентер показывает их вместо буфера игры. - **Маска реактивности** (снимок сцены до прозрачных отрисовок, сравнение перед наложением тумана): работает, но на дымке Bloodborne даёт дрожание — по умолчанию выключена. - **Внутриигровое меню** (Dear ImGui, Insert или L3+R3): апскейлер, пресет, резкость, jitter, маска, счётчик FPS. Настройки в `bbport.ini`. Смена пресета — кнопка «Применить и перезапустить игру». ## Известные проблемы Состояние последнего коммита. В рабочем дереве подготовлен перенос пресетов на уменьшенные цели рендера при сохранении гостевых буферов, постобработки и UI в 1920×1080. Переходы между пресетами и копирование цвета/глубины/stencil прошли Vulkan-тест на Lavapipe. RX 7800 XT не поддерживает blit D32S8, поэтому новый путь оставлял FSR вход 1920×1080 и снижал FPS. Для таких GPU запуск теперь автоматически выбирает проверенный путь с патчем разрешения игры и UI 1920×1080; смена пресета снова требует перезапуска. На GPU с нужной поддержкой остаётся переключение без перезапуска. Пункты 2–3 ниже относятся к последнему коммиту, до этих изменений рабочего дерева. Общий проход векторов движения объектов был слишком дорогим: Performance давал около 49 FPS с ним и 77–78 FPS без него. Теперь дополнительная цель и шейдеры включаются только для G-buffer отрисовок с буфером позы/костей; остальные используют векторы камеры. В пробном запуске выборочный путь держал около 81–87 FPS, без пропусков из-за ёмкости истории. Векторы объектов включены по умолчанию; `BB_OBJECT_MOTION=0` отключает их, а `BB_OBJECT_MOTION_ALL=1` возвращает старый общий путь для сравнения. Выбор по размеру буфера пока эвристический: качество оружия и одежды в движении требует проверки в игре. 1. **Движущиеся объекты «рассыпаются»** (оружие на спине, персонаж, ткань, враги): есть только векторы движения камеры. Камера от третьего лица следует за персонажем, поэтому векторы камеры для него неверны, и апскейлер берёт историю не из того места. Это касается любого временного апскейлера (FSR 3/4, DLSS, XeSS). 2. **Интерфейс в пресетах мыльный**: с патчем разрешения игра считает себя 540p-игрой и, судя по всему, готовит шрифты и элементы интерфейса под это разрешение. Меню (титульное, пауза) вообще не проходят через апскейлер. 3. **Смена пресета требует перезапуска**: разрешение задаётся патчем кода при старте, а буферы игра выделяет один раз. ## План ### 1. Векторы движения объектов Нужны всем апскейлерам и генерации кадров. Игра их не считает, поэтому считаем сами. Как: - Для каждой отрисовки в G-buffer (проходы с 5+ целями) рекомпилятор делает второй вариант вершинного шейдера, который выдаёт позицию дважды: с текущими константами и с константами прошлого кадра. Разница проекций — вектор движения, пишется во вспомогательную цель RG16F как дополнительный выход пиксельного шейдера. - Константы прошлого кадра: для каждого draw запоминаем содержимое константных буферов (матрица объекта, кости скелета) по ключу «шейдер + номер draw в проходе» или по адресу данных. Нужно выяснить, как игра хранит матрицы скелета: в буферах, которые перезаписываются каждый кадр (тогда копируем прошлую версию), или в кольцевом буфере (тогда достаточно адреса прошлого кадра). - Где объект не найден (первый кадр, новый объект) — векторы камеры, как сейчас. - Проверка: отладочный вид векторов (`BB_DEBUG_MOTION`), перепроецирование прошлого кадра по полным векторам, визуально — пила на спине при беге. ### 2. Масштабирование на уровне рендерера (вместо патча разрешения) Игра работает в 1920x1080 (или в разрешении монитора), а в пониженном разрешении рисуются только проходы 3D-сцены. Интерфейс и меню остаются чёткими, пресет меняется на лету. Как: - Кеш текстур выделяет для целей сцены (G-buffer, глубина, свет, цвет сцены, эффекты) копию уменьшенного размера; гостевая память и описания игры не меняются. - Viewport и scissor проходов в эти цели масштабируются (как уже сделано для интерфейса, включая проходы с отключённым отсечением). - Шейдеры, которые считают по пиксельным координатам (`gl_FragCoord`, `texelFetch`, compute-шейдеры по пикселям), получают коэффициент масштаба через push-константы рекомпилятора. Выборки по нормированным координатам работают без изменений. - FSR ставится туда же, где Native AA: цвет сцены перед пост-обработкой (HDR, лучшее качество); пост-обработка и интерфейс идут в полном разрешении. - Риски: проходы, читающие цели сцены по пиксельным координатам в пост-обработке, и чтения из гостевой памяти этих целей (их нужно запретить или масштабировать обратно). ### 3. Другие апскейлеры Все используют одни и те же входы (цвет, глубина, векторы движения, jitter, маски). - **FSR 4 (INT8)**: в FSR-Vulkan есть экспериментальный провайдер FSR 4 v07 INT8 — добавить как вариант в меню и сравнить с FSR 3.1 после шага 1. - **DLSS**: нативный Linux Vulkan SDK (NGX). На RX 7800 XT не работает, но нужен для пользователей NVIDIA. - **XeSS / XeFG и OptiScaler**: Intel поставляет их только как Windows DLL. Варианты: загрузчик Windows DLL (PE) внутри процесса либо запуск всей сборки под Proton с OptiScaler, которому отдаём входы через интерфейс DLSS. Проверено 29.09: libxess.dll (одинаковая у DOOM: The Dark Ages, PRAGMATA и др.) имеет Vulkan-путь (`xessVKCreateContext`, `xessVKExecute`), но импортирует ~300 функций: MSVCP140 (iostream), VCRUNTIME140 (C++-исключения), UCRT, kernel32, setupapi, dxgi. Решено отложить; самый реалистичный путь — хелпер под Wine с общей памятью Vulkan. ### 4. Генерация кадров - FSR 3.1 Frame Generation (есть в FSR-Vulkan): промежуточный кадр между двумя готовыми, по тем же векторам движения; интерфейс нужно рисовать поверх отдельно (есть перенаправление интерфейса — его можно рендерить в отдельный слой). - XeFG — после решения с Windows DLL (см. выше). - Требование: подача кадров через презентер (очередь и VRR уже работают). ### 5. Прочее - Steam Deck: портативная сборка (patchelf, без Nix), проверка пресетов на 1280x800. - Дальнейшая разгрузка потока GPU (шаг 2 из [parallel_gpu.md](parallel_gpu.md)).