Skip to main content

valo_renderer/
report.rs

1//! `report` accounts for resources retained between frames.
2//!
3//! Pool byte counts are estimates derived from resource descriptors, not
4//! queried from the driver. wgpu's own counters are included when the
5//! `counters` feature is on.
6
7/// `PoolReport` summarizes one resource pool or cache.
8#[derive(Clone, Copy, Debug, Default)]
9pub struct PoolReport {
10    /// `count` is the number of live entries.
11    pub count: u32,
12    /// `bytes` is their estimated memory usage.
13    pub bytes: u64,
14}
15
16/// `AtlasReport` summarizes one glyph-atlas family.
17#[derive(Clone, Copy, Debug, Default)]
18pub struct AtlasReport {
19    /// `pages` is the number of allocated atlas textures.
20    pub pages: u32,
21    /// `bytes` is their estimated GPU memory usage.
22    pub bytes: u64,
23    /// `entries` is the number of resident rasterized glyphs.
24    ///
25    /// Whitespace placeholders are excluded.
26    pub entries: u32,
27}
28
29/// `WgpuCounters` reports wgpu's internal live-object accounting.
30///
31/// All values are zero unless the `counters` feature is enabled.
32#[derive(Clone, Copy, Debug, Default)]
33pub struct WgpuCounters {
34    /// `enabled` indicates whether the `counters` feature is active.
35    pub enabled: bool,
36    /// `buffers` is the number of live wgpu buffers.
37    pub buffers: i64,
38    /// `textures` is the number of live wgpu textures.
39    pub textures: i64,
40    /// `bind_groups` is the number of live wgpu bind groups.
41    pub bind_groups: i64,
42    /// `buffer_memory` is wgpu's reported buffer memory in bytes.
43    pub buffer_memory: i64,
44    /// `texture_memory` is wgpu's reported texture memory in bytes.
45    pub texture_memory: i64,
46}
47
48/// `MemoryReport` summarizes resources retained between frames.
49///
50/// Pool byte counts are estimates derived from resource descriptors. `wgpu`
51/// contains separate internal counters when that feature is enabled.
52#[derive(Clone, Copy, Debug, Default)]
53pub struct MemoryReport {
54    /// `images` reports live uploaded images, including mip levels.
55    pub images: PoolReport,
56    /// `atlas` reports `[mask and SDF, color]` glyph-atlas families.
57    pub atlas: [AtlasReport; 2],
58    /// `targets` reports pooled layer, snapshot, filter, and scratch targets.
59    pub targets: PoolReport,
60    /// `host_buffer` reports transient upload-buffer blocks.
61    pub host_buffer: PoolReport,
62    /// `contours` reports cached flattened path contours.
63    pub contours: PoolReport,
64    /// `glyph_paths` reports cached vector glyph paths.
65    pub glyph_paths: PoolReport,
66    /// `ramps` reports cached gradient-ramp textures.
67    pub ramps: PoolReport,
68    /// `raster_cache` reports cached display-list textures.
69    pub raster_cache: PoolReport,
70    /// `wgpu` contains wgpu's internal object and memory counters.
71    pub wgpu: WgpuCounters,
72}
73
74impl MemoryReport {
75    /// `total_bytes` returns the sum of Valo's estimated retained memory.
76    ///
77    /// The separate wgpu counters are excluded.
78    pub fn total_bytes(&self) -> u64 {
79        self.images.bytes
80            + self.atlas.iter().map(|a| a.bytes).sum::<u64>()
81            + self.targets.bytes
82            + self.raster_cache.bytes
83            + self.host_buffer.bytes
84            + self.contours.bytes
85            + self.glyph_paths.bytes
86            + self.ramps.bytes
87    }
88}
89
90pub(crate) fn wgpu_counters(device: &wgpu::Device) -> WgpuCounters {
91    let hal = device.get_internal_counters().hal;
92    WgpuCounters {
93        enabled: cfg!(feature = "counters"),
94        buffers: hal.buffers.read() as i64,
95        textures: hal.textures.read() as i64,
96        bind_groups: hal.bind_groups.read() as i64,
97        buffer_memory: hal.buffer_memory.read() as i64,
98        texture_memory: hal.texture_memory.read() as i64,
99    }
100}
101
102#[cfg(test)]
103mod tests {
104    use super::{AtlasReport, MemoryReport, PoolReport, WgpuCounters};
105
106    #[test]
107    fn total_bytes_includes_every_valo_pool() {
108        let report = MemoryReport {
109            images: pool(1),
110            atlas: [atlas(2), atlas(3)],
111            targets: pool(4),
112            host_buffer: pool(5),
113            contours: pool(6),
114            glyph_paths: pool(7),
115            ramps: pool(8),
116            raster_cache: pool(9),
117            wgpu: WgpuCounters {
118                buffer_memory: 1_000,
119                texture_memory: 2_000,
120                ..Default::default()
121            },
122        };
123
124        assert_eq!(report.total_bytes(), 45);
125    }
126
127    fn pool(bytes: u64) -> PoolReport {
128        PoolReport { count: 1, bytes }
129    }
130
131    fn atlas(bytes: u64) -> AtlasReport {
132        AtlasReport {
133            pages: 1,
134            bytes,
135            entries: 1,
136        }
137    }
138}