16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-22 00:09:18 +02:00

Add headless parallel eu7v2 scenario bake with streaming and PLCE placements

Enable --eu7v2-bake from the main binary: parallel module pool, bounded-RAM
spool flush, streaming terrain triangles, flat include/model parsing, and
eu7v2 emit/load with optional verify. Large placement .scm files emit lean
PLCE records and bake referenced .inc modules separately for reuse.

- CLI: --eu7v2-bake, --eu7v2-verify, --eu7v2-mem-limit-gb, --eu7v2-threads,
  --eu7v2-max-parse; wire max_threads through to the bake parser
- eu7v2 v2 records: PLCE placements, runtime emitter/loader, batch verify
- Parallel bake pool with session cache; drop heavy-serial parse gate in spool
  mode; parse concurrency matches thread count
- Streaming terrain: batched parallel parse+bake, scan/bake pipeline, shape
  spool with persistent buffered I/O and flush-before-read
- Parallel flat-file streaming for models/includes; pack/model spool for
  low-memory incremental flush
- Optional 50 GB private-bytes guard during headless bake

Braniewo_szeroki: 160 modules, verify PASS, ~34s bake (nmt100 ~17s vs ~190s
serial baseline).

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
maj00r
2026-06-17 21:15:36 +02:00
parent 9574d2051b
commit beacc00932
40 changed files with 9327 additions and 193 deletions

381
docs/eu7v2-format.md Normal file
View File

@@ -0,0 +1,381 @@
# Format pliku EU7v2 (`.eu7v2`)
> Dokumentacja oparta na kodzie źródłowym z:
> - `scene/eu7/v2/` — format, emitter, loader, testy roundtrip
> - `scene/eu7/eu7_bake_parser.cpp` — headless bake scenariusza
> - `eu07-parser/include/eu07/scene/bake/` — pool bake, streaming terenu
>
> Stan: **czerwiec 2026**, wersja kontenera **v1** (`kVersion = 1`).
---
## Spis treści
1. [Przegląd ogólny](#1-przegląd-ogólny)
2. [Nagłówek pliku](#2-nagłówek-pliku)
3. [Struktura chunku](#3-struktura-chunku)
4. [Rodzaje pliku (`file_kind`)](#4-rodzaje-pliku-file_kind)
5. [Katalog chunków](#5-katalog-chunków)
6. [Typy podstawowe](#6-typy-podstawowe)
7. [STRS — tablica łańcuchów](#7-strs--tablica-łańcuchów)
8. [META — metadane modułu](#8-meta--metadane-modułu)
9. [INCL — include rekurencyjne](#9-incl--include-rekurencyjne)
10. [PLCE — placementy modułów wielokrotnego użytku](#10-plce--placementy-modułów-wielokrotnego-użytku)
11. [PROT + INST — prototypy i instancje modeli](#11-prot--inst--prototypy-i-instancje-modeli)
12. [SHPE — kształty (triangles)](#12-shpe--kształty-triangles)
13. [MESH — teren (tile)](#13-mesh--teren-tile)
14. [LINE — linie](#14-line--linie)
15. [Rekordy symulacji](#15-rekordy-symulacji)
16. [Bake headless i drzewo modułów](#16-bake-headless-i-drzewo-modułów)
17. [Ścieżki plików](#17-ścieżki-plików)
---
## 1. Przegląd ogólny
Plik `.eu7v2` to binarny format skompilowanego modułu scenerii:
- **Moduły wielokrotnego użytku** — osobny plik `.eu7v2` per `.inc` / `.scm`, placementy jako lean **PLCE**
- **Prototypy + instancje** — chunk **PROT** (deduplikacja meshów) + **INST** (transformacja w world-space)
- **Chunki pomijalne** — nieznany FourCC można pominąć po polu `size`
- **Little-endian** — deterministyczny zapis niezależny od endianness hosta
- **Centralna tablica STRS** — wszystkie stringi przez `string_id` (`uint32`)
Magic pliku: **`EU7C`** (FourCC `'E','U','7','C'`).
---
## 2. Nagłówek pliku
```
Offset Rozmiar Typ Opis
------ ------- -------- -------------------------
0 4 uint32 Magic = 'EU7C'
4 2 uint16 Version (= 1)
6 2 uint16 file_kind (patrz sekcja 4)
8 4 uint32 Reserved (= 0)
12 4 uint32 Reserved (= 0)
16 ... chunks Strumień chunkowy (do EOF)
```
Nagłówek ma **16 bajtów**. Brak pola „rozmiar całego pliku”.
---
## 3. Struktura chunku
```
Offset Rozmiar Typ Opis
------ ------- ------- -----------------------------------------
0 4 uint32 Chunk ID — FourCC little-endian
4 8 uint64 Payload size (tylko payload, BEZ nagłówka chunku)
12 ... bytes Payload
```
Pole `size` to rozmiar **samego payloadu** (`uint64`), bez nagłówka chunku.
Chunki są sekwencyjne do EOF. Nieznany chunk: `seek(payload_size)`.
FourCC — bajty w pliku w kolejności ASCII (np. `STRS``53 54 52 53`).
---
## 4. Rodzaje pliku (`file_kind`)
| Wartość | Nazwa | Typowy źródłowy plik | Opis |
|---------|------------|-----------------------------|-------------------------------------------|
| `1` | `sim` | `.scn`, `.scm`, `.sbt`, `.ctr` | Moduł scenariusza / root |
| `2` | `module` | `.inc` | Moduł wielokrotnego użytku (trawa, drzewo…) |
| `3` | `tile` | (planowane) | Kafel 1 km — teren + instancje |
| `4` | `manifest` | (planowane) | Indeks kafli / modułów mapy |
Emitter runtime (`eu7v2_emit_runtime.cpp`) ustawia:
- `.inc``file_kind::module`
- pozostałe rozszerzenia modułów → `file_kind::sim`
Loader akceptuje `sim` i `module` (`eu7v2_load.cpp`).
---
## 5. Katalog chunków
| FourCC | Stała C++ | Typ pliku | Opis |
|---------|---------------|-------------|---------------------------------------------------|
| `STRS` | `chunk::strs` | wszystkie | Tablica stringów (zawsze pierwszy logicznie) |
| `META` | `chunk::meta` | sim/module | Metadane modułu (first-init, placement params) |
| `INCL` | `chunk::incl` | sim/module | Include rekurencyjne (submoduły `.eu7v2`) |
| `PLCE` | `chunk::plce` | sim/module | Lean placementy → osobne moduły `.eu7v2` |
| `PROT` | `chunk::prot` | sim/module/tile | Prototypy modeli (mesh bez transformacji) |
| `INST` | `chunk::inst` | sim/module/tile | Instancje modeli (proto + transform) |
| `MESH` | `chunk::mesh` | tile/sim | Teren — mesh z origin f64 + wierzchołki f32 |
| `SHPE` | `chunk::shpe` | sim/module | Kształty triangles/strip/fan (nie-teren) |
| `LINE` | `chunk::line` | sim/module | Geometria linii |
| `TRAK` | `chunk::trak` | sim | Tory |
| `TRAC` | `chunk::trac` | sim | Przewody trakcyjne |
| `PWRS` | `chunk::pwrs` | sim | Źródła zasilania |
| `MEMC` | `chunk::memc` | sim | Komórki pamięci |
| `LAUN` | `chunk::laun` | sim | Wyzwalacze zdarzeń |
| `EVNT` | `chunk::evnt` | sim | Zdarzenia |
| `SOND` | `chunk::sond` | sim | Dźwięki |
| `DYNM` | `chunk::dynm` | sim | Pojazdy dynamiczne |
| `TRST` | `chunk::trst` | sim/module | Zestawy wagonowe |
| `TRGR` | `chunk::trgr` | sim | Precomputed track graph (planowane) |
| `SIDX` | `chunk::sidx` | manifest | Indeks sekcji przestrzennej (planowane) |
Chunki o zerowej liczności (pusta tablica) **nie są zapisywane** przez emitter.
---
## 6. Typy podstawowe
| Typ w pliku | Rozmiar | Opis |
|-------------|---------|---------------------------------------------------|
| `uint8` | 1 B | Bajt bez znaku |
| `uint16` | 2 B | LE |
| `uint32` | 4 B | LE |
| `uint64` | 8 B | LE |
| `int32` | 4 B | LE, ze znakiem |
| `float32` | 4 B | IEEE 754 |
| `float64` | 8 B | IEEE 754 — pozycje world-space, originy mesh |
| `string_id` | 4 B | Indeks STRS; `0xFFFFFFFF` = brak (`kNoString`) |
Współrzędne instancji modeli i placementów: **float64** (x/y/z).
Wierzchołki mesh/shape: **float32** względem origin (f64).
---
## 7. STRS — tablica łańcuchów
```
uint32 count
Powtórzone count razy:
uint32 length
char[] data (length bajtów, bez null-terminatora)
```
Indeks `0xFFFFFFFF` (`kNoString`) oznacza brak stringu.
---
## 8. META — metadane modułu
Layout wersjonowany (pole `layout_version`):
```
uint32 layout_version (= 1)
uint32 first_init_count
uint8 has_terrain_chunk (informacyjne)
uint8 has_pack_chunk (informacyjne)
uint8 placement_origin_x (numer parametru include, 0 = brak)
uint8 placement_origin_y
uint8 placement_origin_z
uint8 placement_rotation_y
```
---
## 9. INCL — include rekurencyjne
Submoduły wczytywane rekurencyjnie (np. zagnieżdżone `.scm`, tory, CTR):
```
uint32 count
Powtórzone count razy:
uint32 source_line
string_id source_path (.scm/.inc tekstowy)
string_id binary_path (.eu7v2)
uint32 param_count
string_id[] parameters
TransformRecord site_transform:
uint32 origin_stack_count
dvec3[] origin_stack
uint32 scale_stack_count
dvec3[] scale_stack
dvec3 rotation (stopnie, XYZ)
uint32 group_depth
```
---
## 10. PLCE — placementy modułów wielokrotnego użytku
Pliki placement (flora, dekoracje) emitują lean rekordy wskazujące na **osobny** moduł `.eu7v2`:
```
uint32 count
Powtórzone count razy:
string_id module_path (np. scenery/grass_l61/20.eu7v2)
string_id texture_override (kNoString jeśli brak)
float64 x, y, z (world-space)
float32 rotation_y (stopnie)
uint8 cell_id (0xFF = brak)
```
**Bake:** unikalne `.inc` z placement file są bake'owane jako osobne moduły `file_kind::module`.
**Runtime:** loader syntetyzuje include z PLCE (ładuje wskazany moduł z transformacją).
Typowy rozmiar: **~37 B / placement**.
Przykład: `204_trawky_ter.scm` (110k linii include) → `.eu7v2` ~4 MB (PLCE) + osobne `grass_l61/20.eu7v2` per unikalny `.inc`.
---
## 11. PROT + INST — prototypy i instancje modeli
### PROT — prototyp
```
uint32 count
Powtórzone count razy:
string_id model_file
string_id texture_file
uint8 flags (bit 0=transition, 1=is_terrain, 2=instanceable)
float32 range_min
float32 range_max
uint32 light_state_count
float32[] light_states
uint32 light_color_count
uint32[] light_colors
```
### INST — instancja
```
uint32 count
Powtórzone count razy:
uint8 flags (bit 0=has_scale, 1=texture_override, 2=has_node)
uint32 proto (indeks PROT)
float64 x, y, z
float32 ax, ay, az (kąty Eulera, stopnie)
uint8 cell_id
[flags & 1]: float32 sx, sy, sz
[flags & 2]: string_id texture_override
[flags & 4]: node_record
```
Root scenariusza: modele z PACK bake są deduplikowane do PROT+INST (flattened world-space).
---
## 12. SHPE — kształty (triangles)
```
uint32 count
Powtórzone count razy:
node_record node
uint8 translucent
string_id material
lighting_block (12 × float32: diffuse/ambient/specular RGBA)
float64 ox, oy, oz (origin world-space)
uint32 vertex_count
Powtórzone vertex_count razy:
float32 px, py, pz (względem origin)
float32 nx, ny, nz
float32 u, v
```
Typ węzła (`node.type`) niesie subtype: `triangles`, `triangle_strip`, `triangle_fan`.
Duże pliki terenu (same `node … triangles`) mogą być streamowane przy bake; shapes trafiają do **shape spool** na dysku, potem do chunku SHPE przy emit.
---
## 13. MESH — teren (tile)
Format terenu dla kafli 1 km (origin f64 + relative f32):
```
uint32 count
Powtórzone count razy:
string_id material
uint8 translucent
float64 ox, oy, oz
uint32 vertex_count
Powtórzone vertex_count razy:
float32 px, py, pz, nx, ny, nz, u, v
```
---
## 14. LINE — linie
```
uint32 count
Powtórzone count razy:
node_record
lighting_block
float32 line_width
float64 ox, oy, oz
uint32 vertex_count
dvec3[] vertices (float64 × 3)
```
---
## 15. Rekordy symulacji
Chunki symulacji: `TRAK`, `TRAC`, `PWRS`, `MEMC`, `LAUN`, `EVNT`, `SOND`, `DYNM`, `TRST`.
Wspólny nagłówek węzła: **`node_record`**. Stringi przez STRS. Pozycje torów/krzywych Béziera: **float64**.
Szczegóły pól: `scene/eu7/v2/eu7v2_records.h` (funkcje `write_*` / `read_*`).
---
## 16. Bake headless i drzewo modułów
CLI (binarny `eu07`, bez GUI):
```
eu07.exe --eu7v2-bake <sciezka.scn|.inc> [opcje]
```
| Opcja | Opis |
|--------------------------|---------------------------------------------------|
| `--eu7v2-verify` | Roundtrip: przeładuj `.eu7v2`, porównaj liczności rekordów |
| `--eu7v2-mem-limit-gb N` | Limit pamięci procesu (domyślnie 50 GB); włącza tryb spool |
| `--eu7v2-threads N` | Wątki pool bake (0 = auto = liczba rdzeni) |
| `--eu7v2-max-parse N` | Równoległe parse (0 = auto) |
| `--eu7v2-heavy-parse-mb N` | Próg serial parse dużych plików (0 = wyłączony w trybie spool) |
**Przepływ bake scenariusza:**
1. Root `.scn` → enqueue drzewa modułów (dedup po ścieżce kanonicznej)
2. Pool workerów bake'uje moduły równolegle
3. Każdy `.scm`/`.inc` → osobny `.eu7v2` obok źródła tekstowego
4. Placement `.scm`**PLCE** + enqueue unikalnych `.inc` jako `module`
5. Root emit na końcu (PACK → PROT+INST, includes z podmodułów)
6. Opcjonalnie verify batch wszystkich modułów
Implementacja: `scene/eu7/eu7_bake_parser.cpp`, `eu07-parser/.../bake_tree.hpp`.
---
## 17. Ścieżki plików
```cpp
binary_path_from_text("scenery/foo/bar.scm") scenery/foo/bar.eu7v2
binary_path_from_text("scenery/grass_l61/20.inc") scenery/grass_l61/20.eu7v2
binary_path_from_text("scenery/foo/base.ctr") scenery/foo/base.ctr.eu7v2
```
Rozszerzenia `.scm`, `.scn`, `.sbt`, `.inc``<stem>.eu7v2`.
Inne (np. `.ctr`) → `<nazwa_pliku>.eu7v2` (bez utraty suffixu).
---
## Pliki implementacji
| Temat | Plik |
|--------------------|---------------------------------------------------|
| Format core | `scene/eu7/v2/eu7v2_format.h` |
| Scene payloads | `scene/eu7/v2/eu7v2_scene.h` |
| Sim records | `scene/eu7/v2/eu7v2_records.h` |
| Emit RuntimeModule | `scene/eu7/v2/eu7v2_emit_runtime.cpp` |
| Load runtime | `scene/eu7/v2/eu7v2_load.cpp` |
| Test roundtrip | `scene/eu7/v2/eu7v2_test.cpp` |
| Headless bake | `scene/eu7/eu7_bake_parser.cpp` |
| Bake pool | `eu07-parser/include/eu07/scene/bake/bake_tree.hpp` |
---
*Dokumentacja na podstawie kodu; stan na 17 czerwca 2026.*