4.6 KiB
type, title, description, tags, actor, sources, generated, verified, status, stale_after
| type | title | description | tags | actor | sources | generated | verified | status | stale_after | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Technical Specification | Frame Loop Architecture | Technical specification for the frame loop architecture in wsg_lib, detailing the immutable frame lifetime cycle and resource management |
|
person/jerome |
|
true | current | 2027-01-31 |
La Boucle de Rendu (Frame Loop)
État du document : ACTUEL (implémenté). Ce document décrit la frame lifetime telle qu'elle est réellement implémentée. Deux flux coexistent : le flux facade
App(rendu automatique de la scène,App::render_scene— le workflow recommandé, exemplessimple/cube/demo) et le flux manuel (Context/Renderer/Framepilotés à la main — exemplemanual, un objet par soumission). Le pipeline GPU-driven (compute pass + draw indirect) de l'état visé est décrit dans ARCHI_APP / ARCHI_CPU_GPU (cible).
Pour afficher quelque chose, nous suivons un cycle immuable appelé la Frame Lifetime, basé sur Frame :
Flux facade App (recommandé — App::run + AppHandler) :
Context::get_next_frame(): acquiert la surface texture et crée saTextureView(dansFrame).AppHandler::render(défaut) →App::render_scene(view): le moteur itère les entités de la scène et les dessine en une passe groupée (unCommandEncoder+ une soumission par frame ; passe d'ombre en tête si un caster est actif).Renderer::present(frame): présente l'image à l'écran.- Chaque frame, avant
update, le moteur appelledevice.poll()(les callbacks asynchrones wgpu —on_submitted_work_done,map_async— ne se déclenchent que lors d'un poll), et la fenêtre redimensionnée est gérée parApp::resize(surface + depth texture recréées ensemble).
Flux manual (exemple manual — un objet par soumission) :
Context::get_next_frame()(ouFrame::try_new(&context.surface)) : acquiert la surface texture et crée saTextureView(dansFrame).Renderer::render(&view, &mesh, &material): crée unCommandEncoder, écrit les ordres de dessin dans laTextureView, puis soumet à la file (queue).Renderer::present(frame): présente l'image à l'écran.
Variante bas niveau (API Context brute, sans Frame) :
Context::begin_frame(): acquiert la surface et renvoie lawgpu::SurfaceTexture(sans vue).Context::end_frame(surface_texture): soumet et présente cette texture.
Liens
- ARCHI_APP · ARCHI_RENDU · ARCHI_CPU_GPU · ARCHI_ARENES
- Documentation utilisateur : docs/user · README racine · ROADMAP
- Référence API :
cargo doc -p wsg-lib --no-deps
Pourquoi cette séparation est vitale
Le bloc { let mut render_pass = ... } est crucial. Dans Rust, render_pass emprunte mutablement encoder. Il doit être détruit (via la fin du bloc ou un drop()) avant que tu puisses appeler encoder.finish(). Si tu oublies cela, le compilateur Rust refusera de compiler, empêchant ainsi des bugs critiques de synchronisation GPU.
Ressources : Persistantes vs Par-Frame
Avec notre nouvelle architecture "Atelier", la distinction est devenue encore plus nette :
| Élément | Durée de vie | Pourquoi ? |
|---|---|---|
| SurfaceConfiguration | Persistante | Ne change qu'au redimensionnement. |
| RenderPipeline | Persistante | Stocké dans le PipelineCache (Arc), compilation unique. |
| Material | Persistante | Définit le look ; partage le pipeline via Arc. |
| Mesh | Persistante | Les données géométriques sont envoyées une fois au GPU. |
| CommandEncoder | Par-Frame | Ton "carnet de notes" temporaire pour les ordres du GPU. |
| TextureView | Par-Frame | Fenêtre temporaire sur la texture active du swapchain. |
Ressources GPU persistantes (single buffer) — implémenté (Phase 3, 2026-09-22) : les buffers Transform, Matrix, BBox et Indirect Draw vivent en VRAM (créés à l'initialisation du
Renderer, capacité fixe de 256 slots). Le CPU écrit les transforms chaque frame parqueue.write_bufferdans le mêmeCommandEncoderque les compute passes, qui les lisent dans la même frame (l'ordre est garanti par l'encoder, pas parqueue.submit()inter-frames). Le double buffering reste la cible si des artefacts apparaissent à haute fréquence (voir ARCHI_CPU_GPU / ARCHI_APP).