b72c4e43ae
Clarify for each docs/tech document whether it describes the current (implemented) or target (planned) architecture, and reconcile with the readme/roadmap source of truth: - ARCHI_APP, ARCHI_CPU_GPU, ARCHI_RENDU: mark status=target and add a banner stating the GPU-driven two-pass pipeline, persistent VRAM buffers and scene auto-render are not implemented (they are ROADMAP Phase 3 / README roadmap items 1-3). render() still cannot draw the scene. - ARCHI_ARENES: status=target/deferred. String IDs are the current design; slotmap generational handles are the deferred 'typed handles' step and the slotmap dependency is currently absent (supersedes the retired dep). - FRAME_LOOP: stays status=current; correct the described API flow (Frame based via get_next_frame/Renderer::present, plus the low-level begin_frame/end_frame variant) and move the single-buffer VRAM note to target. - README: label each tech doc as current or target in the Documentation section.
59 lines
3.2 KiB
Markdown
59 lines
3.2 KiB
Markdown
---
|
|
type: Technical Specification
|
|
title: Frame Loop Architecture
|
|
description: Technical specification for the frame loop architecture in wsg_lib, detailing the immutable frame lifetime cycle and resource management
|
|
tags: [architecture, rendering, frame-loop, gpu, wgpu]
|
|
actor: person/jerome
|
|
sources: []
|
|
generated: { by: human:jerome, at: 2026-07-31T00:00:00Z }
|
|
verified: true
|
|
status: current
|
|
stale_after: 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. Il concerne le rendu **CPU-piloté actuel** (objet par objet, exemple `manual`).
|
|
> Le pipeline GPU-driven de l'état **visé** est décrit dans ARCHI_APP.md / ARCHI_CPU_GPU.md (cible).
|
|
|
|
Pour afficher quelque chose, nous suivons un cycle immuable appelé la Frame Lifetime. Deux flux coexistent, tous deux basés sur `Frame` :
|
|
|
|
**Flux `Frame` (utilisé par `App::run` et l'exemple `manual`) :**
|
|
- **`Context::get_next_frame()`** (ou `Frame::try_new(&context.surface)`) : acquiert la surface texture et crée sa `TextureView` (dans `Frame`).
|
|
- **`Renderer::render(&view, &mesh, &material)`** : crée un `CommandEncoder`, écrit les ordres de dessin dans la `TextureView`, 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 la `wgpu::SurfaceTexture` (sans vue).
|
|
- **`Context::end_frame(surface_texture)`** : soumet et présente cette texture.
|
|
|
|
---
|
|
|
|
## 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) — CIBLE, non implémenté** : À l'état **visé**, les
|
|
> buffers Transform et Matrix vivent en VRAM avec un single buffer en phase initiale (le CPU écrit
|
|
> pendant `update()`, le compute shader lit au frame suivant, séquencé par `queue.submit()`), puis un
|
|
> double buffering si des artefacts apparaissent à haute fréquence. **Aucune de ces ressources n'existe
|
|
> encore dans le code** — c'est la cible GPU-driven (ROADMAP Phase 3 / ARCHI_CPU_GPU).
|
|
|
|
---
|