Skip to content

Latest commit

 

History

History
206 lines (173 loc) · 20.2 KB

ROADMAP.md

File metadata and controls

206 lines (173 loc) · 20.2 KB

Нативный порт Bloodborne: что сделано и что дальше

Основной текст — состояние на 2026-09-26; ниже первым разделом — что изменилось к 30.09. Самый подробный срез: CURRENT_STATUS_2026-09-29.md. Отчёт о работе 30.09–01.10 (конвейер GPU, апскейлер, падение, лаунчер, AppImage): SESSION_2026-09-30.md. Подробности по отдельным темам: parallel_gpu.md (многопоточность GPU, подтормаживания при подгрузке), 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): текстуры на отдельном потоке параллельно с буферами работают корректно, но прироста не дают — данные каждого 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).