gpu_allocator/metal/
visualizer.rs1#![allow(clippy::new_without_default)]
2
3use super::Allocator;
4use crate::visualizer::{
5 render_allocation_reports_ui, AllocationReportVisualizeSettings, ColorScheme,
6 MemoryChunksVisualizationSettings,
7};
8
9struct AllocatorVisualizerBlockWindow {
10 memory_type_index: usize,
11 block_index: usize,
12 settings: MemoryChunksVisualizationSettings,
13}
14impl AllocatorVisualizerBlockWindow {
15 fn new(memory_type_index: usize, block_index: usize) -> Self {
16 Self {
17 memory_type_index,
18 block_index,
19 settings: Default::default(),
20 }
21 }
22}
23
24pub struct AllocatorVisualizer {
25 selected_blocks: Vec<AllocatorVisualizerBlockWindow>,
26 color_scheme: ColorScheme,
27 breakdown_settings: AllocationReportVisualizeSettings,
28}
29
30impl AllocatorVisualizer {
31 pub fn new() -> Self {
32 Self {
33 selected_blocks: Vec::default(),
34 color_scheme: ColorScheme::default(),
35 breakdown_settings: Default::default(),
36 }
37 }
38
39 pub fn set_color_scheme(&mut self, color_scheme: ColorScheme) {
40 self.color_scheme = color_scheme;
41 }
42
43 pub fn render_memory_block_ui(&mut self, ui: &mut egui::Ui, alloc: &Allocator) {
44 ui.collapsing(
45 format!("Memory Types: ({} types)", alloc.memory_types.len()),
46 |ui| {
47 for (mem_type_idx, mem_type) in alloc.memory_types.iter().enumerate() {
48 ui.collapsing(
49 format!(
50 "Type: {} ({} blocks)",
51 mem_type_idx,
52 mem_type.memory_blocks.len(),
53 ),
54 |ui| {
55 let mut total_block_size = 0;
56 let mut total_allocated = 0;
57
58 for block in mem_type.memory_blocks.iter().flatten() {
59 total_block_size += block.size;
60 total_allocated += block.sub_allocator.allocated();
61 }
62
63 let active_block_count = mem_type
64 .memory_blocks
65 .iter()
66 .filter(|block| block.is_some())
67 .count();
68
69 ui.label(format!("properties: {:?}", mem_type.heap_properties));
70 ui.label(format!("memory type index: {}", mem_type.memory_type_index));
71 ui.label(format!("total block size: {} KiB", total_block_size / 1024));
72 ui.label(format!("total allocated: {} KiB", total_allocated / 1024));
73 ui.label(format!("block count: {active_block_count}"));
74
75 for (block_idx, block) in mem_type.memory_blocks.iter().enumerate() {
76 let Some(block) = block else { continue };
77
78 ui.collapsing(format!("Block: {block_idx}"), |ui| {
79 ui.label(format!("size: {} KiB", block.size / 1024));
80 ui.label(format!(
81 "allocated: {} KiB",
82 block.sub_allocator.allocated() / 1024
83 ));
84 ui.label(format!("Heap: {:?}", &block.heap));
85
86 block.sub_allocator.draw_base_info(ui);
87
88 if block.sub_allocator.supports_visualization()
89 && ui.button("visualize").clicked()
90 && !self.selected_blocks.iter().any(|x| {
91 x.memory_type_index == mem_type_idx
92 && x.block_index == block_idx
93 })
94 {
95 self.selected_blocks.push(
96 AllocatorVisualizerBlockWindow::new(
97 mem_type_idx,
98 block_idx,
99 ),
100 );
101 }
102 });
103 }
104 },
105 );
106 }
107 },
108 );
109 }
110
111 pub fn render_memory_block_window(
112 &mut self,
113 ctx: &egui::Context,
114 allocator: &Allocator,
115 open: &mut bool,
116 ) {
117 egui::Window::new("Allocator Memory Blocks")
118 .open(open)
119 .show(ctx, |ui| self.render_breakdown_ui(ui, allocator));
120 }
121
122 pub fn render_memory_block_visualization_windows(
123 &mut self,
124 ctx: &egui::Context,
125 allocator: &Allocator,
126 ) {
127 let color_scheme = &self.color_scheme;
129
130 self.selected_blocks.retain_mut(|window| {
131 let mut open = true;
132
133 egui::Window::new(format!(
134 "Block Visualizer {}:{}",
135 window.memory_type_index, window.block_index
136 ))
137 .default_size([1920.0 * 0.5, 1080.0 * 0.5])
138 .open(&mut open)
139 .show(ctx, |ui| {
140 let memblock = &allocator.memory_types[window.memory_type_index].memory_blocks
141 [window.block_index]
142 .as_ref();
143 if let Some(memblock) = memblock {
144 ui.label(format!(
145 "Memory type {}, Memory block {}, Block size: {} KiB",
146 window.memory_type_index,
147 window.block_index,
148 memblock.size / 1024
149 ));
150
151 window
152 .settings
153 .ui(ui, allocator.debug_settings.store_stack_traces);
154
155 ui.separator();
156
157 memblock
158 .sub_allocator
159 .draw_visualization(color_scheme, ui, &window.settings);
160 } else {
161 ui.label("Deallocated memory block");
162 }
163 });
164
165 open
166 });
167 }
168
169 pub fn render_breakdown_ui(&mut self, ui: &mut egui::Ui, allocator: &Allocator) {
170 render_allocation_reports_ui(
171 ui,
172 &mut self.breakdown_settings,
173 allocator
174 .memory_types
175 .iter()
176 .flat_map(|memory_type| memory_type.memory_blocks.iter())
177 .flatten()
178 .flat_map(|memory_block| memory_block.sub_allocator.report_allocations()),
179 );
180 }
181
182 pub fn render_breakdown_window(
183 &mut self,
184 ctx: &egui::Context,
185 allocator: &Allocator,
186 open: &mut bool,
187 ) {
188 egui::Window::new("Allocator Breakdown")
189 .open(open)
190 .show(ctx, |ui| self.render_breakdown_ui(ui, allocator));
191 }
192}