refactor(renderer): activate depth buffer on all render paths (Étape 9)
- 9.1: allocate shared Depth32Float depth texture + view in Renderer, sized to the initial surface (create_depth_texture helper, reusable for the Phase 4.4 resize); Renderer::new now takes width/height. - 9.2: attach depth_stencil_attachment (clear 1.0 / store) to both the low-level render and high-level render_scene passes. - 9.3: every pipeline declares a matching DepthStencilState (write true, compare Less) via the shared DEPTH_FORMAT constant (D1). Décisions D1-D4 actées 2026-09-18 (DRAFT Étape 9).
This commit is contained in:
@@ -21,7 +21,7 @@
|
||||
use crate::core::Context;
|
||||
use crate::core::Frame;
|
||||
use crate::math::Transform;
|
||||
use crate::pipeline::create_uniform_bind_group_layouts;
|
||||
use crate::pipeline::{DEPTH_FORMAT, create_uniform_bind_group_layouts};
|
||||
use crate::resources::uniform::{FRAME_UNIFORMS_SIZE, OBJECT_UNIFORM_SIZE};
|
||||
use crate::resources::{Camera, FrameUniforms, Material, Mesh, ObjectUniform};
|
||||
use crate::scene::Scene;
|
||||
@@ -42,6 +42,14 @@ pub struct Renderer {
|
||||
device: wgpu::Device,
|
||||
/// Surface texture output format — stored here so it can be passed to PipelineCache on Material creation.
|
||||
format: wgpu::TextureFormat,
|
||||
/// z-buffer texture backing `depth_view` (Étape 9). Held here only to keep the GPU resource
|
||||
/// alive for the whole application lifetime (a `TextureView` alone does not guarantee the
|
||||
/// underlying `Texture` stays valid in wgpu). Not read directly (hence `_` prefix → no
|
||||
/// `dead_code`); reused when the depth texture is recreated at resize (ROADMAP Phase 4.4).
|
||||
_depth_texture: wgpu::Texture,
|
||||
/// Depth attachment view used by both render passes (`render`, `render_scene`). Format
|
||||
/// `DEPTH_FORMAT` (Depth32Float) — matches every pipeline's `DepthStencilState` (D1).
|
||||
depth_view: wgpu::TextureView,
|
||||
/// Bind group layout for the per-object uniforms (group 1) — must match every pipeline layout.
|
||||
object_layout: wgpu::BindGroupLayout,
|
||||
/// Shared per-frame uniform buffer handle — kept so the camera matrices can be rewritten each
|
||||
@@ -64,15 +72,21 @@ pub struct Renderer {
|
||||
impl Renderer {
|
||||
/// Creates a Renderer by cloning Device and Queue Arc references from the Context, plus capturing
|
||||
/// the surface format, and allocates the shared frame + object uniform buffers and their bind groups.
|
||||
/// Inputs: context (borrowed reference to Context providing GPU resource handles), format (surface texture format).
|
||||
/// Inputs: context (borrowed reference to Context providing GPU resource handles), format (surface
|
||||
/// texture format), width (surface width in pixels) and height (surface height in pixels) — the
|
||||
/// latter two size the depth texture allocated here (Étape 9).
|
||||
/// Returns a new Renderer instance sharing the same underlying GPU resources as Context.
|
||||
/// Called once at application startup during scene setup. The Renderer shares these resources via Arc;
|
||||
/// Context retains ownership and can continue using them after this call.
|
||||
pub fn new(context: &Context, format: wgpu::TextureFormat) -> Self {
|
||||
pub fn new(context: &Context, format: wgpu::TextureFormat, width: u32, height: u32) -> Self {
|
||||
let queue: wgpu::Queue = context.queue.clone();
|
||||
let device: wgpu::Device = context.device.clone();
|
||||
let [frame_layout, object_layout] = create_uniform_bind_group_layouts(&device);
|
||||
|
||||
// Étape 9 (DRAFT 9.1) : depth texture + view, allouées une seule fois à la taille initiale
|
||||
// de la surface (D3). Le helper isolé rendra trivial le recreate planifié en Phase 4.4.
|
||||
let (depth_texture, depth_view) = create_depth_texture(&device, width, height);
|
||||
|
||||
// Shared frame uniforms: identity camera + white directional light, lit mode by default.
|
||||
// Values become meaningful once an active camera is wired (Étape 4.3); for now the default
|
||||
// is a coherent scene when a shader actually reads them, and irrelevant to shaders that don't.
|
||||
@@ -115,6 +129,8 @@ impl Renderer {
|
||||
queue,
|
||||
device,
|
||||
format,
|
||||
_depth_texture: depth_texture,
|
||||
depth_view,
|
||||
object_layout,
|
||||
frame_buffer,
|
||||
frame_bind_group,
|
||||
@@ -200,6 +216,16 @@ impl Renderer {
|
||||
store: wgpu::StoreOp::Store,
|
||||
},
|
||||
})],
|
||||
// Étape 9 (DRAFT 9.2) : depth attachment via la view partagée (D1 : clear 1.0
|
||||
// = profondeur max au loin en début de frame, puis Store pour la garder).
|
||||
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
|
||||
view: &self.depth_view,
|
||||
depth_ops: Some(wgpu::Operations {
|
||||
load: wgpu::LoadOp::Clear(1.0),
|
||||
store: wgpu::StoreOp::Store,
|
||||
}),
|
||||
stencil_ops: None,
|
||||
}),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
@@ -245,6 +271,16 @@ impl Renderer {
|
||||
store: wgpu::StoreOp::Store,
|
||||
},
|
||||
})],
|
||||
// Étape 9 (DRAFT 9.2) : même depth attachment que le chemin bas niveau, pour un
|
||||
// z-test cohérent (D2 — les deux render passes partagent la depth_view).
|
||||
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
|
||||
view: &self.depth_view,
|
||||
depth_ops: Some(wgpu::Operations {
|
||||
load: wgpu::LoadOp::Clear(1.0),
|
||||
store: wgpu::StoreOp::Store,
|
||||
}),
|
||||
stencil_ops: None,
|
||||
}),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
@@ -321,6 +357,38 @@ impl Renderer {
|
||||
}
|
||||
}
|
||||
|
||||
/// Allocates the depth texture + view backing the render passes' `depth_stencil_attachment`
|
||||
/// (Étape 9, DRAFT 9.1). Format is the shared `DEPTH_FORMAT` (Depth32Float, D1) so it always
|
||||
/// matches every pipeline's `DepthStencilState`. Sized to the surface (width x height), single
|
||||
/// mip, no MSAA, used strictly as a render target.
|
||||
///
|
||||
/// Exposed as a standalone helper so the depth texture can be recreated cheaply at resize
|
||||
/// (ROADMAP Phase 4.4) without touching the render-pass logic.
|
||||
/// Inputs: device (GPU resource creator), width (surface width), height (surface height).
|
||||
/// Returns the (texture, view) pair; the caller keeps both alive.
|
||||
fn create_depth_texture(
|
||||
device: &wgpu::Device,
|
||||
width: u32,
|
||||
height: u32,
|
||||
) -> (wgpu::Texture, wgpu::TextureView) {
|
||||
let depth_texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: Some("depth texture"),
|
||||
size: wgpu::Extent3d {
|
||||
width,
|
||||
height,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: DEPTH_FORMAT,
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||
view_formats: &[],
|
||||
});
|
||||
let depth_view = depth_texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||
(depth_texture, depth_view)
|
||||
}
|
||||
|
||||
/// Binds a Material pipeline, the two uniform bind groups, and Mesh buffers into an active render
|
||||
/// pass and issues the draw call. Shared by `Renderer::render` and `Renderer::render_scene`.
|
||||
/// The frame (group 0) and object (group 1) bind groups are **required** by every pipeline layout
|
||||
|
||||
Reference in New Issue
Block a user