feat(core): Étape 11 — resize (surface + depth, Phase 4.4)

This commit is contained in:
Jérôme Bousquié
2026-09-18 17:29:45 +02:00
parent f4df63a136
commit b0aafefed9
4 changed files with 73 additions and 6 deletions
+41
View File
@@ -135,6 +135,29 @@ impl App {
let aspect = size.width as f32 / size.height.max(1) as f32;
self.renderer().render_scene(view, &self.scene, aspect);
}
/// Resizes the surface and depth texture to a new window size (ROADMAP Phase 4.4).
/// Reconfigures the surface via `Context::configure` (which returns the chosen format) and
/// recreates the depth texture via `Renderer::resize_depth` so the color and depth attachments
/// stay the same size. If the surface format changes (rare, deterministic per window), the
/// Scene's GPU context is re-initialized to the new format; otherwise the swap alone suffices.
/// Inputs: width/height — the new surface dimensions in pixels.
/// Returns Ok(()) on success or a `WsgError` if the surface cannot be reconfigured.
pub fn resize(&mut self, width: u32, height: u32) -> Result<(), WsgError> {
let context = self.context.as_ref().ok_or(WsgError::SurfaceIncompatible)?;
let old_format = self.renderer().format();
let new_format = context.configure(&context.adapter, width, height)?;
self.renderer_mut().resize_depth(width, height);
self.renderer_mut().set_format(new_format);
if new_format != old_format {
// Surface format changed: re-wire the Scene's GPU context (device + queue + format)
// so its PipelineCache/pipelines match the new surface format.
let device = std::sync::Arc::new(self.renderer_mut().device().clone());
self.scene
.init_gpu(device, self.context().queue.clone(), new_format);
}
Ok(())
}
}
/// Builder for constructing a configured `App` instance with custom title and dimensions.
@@ -277,7 +300,25 @@ impl<H: AppHandler> ApplicationHandler for AppRunner<H> {
return;
};
match event {
WindowEvent::Resized(size) => {
// Garde (D3) : minimiser la fenêtre envoie Resized(0x0) ; ne jamais reconfigurer à 0.
let w = size.width as u32;
let h = size.height as u32;
if w == 0 || h == 0 {
return;
}
// Étape 11 : reconfigurer surface + depth à la nouvelle taille, puis re-rendre.
if let Err(e) = app.resize(w, h) {
eprintln!("WSG : erreur de resize ({e:?})");
}
app.window().request_redraw();
}
WindowEvent::RedrawRequested => {
// Garde (D6) : ne pas rendre sur une surface de taille nulle (fenêtre minimisée).
let size = app.window().inner_size();
if size.width == 0 || size.height == 0 {
return;
}
// Rendering logic
let frame = app.context().get_next_frame();
+17
View File
@@ -167,6 +167,23 @@ impl Renderer {
self.write_default_frame_uniforms();
}
/// Recreates the depth texture at a new size, used on window resize (ROADMAP Phase 4.4).
/// The previous depth texture is dropped when its field is replaced — no leak, no double
/// allocation. The helper `create_depth_texture` (Étape 9, D3) is reused so the recreate stays
/// trivial. Inputs: width/height — the new surface dimensions in pixels.
pub fn resize_depth(&mut self, width: u32, height: u32) {
let (depth_texture, depth_view) = create_depth_texture(&self.device, width, height);
self._depth_texture = depth_texture;
self.depth_view = depth_view;
}
/// Updates the stored surface texture format after a surface reconfigure (ROADMAP Phase 4.4).
/// Used when `Context::configure` returns a different format so the Renderer stays in sync
/// with the surface. Inputs: format — the new surface texture format.
pub fn set_format(&mut self, format: wgpu::TextureFormat) {
self.format = format;
}
/// Rewrites the shared per-frame uniform buffer from the scene's active camera and the current
/// viewport aspect, then returns the frame bind group wired to that buffer. Called at the start of
/// every `render_scene` so the GPU sees the latest camera matrices and camera position (Étape 4.3).