From 2772c39e41c930d41679876842c1f0854ee6f181 Mon Sep 17 00:00:00 2001 From: Valentin Popov Date: Sat, 18 Jul 2026 09:45:57 +0400 Subject: [PATCH] feat(runtime): bound static preview graph roots --- README.md | 2 +- crates/fparkan-runtime/src/lib.rs | 18 +++++++++------ docs/rendering/renderer_truth_table.md | 16 ++++++------- docs/tomes/05-render.md | 31 +++++++++++++------------- 4 files changed, 35 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index bdc0d78..4455504 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Open source проект с реализацией компонентов игр - [apps/fparkan-cli](apps/fparkan-cli) — CLI для архивов, графов и acceptance-отчетов. - [apps/fparkan-viewer](apps/fparkan-viewer) — inspection-only CLI для archive/model/texture/map без live Vulkan draw path. - [apps/fparkan-headless](apps/fparkan-headless) — headless runtime composition root. -- [apps/fparkan-game](apps/fparkan-game) — mission composition root: по умолчанию выдаёт planning report; opt-in `--backend static-vulkan` использует bounded preview loader и открывает native Vulkan окно для первой mesh-backed MSH-модели. +- [apps/fparkan-game](apps/fparkan-game) — mission composition root: по умолчанию выдаёт planning report; opt-in `--backend static-vulkan` использует first-root preview loader и открывает native Vulkan окно для первой MSH-модели выбранного root. ## Текущий статус рендера diff --git a/crates/fparkan-runtime/src/lib.rs b/crates/fparkan-runtime/src/lib.rs index 1d7c499..512ba9b 100644 --- a/crates/fparkan-runtime/src/lib.rs +++ b/crates/fparkan-runtime/src/lib.rs @@ -191,7 +191,7 @@ enum MissionAssetScope { /// Prepare every reachable asset; required by normal runtime loading. #[default] Full, - /// Prepare one root at a time until a mesh-backed preview model is found. + /// Prepare only the first mission root for a static preview. FirstMeshPreview, } @@ -476,9 +476,9 @@ pub fn load_mission( /// Loads a mission using the bounded static-preview asset scope. /// /// This mode preserves map, TMA, graph, construction and registration work, -/// but prepares only the first root that supplies a mesh-backed model. It is -/// intended solely for the opt-in static Vulkan preview and must not be used -/// for normal gameplay, where all reachable assets remain required. +/// but visits only the first mission root. It is intended solely for the +/// opt-in static Vulkan preview and must not be used for normal gameplay, +/// where all reachable assets remain required. /// /// # Errors /// @@ -630,8 +630,12 @@ fn load_mission_with_options_and_progress( .iter() .map(|object| resource_name(&object.resource_name.raw)) .collect(); + let scoped_graph_roots = match options.asset_scope { + MissionAssetScope::Full => graph_roots.as_slice(), + MissionAssetScope::FirstMeshPreview => graph_roots.get(..1).unwrap_or_default(), + }; let (mut prototype_graph, resolved_prototypes, mut prototype_report) = - build_prototype_graph_report(&repository, vfs.as_ref(), &graph_roots); + build_prototype_graph_report(&repository, vfs.as_ref(), scoped_graph_roots); extend_graph_report_with_visual_dependencies( &repository, &mut prototype_report, @@ -649,7 +653,7 @@ fn load_mission_with_options_and_progress( &prototype_graph.root_prototype_request_spans, &resolved_prototypes, ), - MissionAssetScope::FirstMeshPreview => prepare_first_mesh_preview_assets( + MissionAssetScope::FirstMeshPreview => prepare_first_preview_assets( &asset_manager, &prototype_graph.root_prototype_request_spans, &resolved_prototypes, @@ -769,7 +773,7 @@ fn record_load_phase( } } -fn prepare_first_mesh_preview_assets( +fn prepare_first_preview_assets( asset_manager: &AssetManager, root_spans: &[std::ops::Range], prototypes: &[fparkan_prototype::EffectivePrototype], diff --git a/docs/rendering/renderer_truth_table.md b/docs/rendering/renderer_truth_table.md index c4f0ac1..00f756d 100644 --- a/docs/rendering/renderer_truth_table.md +++ b/docs/rendering/renderer_truth_table.md @@ -13,7 +13,7 @@ | `RecordingBackend` | No | No | Optional CPU-side IDs only | `covered-planning` | Stable command capture for backend-neutral tests | Native window, Vulkan, GPU resource lifetime, pixels | | `NullBackend` | No | No | Optional CPU-side IDs only | Usually `covered` for validation-only rows | Command stream framing and bounds validation | Capture stability, GPU execution, pixels | | `VulkanAssetRenderer` | Yes | Yes | Yes | `covered-gpu` | Static original asset rendering: MSH/Texm/WEAR/MAT0/terrain through Vulkan | Animation/FX parity unless explicitly wired | -| `fparkan-game --backend static-vulkan` | Implemented; native run not yet accepted on a full corpus mission | Implemented static MSH draw | First prepared MSH from loaded mission assets | Not yet `covered-gpu` | Opt-in mission-to-native-window bootstrap, static MSH projection and synchronized teardown telemetry | Full mission scene, texture/material binding, placed transforms/orientation, camera, gameplay, original-runtime parity | +| `fparkan-game --backend static-vulkan` | Yes, GOG `Autodemo.00` | Yes, static MSH draw | First MSH from first mission root | `covered-gpu` only for the narrow static-preview bridge | Opt-in mission-to-native-window bootstrap, static MSH projection and synchronized teardown telemetry | Full mission scene, texture/material binding, placed transforms/orientation, camera, gameplay, original-runtime parity | | Future rendered `fparkan-game` mode | Yes | Yes | Yes | `covered-gpu` plus original-evidence IDs | Mission-driven render snapshot execution and pixel capture | Original-runtime parity for animation/FX/x87 without dedicated captures | ## Rules @@ -36,13 +36,13 @@ synthetic window descriptor и `VulkanPlanningBackend`. Opt-in `--backend static-vulkan` уже создаёт native `winit` window и передаёт первую подготовленную MSH модели миссии в `VulkanSmokeRenderer` с пустым списком materials (явный white-fallback). Режим использует - отдельный bounded preview loader: normal `load_mission` по-прежнему готовит все reachable - assets, тогда как preview останавливает asset preparation после первого root с mesh-backed - model. `--load-progress ` writes the last entered loader phase synchronously for timeout - diagnosis. This is not rendered acceptance: fresh GOG `MISSIONS/Autodemo.00/data.tma` test - with this scope still did not reach a window in the local 120-second runner; its checkpoint - was `Graph`, therefore no live report, pixel artifact or validation evidence exists for the - game path. + отдельный first-root preview loader: normal `load_mission` по-прежнему готовит все reachable + assets и весь graph, тогда как preview строит graph и готовит assets только для первого + mission root. `--load-progress ` writes the last entered loader phase synchronously for + timeout diagnosis. Fresh GOG `MISSIONS/Autodemo.00/data.tma` run passed in 38.7 seconds with + one presented frame, native 1280×720 swapchain (2 images), 7,372,800-byte readback hash + `10681850560830502773`, and validation warnings/errors `0/0`. This is `covered-gpu` evidence + for that narrow static-preview bridge only, not full-scene or original-renderer parity. - `apps/fparkan-viewer` сейчас inspection-only CLI и не открывает live Vulkan asset viewer. - Следующий реальный milestone для rendered acceptance: `VulkanAssetRenderer` diff --git a/docs/tomes/05-render.md b/docs/tomes/05-render.md index d55b63b..b689c08 100644 --- a/docs/tomes/05-render.md +++ b/docs/tomes/05-render.md @@ -937,8 +937,8 @@ from a runtime slot or draw order. ### Opt-in mission static-Vulkan bridge `fparkan-game --backend static-vulkan` is an explicit native-window experiment, -not the default planning path. After mission loading it selects the first -prepared MSH model, sends it through the existing static XZ clip-space +not the default planning path. It visits only the first mission root, selects +its prepared MSH model, sends it through the existing static XZ clip-space projection and renders a requested number of frames through `VulkanSmokeRenderer`; teardown rejects validation warnings/errors and reports swapchain/readback telemetry. It deliberately supplies no material textures, @@ -946,21 +946,20 @@ so the renderer's documented white fallback is used. This is a narrow bootstrap from mission assets to a live Vulkan renderer. It does not render every placed object, apply TMA transforms or orientation, bind -WEAR/MAT0/TEXM material data, or establish a game camera. A GOG -`MISSIONS/Autodemo.00/data.tma` attempt exceeded the local 120-second runner -limit before the window/report, so this mode has implementation and unit/lint -evidence only, not a corpus GPU acceptance claim. +WEAR/MAT0/TEXM material data, or establish a game camera. Fresh GOG +`MISSIONS/Autodemo.00/data.tma` evidence now proves the narrow GPU bridge: one +presented frame completed in 38.7 seconds with a native 1280×720 two-image +swapchain, 7,372,800-byte synchronized readback (FNV-1a +`10681850560830502773`) and validation warnings/errors `0/0`. This is not a +full-scene or original-renderer pixel-parity claim. -The preview now asks `load_mission_static_preview` for assets. Normal mission -loading remains full and transactional; the preview scope walks root spans in -TMA order and stops asset preparation after the first mesh-backed model. It is -therefore not a hidden relaxation of gameplay validation. A second GOG -`Autodemo.00` attempt with this narrower asset scope still exceeded 120 seconds -before opening a window. The diagnostic `--load-progress ` checkpoint -reported `Graph`, which proves the remaining startup cost is in prototype graph -construction/visual-dependency expansion rather than terrain decode, asset -preparation, window creation or the Vulkan draw loop. The timeout probe does -not distinguish individual graph suboperations; no renderer acceptance follows. +The preview now asks `load_mission_static_preview` for both graph and assets. +Normal mission loading remains full and transactional; preview graph traversal +and asset preparation are restricted to the first TMA root. It is therefore not +a hidden relaxation of gameplay validation. The preceding all-root preview +probe timed out at `Graph`; this reduction is what allowed the successful GOG +native run. If that first root has no usable MSH, static preview fails explicitly +rather than expanding later roots or pretending to render the entire mission. `Land.msh` использует отдельный geometry-only bridge: validated `TerrainFace28` сохраняет source triangle order, а его positions и packed UV0 попадают в тот же