Record the Metal/offscreen camera picture acceptance
build / mod (push) Failing after 22s

The final engine 6a53a626c with the API30 AirDef build was run in the
real game (macOS, Apple M5, Metal, --offscreen, a clean HORIZON_HOME and
copied test worlds), not only in the sandbox: the monitor and the film's
main view report ready with the picture actually drawn (screenshots show
the panel and picture area, not a registered target), an empty set-views
drops the request, a world change bumps the generation and clears it, and
AirDef's next submission prepares the camera again in the new world.

Fixes nothing: no defect showed. It also records what the run does not
prove (a human visual check, Windows/other GPUs, two runs with the same
local id on the GPU, a mod reload on the GPU), the per-tick
set-views/set-main-view ordering that can honestly read awaiting-frame
between tick and note (not flicker), and that a title trip back into the
same world keeps the request because the generation is per world.

Co-Authored-By: Kimi Code <noreply@moonshot.cn>
This commit is contained in:
2026-11-04 21:03:34 +03:00
parent 9217f9a5cc
commit 61aaa0bf35
3 changed files with 59 additions and 5 deletions
+9 -3
View File
@@ -38,7 +38,12 @@
экран реально использовал (чужой тот же local ID и чужая картинка его не готовят). `enabled` —
последний отмеченный кадр был кадром мира, не заголовком. Пустая `set-views` и смена мира
очищают заявку/выбор/готовность, reload начинает заново; главный вид теряет picture target до
нового кадра. Проверено настоящими Wasmtime-гостями; GPU-приёмка не выполнялась.
нового кадра. Проверено настоящими Wasmtime-гостями. Итоговый engine `278f356aa` с AirDef API30
проверен и в запущенной игре на Metal/offscreen (Apple M5, чистый `HORIZON_HOME`, копии тестовых
миров): monitor даёт `ready` с нарисованной картинкой (по снимкам), film-main-view — `ready` с
main-view (на экране карточка подготовки фильма), пустая заявка
и смена мира — `not-requested` с новым поколением, после deploy+monitor камера снова готова;
команды и ограничения — в [ENGINE.md](ENGINE.md#gpu-приёмка-картинки-камер-metaloffscreen).
- **#96:** engine `e44ad82a9`: opt-in `audio::tests::export_moving_mass_raid` проводит
100 движущихся двигателей и 16 импульсных источников через настоящие `Audio::tick_acoustics`
и `film_mix`: эхо/реверб, камера, инвалидация и смена epoch, новый capture без старого хвоста.
@@ -88,8 +93,9 @@ GUI/MP4 и варианты комплексов (разные ракеты/пр
command max 1013387/1000000000, ошибок 0, build identity совпал.
Не завершены: субъективное прослушивание, настоящий MP4 с акустикой, полный 10-минутный
replay/export, расширенная модельная/ночная/FPS приёмка, GPU-приёмка camera-ready картинки и полные
query/voice/peak-memory бюджеты. Старый допуск broadband RT60 35% не ужесточался до 15%.
replay/export, расширенная модельная/ночная/FPS приёмка, визуальная/Windows-GPU приёмка
camera-ready картинки и полные query/voice/peak-memory бюджеты.
Старый допуск broadband RT60 35% не ужесточался до 15%.
Попытка живого MP4 в этом проходе не дала проверенного файла и за приёмку не считается;
изолированные процессы закрыты. Продолжать с текущего pin, не с временных пакетов агентов.
+49 -1
View File
@@ -166,7 +166,55 @@ local ID выбрали два мода, экран использует выб
другого мира не рисуются), перезагрузка мода начинает заново, а повторная отправка и камера,
отданная в main-view, ждут нового кадра (у такой камеры нет своего picture target).
Проверено двумя настоящими Wasmtime-гостями с одинаковым local ID, пустой заявкой, сменой мира
и reload. `/airdef capabilities` показывает строку камер. Проверки хоста не заменяют GPU-приёмку.
и reload. `/airdef capabilities` показывает строку камер.
### GPU-приёмка картинки камер (Metal/offscreen)
Итоговый engine `278f356aa` с AirDef API30 проверен в запущенной игре, а не только в песочнице:
macOS, Apple M5 (Metal, IntegratedGpu), `--offscreen`, `HORIZON_NO_AUDIO=1`, чистый
`HORIZON_HOME=/tmp/airdef-camera-accept` и копии тестовых миров из scratch-папки прежних прогонов
(`AirDefenseLab`, `Polygon`), ресурсы лаунчера v0.2.91. `.hmod` — из этого дерева
(`python3 tools/airdef.py mod`, API30), не из основного дерева.
```
tools/airdef.py install # HORIZON_HOME=<scratch>
horizon-ctl --socket $H/ctl.sock launch --game horizon/target/fast/horizon-client \
--world AirDefenseLab --creative --offscreen --wait --resources <26.3>
# мод-команды клиентские: ctl command/chat уходят в консоль сервера, поэтому — через поле чата
horizon-ctl key t tap; horizon-ctl type "/airdef capabilities"; horizon-ctl key enter tap
horizon-ctl screenshot <png>
```
Наблюдения (строки `/airdef capabilities`, `поколение` = generation):
| Когда | Камеры |
| --- | --- |
| камер нет | `API=true, включено=true, запрос=false, подготовлено=false, поколение=1, not-requested, main=нет, []` |
| `/airdef deploy s400` + `/airdef monitor` | `... запрос=true, подготовлено=true, поколение=1, ready, main=нет, [32:ready]` |
| `/airdef monitor` (пустая заявка) | `... запрос=false, ... not-requested, main=нет, []` |
| `/airdef replay film best` | `... main=1996488705, [1996488705:ready]`, затем `main=1996488707` на следующем плане |
| другой мир (AirDefenseLab → Polygon) | `поколение=2, запрос=false, ... not-requested, main=нет, []` |
| там же deploy+monitor | `поколение=2, запрос=true, подготовлено=true, ready, [32:ready]` |
Снимки подтверждают, что `prepared` — нарисованная картинка, а не регистрация (число различных
цветов, выборка каждого 6-го пикселя): при взгляде в небо (кадр однородный) включение монитора
добавляло панель и picture-область — 477→4867 цветов на кадре; в том же мире A/B
«монитор выключен/включён» в области панели: 199→2080 цветов,
доля тёмной панели 1.2%→48.7%, а в области картинки 110→1771 цветов с доминирующим небом (рисуется
сцена с камеры С-400, а не плоская заглушка «НЕТ СВЯЗИ»). В film-режиме экран показывал карточку
«Готовлю кадры…» (фильм готовит планы), при этом main-view milestone был `ready` — это API-отметка
и отрисовка кадров рендерером, не проверка пикселей фильма.
`title → тот же мир` не меняет поколение: заявка и milestone сохраняются (смена поколения — это
смена мира), а `enabled` сбрасывается кадром заголовка (note с `world=false`), поэтому `ready`
требует нового кадра мира после возврата; он и наступает (наблюдалось). 8 из 8 запросов при
работающем мониторе дали `ready`. `set_views`/`set_main_view` вызываются модом каждый tick, то есть каждый
tick начинает ожидание нового кадра: выборка между tick и note может честно показать
`awaiting-frame` по порядку вызовов — это не flicker, а порядок tick → render → note.
Остаток этой приёмки: визуальная оценка человеком, Windows/другие GPU, два запуска с одинаковым
local ID на GPU (покрыто Wasmtime-гостями), reload мода на GPU (покрыт host-тестом), fence/представление
кадров не проверялись.
Остаток #102: полные query/voice/peak budgets,
GPU/готовый MP4 и платформенная приёмка. Эти результаты текущими тестами не объявляются выполненными.
+1 -1
View File
@@ -20,7 +20,7 @@
| #91 | Общий каталог доступности и потребители меню/инвентаря; явный RM48U-профиль; корректные подписи очередей; `catalog/specs.json` — единственный источник числовых строк, из него генерируются Rust-таблицы для мода и `airdef-core`, CI проверяет свежесть | Варианты комплексов (разные ракеты/профили по батареям) и игровая приёмка; каталог остаётся статичными данными, не динамическим ECS |
| #92 | Authored overrides, проверка ссылок/PNG/границ, manifest, безопасная транзакционная генерация; registry/texture/icon modules | Дальнейшее ручное улучшение контента относится к #115 |
| #96 | Акустические пути; измеренные синтетические occlusion/echo/reverb fixtures; лицензии и исходные notices в архивах; настоящий MP4 с акустикой: пары on/off, статусы ready, окклюзия/поглощение и диффузный wet-остаток в замкнутой геометрии | Прослушивание, игровой массовый звук/CPU, чистый хвост/RT60 в MP4; точность RT60 пока по допуску 35%, не 15% |
| #102 | Pinned engine/API30, packer/build identity; smoke/acoustics/capture-owner/light/source/owner-scoped camera milestones; fallback/владение; WASM27 и flat stress271; измеренный callback fuel; JSON provenance/failure tests; Metal/no-audio smoke; URL/Git-регрессия; camera-ready по закодированному кадру с per-run/per-world сбросом | Старое69-шаговое утверждение о перекрытии отозвано; GPU-приёмка картинки камер, полные query/voice/peak budgets, GPU/готовый MP4 и Windows-приёмка остаются |
| #102 | Pinned engine/API30, packer/build identity; smoke/acoustics/capture-owner/light/source/owner-scoped camera milestones; fallback/владение; WASM27 и flat stress271; измеренный callback fuel; JSON provenance/failure tests; Metal/no-audio smoke; URL/Git-регрессия; camera-ready по закодированному кадру с per-run/per-world сбросом; GPU-приёмка monitor/main-view на Metal/offscreen (Apple M5) | Старое69-шаговое утверждение о перекрытии отозвано; визуальная/Windows-GPU приёмка картинки камер, полные query/voice/peak budgets, GPU/готовый MP4 и Windows-приёмка остаются |
| #104 | Движок вынесен в `chexit/horizon-airdef`, ветка `airdef`; AirDef использует точный gitlink | Отдельная Windows-проверка миграции старого standalone checkout |
| #107 | ПУ оценивается по наблюдениям: обратный курс не выдаёт точную ПУ | Повторная игровая проверка сценариев с маневрирующими целями |
| #110 | Изменения чанков инвалидируют акустические снимки/кэш; включено в pin и проверено engine-тестами | Внешняя игровая приёмка на целевых машинах |