Server-Side Rendering: Vulkan + CUDA Interop + NVENC → WebSocket → WebCodecs → Canvas
| Protokoll | WebSocket über TCP/TLS (:443) |
| Pfad | Browser → CloudFront → ALB → Node.js :3000 → render-service :8081 |
| Video | WS binary (1-byte type + H.264 NALUs) → WebCodecs VideoDecoder → Canvas |
| Input | WebSocket JSON (/ws/input) |
| Latenz (typisch) | ~50 ms (encode ~3ms + TCP + decode ~10ms) |
| Firewall | Nur HTTPS/443 — funktioniert in allen Corporate Networks |
| Prisma-Compliance | Ja — Private Subnets, keine public IPs |
ws-{timestamp}-{random}/ws/render?sessionId=X für Video-Frames/ws/input?sessionId=X für Input-CommandsMAX_SESSIONS = 4 (env-überschreibbar bis 64).Content-Length aus dem Header gelesen — über das Ende eines 64 KiB-Stack-Arrays hinaus (reproduziert: Exit 139). Zusätzlich warf std::stoi ungefangen in einem detached Thread (Exit 134). Jetzt auf die real empfangenen Bytes geklemmt, std::stol in try/catch, Catch-all im Thread. Der Health-Check pollt dauerhaft — deshalb trat es nur bei langen Ladevorgängen auf.backtrace_symbols_fd) für SIGSEGV/SIGABRT/SIGBUS/SIGFPE, dauerhaft installiert — hat den Fehler oben gefunden. Build mit -g -fno-omit-frame-pointer -rdynamic, Binary wird nicht gestrippt.ActiveSessions ist nur Dashboard-Metrik, an keine Scaling-Policy gebunden.catparts/ — auf Anfrage (on-demand) oder Bulk-Pipelinevq3d/ cached — kompaktes Binary (Vertices, Normals, Indices, BVH, Part-IDs, Face-IDs)| Maßnahme | Status | Implementierung |
|---|---|---|
| Import/Render getrennt Render-Worker lädt nur .vq3d, nie CATPart |
Aktiv | Ingest-Pipeline → S3 → vq3d_loader.cpp |
| Mesh-Cache (S3 + SSD) SHA-basiert, 2. Aufruf < 500ms |
Aktiv | s3-loader.ts (ETag), asset_cache.cpp (LRU) |
| BVH + Frustum/Occlusion Culling SAH-BVH, nur sichtbare Draw-Calls |
Aktiv | bvh-builder.ts (offline), bvh_culler.cpp (runtime) |
| GPU-freundliches Binary Interleaved Pos+Normal+PartID, zero-copy upload |
Aktiv | .vq3d Format, vq3d_loader.cpp |
| CUDA Interop Zero-Copy Encoding Vulkan→CUDA→NVENC ohne CPU-Roundtrip, ~3ms/frame @ 50fps |
Aktiv | cuda_interop.cpp + nvenc_encoder.cpp |
| Variable FPS (wake-on-input) Idle: kein Rendern. Input → sofort 60fps |
Aktiv | session.cpp (condition variable) |
| GPU Picking Part-ID + Face-ID Render Buffer, <5ms |
Aktiv | pick_buffer.cpp |
| Persistent GPU Workers Warme GPU, kompilierte Shader, kein Cold-Start |
Aktiv | ECS EC2 GPU Tasks (langlebig) |
| WebSocket Transport ~50ms Latenz, Prisma-konform (private Subnets) |
Aktiv | ws_transport.cpp + WebCodecs (Browser) |
| On-demand Konvertierung Kein Vorverarbeiten nötig — Part wird bei erstem Zugriff konvertiert + gecacht |
Aktiv | resolveVq3d() → CatPartReader → S3 |
| Auto-Connect + Reconnect Viewer verbindet automatisch, kein manueller Button |
Aktiv | viewer.html (WebSocket, 3s Retry) |
| Freie Orbit-Rotation Keine vertikale Begrenzung, Up-Vektor flippt an Polen |
Aktiv | session.cpp (processOrbit) |
| meshoptimizer Vertex-Cache, Overdraw, Fetch-Optimierung |
Geplant | In Pipeline nach Tessellierung |
| Dynamische Deflection BBox-abhängig statt konstant → 50-80% weniger Polygone |
Geplant | OCCT BRepMesh parameter |
| Progressive LOD Grobes Mesh sofort, verfeinern im Hintergrund |
Geplant | Multi-LOD im .vq3d Format |
| GPU Instancing Identische Parts (Schrauben etc.) nur 1x uploaden |
Geplant | Part-Hash → Instance-Gruppen |
| Fahrzeug laden | < 3s |
| Kamera-Interaktion | < 50ms |
| Picking | < 5ms |
| Frame-Rate | 60 fps |