Repository navigation
Architecture
MasterLaplace edited this page Jul 14, 2026
·
10 revisions
LplPlugin/
├── xmake.lua # Root orchestrator
├── core/ # lpl-core: Platform types, assertions, logging
├── math/ # lpl-math: Vec3, Quat, Fixed32, CORDIC
├── memory/ # lpl-memory: PinnedAllocator, pools
├── concurrency/ # lpl-concurrency: ThreadPool, SpinLock
├── container/ # lpl-container: FlatAtomicsHashMap, Morton
├── gpu/ # lpl-gpu: CUDA lifecycle, physics kernels
├── ecs/ # lpl-ecs: EntityRegistry, Partition (SoA chunks)
├── physics/ # lpl-physics: WorldPartition, collision, octree
├── net/ # lpl-net: transport, protocol, session, netcode
├── input/ # lpl-input: InputManager (keys, axes, neural)
├── platform/ # lpl-platform: HW backends (clock/display/gpu/input)
├── render/ # lpl-render: software + Vulkan renderer, ImGui
├── shaders/ # lpl-shaders: shader sources for the renderer
├── image/ # lpl-image: 2D software imaging (Surface, Painter, Codec)
├── scene/ # lpl-scene: scene graph (Scene, Transform2D)
├── audio/ # lpl-audio: Spatial audio (stub)
├── haptic/ # lpl-haptic: Haptic/vestibular (stub)
├── bci/ # lpl-bci: OpenBCI, FFT, DSP, metrics, calibration
├── serial/ # lpl-serial: state serialization & deterministic replay
├── bench/ # lpl-bench: benchmark harness (Harness, SystemInfo)
├── engine/ # lpl-engine: Facade aggregating all modules
├── kernel/ # lpl_kmod.c (Netfilter + ring buffers)
├── apps/ # lpl-server, lpl-client, lpl-benchmark
└── samples/ # example codelpl-engine (facade — depends on every module; lpl-render only when --renderer is on)
├── lpl-core
├── lpl-math # lpl-core
├── lpl-memory # lpl-core
├── lpl-concurrency # lpl-core
├── lpl-container # lpl-core, lpl-memory, lpl-concurrency
├── lpl-gpu # lpl-core, lpl-math, lpl-memory
├── lpl-ecs # lpl-core, lpl-math, lpl-memory, lpl-container, lpl-concurrency, lpl-gpu
├── lpl-physics # lpl-core, lpl-math, lpl-memory, lpl-container, lpl-ecs (+lpl-gpu)
├── lpl-net # lpl-core, lpl-math, lpl-memory, lpl-container, lpl-concurrency, lpl-ecs
├── lpl-input # lpl-core, lpl-math
├── lpl-platform # lpl-core
├── lpl-render # lpl-shaders, lpl-core, lpl-math, lpl-memory (+ Vulkan, ImGui, glm, stb, tinyobjloader)
├── lpl-image # lpl-core
├── lpl-scene # lpl-core, lpl-math
├── lpl-audio # lpl-core, lpl-math
├── lpl-haptic # lpl-core, lpl-math
├── lpl-bci # lpl-core, lpl-math, lpl-input, lpl-container (+ eigen, liblsl, brainflow)
├── lpl-serial # lpl-core, lpl-math, lpl-ecs, lpl-net, lpl-input
└── lpl-bench # lpl-core
Apps:
├── lpl-server # lpl-engine
├── lpl-client # lpl-engine
└── lpl-benchmark # lpl-bench + lpl-core, lpl-math, lpl-memory, lpl-container, lpl-concurrency, lpl-ecs, lpl-physics[OpenBCI Cyton — 8 ch / 250 Hz]
↓ USB serial — 33-byte packets
bci/src/source/ → OpenBCIDriver → BciRingBuffer (lock-free)
↓
bci/src/dsp/ — FFT per channel (Hann window, 256 pts) → PSD[8][128 bins]
↓
┌─────────────────────────────────────────────────────┐
│ SignalMetrics::schumacher() → R(t) 40-70 Hz │ muscle tension
│ RiemannianGeometry::riemannian_distance() → δ_R │ cognitive state
│ RiemannianGeometry::mahalanobis_distance() → D_M │ anomaly detection
└─────────────────────────────────────────────────────┘
↓
NeuralMetrics::from_state() → { muscle_tension, stability, concentration }
↓
input/ InputManager → ECS ComponentID::NEURAL → SystemScheduler → WorldPartition
The engine/ module provides the top-level Core class. It is the single entry point and owns all sub-systems by composition.
┌─────────────────── Core ───────────────────────┐
│ │
│ WorldPartition _world (chunks, ECS) │
│ Network _network (transport UDP) │
│ SystemScheduler _scheduler (DAG PreSwap/ │
│ PostSwap) │
│ InputManager _inputManager (keys/axes/neural│
│ par entité) │
│ PacketQueue _packetQueue (queues typées) │
│ SessionManager _sessionManager (serveur) │
│ │
│ run(threaded) → boucle fixe 60Hz (serveur)│
│ runVariableDt(...)→ boucle variable (client) │
│ initClientNetwork()→ connect au serveur │
│ registerSystem() → ajoute un SystemDescriptor │
│ buildSchedule() → compile le DAG │
│ │
└─────────────────────────────────────────────────┘
Chaque frame suit le pipeline PreSwap → swapBuffers → PostSwap :
1. PreSwap Systems (mutation du write buffer)
├─ NetworkReceive : socket/ring → PacketQueue
├─ Session : ConnectEvent → créer entité + MSG_WELCOME (serveur)
├─ InputProcessing : InputEvent → InputManager (serveur)
├─ Welcome : WelcomeEvent → myEntityId (client)
├─ StateReconciliation : StateUpdateEvent → monde local (client)
├─ BCI / LocalInput : source BCI + input → InputManager (client)
├─ Movement : InputManager → vélocité (partagé srv/cli)
└─ Physics : world.step(dt)
2. swapBuffers() — copie hot write→read, toggle writeIdx
3. PostSwap Systems (lecture du read buffer stable)
├─ Broadcast : sérialise + envoie MSG_STATE (serveur)
├─ Camera : suivi de l'entité locale (client)
└─ Render : Vulkan draw (client)
┌───────────── RX PATH (inbound) ─────────────┐
│ │
UDP Packet (port 7777)
↓
Netfilter Hook (kernel/lpl_kmod.c — NF_INET_PRE_ROUTING)
↓
RxRingBuffer (mmap'd LplSharedMemory, atomic head/tail)
↓
net/ Network::network_consume_packets() → dispatch to PacketQueue (typed events)
↓
Systems ECS (drain queues) → mutate WorldPartition (write buffer)
↓
physics/ WorldPartition::step()
├─ GPU path: CUDA kernel (PhysicsKernel.cu)
└─ CPU path: physicsTick (current)
↓
Inter-chunk migration (backward iteration + swap-and-pop, both buffers)
↓
swapBuffers() (copy hot write→read, atomic toggle writeIdx)
│ │
└───────────── TX PATH (outbound) ─────────────┘
│ │
SessionManager::broadcast_state() → write TxPackets to TxRingBuffer
↓
ioctl(LPL_IOC_KICK_TX) → wake kernel TX thread
↓
lpl_tx_worker (kernel thread) → kernel_sendmsg() → UDP to clients
Each chunk (1000×∞×1000 units) is a self-contained Partition in ecs/:
┌─────────────────────────────────────────────────┐
│ Partition (Chunk) │
├─────────────────────────────────────────────────┤
│ HOT DATA (double-buffered, PinnedAllocator) │
│ ├─ positions[2] : Vec3[] (write/read) │
│ ├─ velocities[2] : Vec3[] (write/read) │
│ └─ forces[2] : Vec3[] (write/read) │
├─────────────────────────────────────────────────┤
│ COLD DATA (single buffer, PinnedAllocator) │
│ ├─ ids : uint32_t[] │
│ ├─ rotations : Quat[] │
│ ├─ masses : float[] │
│ ├─ sizes : Vec3[] │
│ ├─ health : int32_t[] │
│ └─ neuralControls : NeuralControl[] │
├─────────────────────────────────────────────────┤
│ METADATA │
│ ├─ _idToLocal : adaptive sparse set (O(1))│
│ ├─ _bound : BoundaryBox │
│ ├─ _locker : SpinLock │
│ └─ _octree : FlatDynamicOctree │
└─────────────────────────────────────────────────┘
Double buffering enables concurrent lock-free reads (reader↔writer):
-
Writers (physics, network) write to
buf[writeIdx] -
Readers (rendering, broadcast) read from
buf[writeIdx ^ 1](stable snapshot) -
swapBuffers()copies the write buffer to the read buffer then toggleswriteIdx - The
SpinLockonly protects structural mutations (writer↔writer):addEntity,removeEntityById,physicsTickthat modify vector sizes
┌──────────────────┐ UDP 7777 ┌────────────────────────┐
│ Client │ ────── MSG_CONNECT ─────→ │ Server (Core) │
│ (lpl-client) │ ───── MSG_INPUTS ───────→ │ │
│ │ ←───── MSG_WELCOME ────── │ ┌─ net/ │
│ PreSwap: │ ←───── MSG_STATE ──────── │ ├─ input/ │
│ ├ NetworkRecv │ │ ├─ ecs/ │
│ ├ Welcome │ /dev/lpl0 │ └─ engine/ │
│ ├ StateRecon │ ──── (mmap shared mem) ── │ │
│ ├ BCI+LocalInput│ │ PreSwap: │
│ ├ Movement │ │ ├ NetworkRecv │
│ └ Physics │ │ ├ Session │
│ │ │ ├ InputProcessing │
│ PostSwap: │ │ ├ Movement │
│ ├ Camera │ │ └ Physics │
│ └ Render (Vk) │ │ │
│ │ │ PostSwap: │
│ │ │ ├ Broadcast │
│ │ │ └ ServerMonitor │
└──────────────────┘ └────────────────────────┘
| Message | Format | Description |
|---|---|---|
MSG_CONNECT (0x10) |
[1B type] |
Client connection → player entity creation |
MSG_WELCOME (0x11) |
[1B type][4B entityId] |
Server response with assigned ID |
MSG_INPUTS (0x12) |
[1B type][4B entityId][KeyCount+Keys][AxisCount+Axes][optional 13B neural] |
Unified input packet (keys, axes, optional neural) |
MSG_STATE (0x13) |
[1B type][2B count][{4B id, 12B pos, 12B size, 4B hp}×N] |
World state broadcast |
← Philosophy & Principles | Next: Tech Stack & Build →
LplPlugin — Zero-Copy Real-Time VR Engine | Author: MasterLaplace | License: GPL-3.0 | Source Code
This project is a marathon, not a sprint.