aetna_wgpu/msaa.rs
1//! MSAA color-attachment helper.
2//!
3//! Aetna's stock surfaces (rounded_rect, gradient, custom rect-shaped
4//! shaders) compute coverage analytically inside the fragment shader,
5//! so MSAA only helps when sample-rate shading is on — the SDF input
6//! varying carries `@interpolate(perspective, sample)` and the shader
7//! evaluates per sub-sample. Pair that with a [`Runner`](crate::Runner)
8//! built via [`Runner::with_sample_count`](crate::Runner::with_sample_count)
9//! and an [`MsaaTarget`] of matching `sample_count` for the attachment.
10//!
11//! The host always supplies the single-sample resolve target itself —
12//! a fresh texture in headless render binaries (so it can be read back
13//! / sampled), or the surface frame in windowed apps. `MsaaTarget` is
14//! deliberately just the multisampled side; bundling the resolve here
15//! would waste a fullscreen texture in the surface case.
16
17/// A multisampled color attachment.
18///
19/// Hosts allocate one of these to match their resolve target's extent
20/// and pass [`Self::view`] as the render pass `view` while binding
21/// their resolve target as `resolve_target`. On window resize, check
22/// [`Self::matches`] and reallocate when it returns false.
23pub struct MsaaTarget {
24 pub texture: wgpu::Texture,
25 pub view: wgpu::TextureView,
26 pub sample_count: u32,
27 pub format: wgpu::TextureFormat,
28 pub size: wgpu::Extent3d,
29}
30
31impl MsaaTarget {
32 /// Build a fresh multisampled color attachment sized to `size`.
33 /// Usage is `RENDER_ATTACHMENT` only — multisampled textures cannot
34 /// be sampled or copied directly; the resolve target is what the
35 /// host reads back, presents, or samples.
36 pub fn new(
37 device: &wgpu::Device,
38 format: wgpu::TextureFormat,
39 size: wgpu::Extent3d,
40 sample_count: u32,
41 ) -> Self {
42 let texture = device.create_texture(&wgpu::TextureDescriptor {
43 label: Some("aetna_wgpu::msaa_target"),
44 size,
45 mip_level_count: 1,
46 sample_count,
47 dimension: wgpu::TextureDimension::D2,
48 format,
49 usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
50 view_formats: &[],
51 });
52 let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
53 Self {
54 texture,
55 view,
56 sample_count,
57 format,
58 size,
59 }
60 }
61
62 /// True when this target's extent matches the requested size — the
63 /// idiomatic "do I need to reallocate after a resize?" check.
64 pub fn matches(&self, size: wgpu::Extent3d) -> bool {
65 self.size.width == size.width
66 && self.size.height == size.height
67 && self.size.depth_or_array_layers == size.depth_or_array_layers
68 }
69}