Skip to content

Latest commit

 

History

History
436 lines (413 loc) · 23.9 KB

File metadata and controls

436 lines (413 loc) · 23.9 KB

Laige documentation

Documentation index and navigation (DOC-001). The engine is at M1 (heartbeat): laige-core holds the M0 foundations, and laige-sim has started (M1-ECS-01: the entity handle and world entity storage; M1-ECS-02: the component type registry; M1-ECS-03: archetype SoA component storage; M1-ECS-04: the query API + iteration legality; M1-ECS-05: the deterministic iteration contract; M1-ECS-06: the ECS guardrails G-R3/G-R4; M1-ECS-07: the ECS stress + memory accounting suite; M1-SYS-01: the system registry; M1-SYS-02: the system scheduler; M1-SYS-03: the per-system timing + budget enforcement; M1-LOOP-01: the fixed-timestep game loop core; M1-LOOP-02: the per-tick presentation snapshot + interpolation state; M1-HEAD-01: the headless engine run — Engine (config → world → systems → loop) and the laige-run binary; M1-CFG-01: the declarative game config — the version 1 config.json schema (tick rate, budgets, camera defaults, asset roots, determinism block), loadGameConfig, the programmatic override merge, and the debug-only hot reload of non-simulation keys (laige/sim/config.h); M1-DET-01: deterministic mode — the SimMath-only sim guarantee (the G-R8 compile-time trait + the CI source scan), the per-system PRNG substreams, and the seed/determinism config keys; M1-DET-02: replay recording — the versioned replay log format (replay identity per ADR 0002), the ReplayRecorder (atomic temp+rename, size-bounded), Engine::startReplayRecording, and laige-run --replay; M1-DET-03: replay execution — World::stateHash (the deterministic state hash), runReplay (the identity-checked re-run and its per-tick hash stream), and the laige-replay runner; M1-SAMPLE-01: hello.laige — the headless template game (samples/hello: one component, one system, one entity, the per-tick World::stateHash stream on stdout, record → replay through the scenario's own binary, the PRD §9.4 line budget — samples/hello/README.md); M1-DET-04: bit-exactness CI — the hello scenario's committed per-tick hash baselines (both SimMath backends), the hello --expect baseline check in every P0 OS job's ctest, the merge detcheck job's two-configuration pairs (g++ vs clang++, Debug+ASan vs Release), and the determinism report). Every section of the AGENTS §13 docs/ tree exists; each entry below links what is written and the "not yet written" section marks what is still to land.

Getting started

  • Building Laige — the source of truth for the canonical build commands, build trees, options, compiler policy (NFR-8.10), sanitizer builds (NFR-8.2), and the current M0 status. Tool commands: laige-run, laige-replay, laige-fuzz, laige-bench, laige-detcheck, the laige-api manifest target, and the include-graph lint.
  • hello.laige — the headless template game (M1-SAMPLE-01): the canonical smallest-complete Laige game — build it with the repository, run it headless, record and replay it, and learn every component/system/tick mark a Laige game uses.

Concepts

  • Concepts index — architecture, coordinates (ARCH-008), lifecycle, threading, and determinism scope. Determinism is written (M1-DET-01: the same-build scope, the two-layer G-R8 enforcement, the exception policy, the PRNG substreams); coordinates is written (M2-ISO-01: the world axes/handedness/units, the NDC conventions, the isometric projection family (ADR 0005), the depth key formula and 32-bit layout, the (key, entity id) total render order, the supported-iso-shear contract, and the sim↔render conversion rules); the other topics name their planned document and interim home.

API contracts (per public header)

  • Entity handle and world entity storage — laige::Entity (32-bit id+generation handle) and laige::World entity storage, including the M1-ECS-06 guardrails: the G-R3 entity-count thresholds (beginFrame(), guardrailStats(), ecs/entity_budget_{25,50,100}) and the G-R4 per-frame churn budget (ecs/churn_per_frame) (M1-ECS-01/06; laige-sim).
  • Component type registry — ComponentTypeId, LAIGE_COMPONENT, World::registerComponent<T> (M1-ECS-02; laige-sim).
  • Archetype SoA component storage — archetypes as ordered component sets with per-column SoA storage, World::get<T>/addComponent<T>/removeComponent<T>, the reserve policy, and the 10k-entity churn baseline (M1-ECS-03; laige-sim).
  • Query API + iteration legality — World::each<T1, T2, ...>(fn, Read/Write tags...) over the archetype rows: superset match, per-component access, the stack-scoped iteration-legality guard, and the 10k-entity zero-allocation window (M1-ECS-04; laige-sim).
  • Deterministic iteration order — the World::each visit contract: archetypes in first-seen (creation) order, entities in ascending slot id, the dense-id-order scheme under moves, no unordered containers in the iteration path, and the convergence property test (M1-ECS-05; laige-sim).
  • System registry — plain registered functions (LAIGE_SYSTEM + SystemDef) with declared time budgets (fpx16_16 ms) and declared component I/O (Io<T, Access>), World::registerSystem/system/systemCount, and SystemContext's delegated each (M1-SYS-01; laige-sim).
  • System scheduler — World::scheduleSystems/runSystems: the execution order (the registration order plus the declared depends_on edges), the pre-run validation (unknown dependency, cycle, double writer, read-before-write warn), and the per-tick system phase (M1-SYS-02; laige-sim).
  • Per-system timing and budget enforcement — the per-tick rolling time windows, the G-R5 budget enforcement (system/budget_overrun warn, system/budget_critical error), and the World::systemTimingStats/systemTimingWindow profiler feed (M1-SYS-03; laige-sim).
  • Fixed-timestep game loop core — the GameLoop accumulator loop: integer ticks at a validated 20–120 Hz rate (default 60), the exact due computation, the bounded catch-up with the loop/tick_dropped overload warn (drop, never silent), and the GameLoopStats profiler feed (M1-LOOP-01; laige-sim).
  • Presentation snapshot and interpolation state — Position2D (the first built-in component) and PresentationSnapshot: the per-tick prev/curr capture, the exact-integer anchored alpha (clamped to [0, 1], never extrapolates), and sample_position (M1-LOOP-02; laige-sim).
  • The always-on profiler — the FR-11.1 always-on counters (tick/frame time windows, entity counts, sim alloc count, draw calls / texture binds / net bytes), the cold snapshot + text/JSON reports, the GameLoop per-tick timing hook, the engine's per-run report (laige-run --prof-out), and the measured ≤1% enabled cost (M1-PROF-01; laige-sim).
  • The frame graph / budget report — the FR-11.2 per-frame budget report: every declared budget (system time, total tick time, allocation count) measured vs declared with a pass/flag, the over-budget systems list, the fixed FrameBudgetRecorder ring, the engine's opt-in cached per-run report (laige-run --budget-report, --fail-on-budget), and the zero-allocation record path (M1-PROF-02; laige-sim).
  • Headless engine run — laige::Engine (config → world → systems → loop): run_headless(maxTicks) the bounded + server run forms, the ordered idempotent CONC-006 shutdown, the backend selection at init, and the laige-run CLI (M1-HEAD-01; laige-sim + tools/run).
  • Declarative game config — the version 1 config.json schema (the required version key, tick rate, budgets, camera defaults, asset roots, the determinism block), EngineConfig, loadGameConfig, the EngineConfigOverride merge, and the debug-only ConfigHotReloader (M1-CFG-01; laige-sim).
  • Determinism-safe storage — the G-R8 compile-time trait: SimMathBackend, DeterminismConfig, detail::IsDeterminismSafe<T>, and LAIGE_DETERMINISM_SAFE(Type, MemberTypes...) (M1-DET-01; laige-sim).
  • Replay recording and execution — the versioned replay log format (replay identity: seed, tick rate, component schema hash, math backend id, config hash — ADR 0002), the ReplayRecorder (atomic temp+rename, size-bounded), the parseReplay/loadReplay readers, the identity hashes, the engine/CLI wiring (M1-DET-02), and the execution half: World::stateHash, replayIdentityDiff/runReplay, and the laige-replay runner (M1-DET-03; laige-sim).
  • Result / Status / error codes — laige::Result<T,E>, laige::Status, the stable ErrorCode registry (M0-CORE-01).
  • Structured logging — the laige::log facade, sinks, rate limiting, crash handling (M0-CORE-02; AGENTS §14).
  • SimMath deterministic math — the op surface plus the fp32_pinned and fpx16_16 backends, NaN/Inf policy, pinned-math flags (M0-CORE-03/04; ADR 0002).
  • Memory pools — ArenaPool<T> and Pool<T> with generation-checked handles and PoolStats accounting (M0-CORE-05).
  • Allocation watch — the heap-allocation counter (owner-thread attribution) behind the G-R1 zero-sim-loop-allocation guardrail: the armed-window model, the per-tick debug assertion (game_loop.md), the release fallback, and the sanitizer scope (M1-ALLOC-01).
  • Bounded JSON — laige::JsonValue, parseJson, serializeJson, JsonOptions bounds (M0-CORE-07; ADR 0003).
  • Budget harness — Histogram, TimeIt, budgetCheck, the AGENTS §12 report format, and the budgets.json schema (M0-CORE-08).
  • PRNG — laige::Prng: xorshift128+ with splitmix64 seeding, substreams, period, and the determinism contract (M0-CORE-06).
  • Determinism checker — the laige-detcheck tool and the scenario hash-line contract (<tick> <hash> lines, two build configurations) (M0-TOOL-02; activated on the hello scenario by M1-DET-04 — the baseline comparison and the CI matrix).
  • GL context — laige::render::GlContext: the OpenGL 3.3 core context contract (windowed + headless offscreen, the version gate, the capability snapshot, the offscreen FBO, the display refresh rate query), the exact per-OS headless mechanism (EGL surfaceless on Linux; never-shown GLFW window on Windows/macOS), and the clean-failure contract (M2-GL-01; ADR 0007; laige-render).
  • Frame pipeline — laige::render::RenderThread and laige::render::FrameClock: the render thread, the lock-free single-slot frame handoff (one producer, one consumer; the atomic-slot handoff argument, the backpressure drop, the exact accounting), the vsync-paced frame clock (the frame deadline grid and the render_time provider for presentation/interpolation), and the ordered idempotent shutdown (M2-GL-02; laige-render).
  • Matrix utilities — the rendering-side camera and projection matrix builders: ortho, perspective, lookAt, the 2D-plane camera planeOrtho (top_down/side_view), and the isometric family (isoMatrix/isoDimetric2To1/isoTrueIso3060, the ADR 0005 presets): the pinned conventions (right-handed world, +z up, OpenGL NDC), the element formulas, and the Performance contract (M2-GL-03; ADR 0008; laige-render).
  • Camera — laige::render::Camera: the presentation-side 3D camera core (FR-2.4): position/look-at, ortho or perspective (FOV), zoom with clamping exact at the bounds, the rectangular bounds constraint, the smooth follow (per-update lerp), the bounded decaying shake (exact-zero decay bound), the option validation and stopped state, and the Performance contract (M2-CAM-01; laige-render).
  • Isometric camera — laige::render::IsoCamera: the isometric camera (FR-2.4) on top of the M2-CAM-01 camera: the ADR 0005 preset selector (2:1 dimetric default, true 30°/60°, custom shear validated against isoShearSupported), the combined world→NDC matrix build from the M2-GL-03 preset builders, and the grid-snap camera mode (the continuous position snap to grid coordinates + the documented dyadic zoom-level ladder) (M2-CAM-02; laige-render).
  • Isometric depth keys — the engine-owned 32-bit sortable depth key for isometric render ordering: isoDepthKey<Backend>(pos, stepHeight, layer) (world-space by contract — PRD §4), isoDepthKeyParts (the exact inverse), isoDepthOrderLess (the explicit stable (key, entity id) total render order — RENDER-003), and isoShearSupported (the back-to-front shear contract; both built-in presets pass): the formula, bit layout, domain and saturation contract, the Performance contract, and the determinism/replication scope (M2-ISO-01; laige-render).
  • Isometric depth key table — the per-scene-chunk precomputed, incrementally-updated tile-grid → depth-key map: IsoDepthKeyTable<Backend> (create/rebuild/ setTile/ensureChunk + keyAt/tileHeightAt/covers), the cell model (one pre-sized CellRecord per covered cell — flat storage, one allocation at creation), the O(1) zero-allocation incremental update with its documented neighborhood (radius 0), the bounded + logged growth, the PRD §8.1 budget (10k dirty cells ≤ 0.3 ms — the iso_depthkey_rebuild entry, re-baselined 2026-10-04), and the sim-writes/render-reads threading contract (M2-ISO-02; laige-render).
  • Projection modes + screen↔world transforms — laige::render::ProjectionView: the per-scene/view projection modes (iso default, side_view, top_down, free_cinematic — FR-2.5) wrapping the M2-GL-03 / M2-CAM-01 matrices, and the FR-2.11 picking base: worldToScreen / screenToWorldRay / screenToWorld (pure, O(1), allocation-free; the documented round-trip precision and the per-mode preimage geometry; the NDC↔pixel boundary) (M2-PROJ-01; laige-render).
  • Isometric grid picking — laige::render::screenToGrid: the engine-owned safe screen → ground-plane → grid-cell inverse of the isometric projection (FR-2.11, on top of the M2-PROJ-01 transforms): the O(1) 2×2 inverse of the M2-CAM-02 camera matrix, the documented half-open cell boundary rule and precision zone (exact at all supported zoom levels), the total-function saturation contract, and the PRD §8.1 budget (one pick mean ≤ 0.01 ms — the iso_picking entry) (M2-ISO-03; laige-render).
  • Deterministic depth sort — laige::render::DepthSort: the stable, deterministic, pre-allocated sorter for the frame's 32-bit isometric depth keys (FR-2.2, RENDER-003): create (one flat 16 B/slot allocation) + sort (O(4n + 4·256), zero per-frame allocation, the stable (key, entity id) tie-break via the batcher's insertion order), 4 × 8-bit LSD radix (bucket) passes, the BudgetExhausted-when-overflowing contract, and the PRD §8.1 budget (10k keys sorted mean ≤ 1.0 ms — the depth_sort_10k entry) (M2-SORT-01; laige-render).
  • Sprite batcher — laige::render::SpriteBatcher: the engine-owned "declare, don't draw" sprite declaration window + batch builder (S-5, FR-2.1): the frame protocol (beginFrame → add × n → build), the pool-backed SpriteItem (position, depth key, UV sub-rect, rotation, scale, tint, blend, atlas/material refs), the (atlas, material, blend) grouping with deterministic group order and the M2-SORT-01 sorted instance order per group (one draw call per group at submit, M2-SPRITE-02), the bounded drop-oldest + warn overflow policy, the G-R11 counted + warned per-sprite depth override, and the zero-per-frame-allocation contract (M2-SPRITE-01; laige-render).
  • Sprite renderer — laige::render::SpriteRenderer: the frame pipeline's submit stage (M2-SPRITE-02) + render observability and the draw-call budget (M2-SPRITE-04, G-R2): the minimal GLSL 3.30 sprite shader (world position, UV sub-rect, rotation, scale, tint; one atlas texture) and the GPU instanced draw — ONE glDrawArraysInstanced per (atlas, material, blend) group per frame, the per-frame / since-construction counters (draw calls, texture binds, blend changes, program changes, instances, primitives, upload volume, render-target use, the G-R2 draw-call-cap flag) as the M2-PROF-01 profiler feed, the configurable per-pass draw-call cap (default 64; over-cap warns + flags, never gates), the textureMemoryBytes() VRAM estimate, the pre-allocated instance buffer (zero per-frame allocation), and the offscreen 1 000-sprite render verified against a CPU reference.
  • Sprite frames — laige::render::SpriteFrameLayout + spriteFrameUv: the atlas UV frame animation hook (M2-SPRITE-03; FR-2.1 "atlas UV animation (sheet frames)"): the sheet frame layout (frame size, row/col, margins) and the pure frame-index → UV sub-rect computation (out-of-range frame → documented error, never wrap) the caller uses to fill SpriteItem.uv/frameIndex — the data-driven hook M3 animation drives.
  • Tilemap — laige::render::TileMap<Backend>: the chunked tile grid data (per tile: texture id, depth/height, animation id — 0 = static, 1..maxAnimations = the animation slot), the auto-depth wiring of the M2-ISO-02 depth key table (a tile's Y height is automatically reflected in its depth key), the tile-quad batch path into the sprite batcher (tiles are sprites — one tilemap renders in a bounded number of draw calls, one per (texture, material, blend) group), the data-driven tile animation frame cycle (per-tile frame cycling at the animation's documented sim-tick rate — setAnimation + advanceAnimations; M2-TILE-02), and the parallax tile layer declaration (a Tilemap-source parallax layer declares the tilemap's quads translated by its worldOffset; M2-TILE-02, the M2-PAR-01 hook) (M2-TILE-01/02; FR-2.6).
  • Parallax layers — laige::render::ParallaxLayers<Backend>: the named background/midground/foreground layer model (M2-PAR-01; FR-2.3): the parallax factor (0..1), the EXACT world-space offset formula factor * (p - center) + offset, the UV scroll (auto or manual) with the exact wrap at the texture boundary (rendered through the 2 x 2 wrap split into the sprite batcher), the documented background-first render order (the depth-key layer values: background -2, midground -1, ground 0, foreground +1), and the Tilemap source (the M2-TILE-02 hook — the tiles are declared through the tilemap's declareTo overload, not this registry's).
  • Particle simulation — laige::ParticleSystem<Backend>: the CPU-simulated, budgeted, pooled particle half of FR-2.7 (M2-PART-01): the bounded pre-allocated pool (drop-on-overflow, one rate-limited warn per tick), burst + continuous emitters, per-particle 2D position + constant depth + velocity + life + size, the exact integer color fade, the once-per-sim-tick update() (ARCH-002), and the fixed-seed determinism contract (the 4-draw Prng contract, the machine-greppable state hash). The render half (particles as batched sprites) lands in M2-PART-02.

Guides

  • Guides index — task-oriented usage and optimization guides. None yet: they land with their milestones (first headless project and determinism/replay in M1, profiling in M1, rendering in M2, MMO server setup in M6/M7).

Debugging

  • Debugging index — what is usable today (structured logging, the budget harness, laige-detcheck, sanitizer builds, test seeds). The in-engine debug mode (AGENTS §15) lands with the profiling work (M1-PROF-01, M2-PROF-01).

Benchmarks

  • Benchmarks index — methodology, baselines, results, and the regression policy.
  • Benchmark methodology — the AGENTS §12 report fields, the budgets.json field mapping, the baseline-file convention, and the PRD §8.1 regression policy (M0-DOC-01).
  • Baselines — recorded baseline reports (m0-synthetic.md, M0-EXIT-01, and m1-ecs-stress.md, M1-ECS-07; every budgets.json entry still has measured: 0).
  • Determinism matrix — the M1-DET-04 determinism report: the committed per-tick hash baselines of the hello scenario (both SimMath backends), the CI matrix (every P0 OS job's baseline check + the merge detcheck job's cross-compiler / sanitizer / Release pairs), and the ARCH-010 scope statement.

Architecture decisions (ADRs)

  • ADR index — 0001 (name and license), 0002 (deterministic math), 0003 (config JSON), 0004 (GoogleTest vendoring), 0005 (iso default: 2:1 dimetric), 0006 (UI widget scope: the seven FR-2.8 widgets).

Compatibility

  • Compatibility — P0 platforms and compilers (PRD §6; the CI matrix), the current machine-readable formats (budgets.json, laige-api.json, deps.lock, and the version 1 replay log format, M1-DET-02), and the migration-guide status (none yet — pre-1.0, no breaking changes).

Testing

  • Testing conventions — test layout (module dirs mirror src/, <module>_tests executables), the regress_<short-id> regression-test convention, laige-fuzz target registration and CI lane semantics, and the seed-handling convention for randomized tests (M0-TEST-01).

Not yet written (honest status)

Related

  • Roadmap index — the M0/M1/… step plan, progress board, and change log; M0 foundations is the current milestone.
  • AGENTS.md — the engineering contract this documentation implements.
  • PRD.md — the product requirements.