fix view leak and add view count

This commit is contained in:
2025-08-24 22:13:02 -04:00
parent 74d01d14d4
commit 44a8b1cbeb
7 changed files with 41 additions and 18 deletions

View File

@@ -13,6 +13,7 @@ struct State {
region: UiRegion, region: UiRegion,
children: Vec<Id>, children: Vec<Id>,
parent: Option<Id>, parent: Option<Id>,
textures: Vec<TextureHandle>,
// TODO: there's probably a better way but idc at this point // TODO: there's probably a better way but idc at this point
id: Option<Id>, id: Option<Id>,
} }
@@ -59,6 +60,7 @@ impl<'a, Ctx> Painter<'a, Ctx> {
children: Vec::new(), children: Vec::new(),
parent: None, parent: None,
id: None, id: None,
textures: Vec::new(),
}, },
} }
} }
@@ -109,6 +111,7 @@ impl<'a, Ctx> Painter<'a, Ctx> {
children: Vec::new(), children: Vec::new(),
id: Some(id.duplicate()), id: Some(id.duplicate()),
parent: self.state.id.as_ref().map(|i| i.duplicate()), parent: self.state.id.as_ref().map(|i| i.duplicate()),
textures: Vec::new(),
}; };
// save state // save state
let self_state = std::mem::replace(&mut self.state, child_state); let self_state = std::mem::replace(&mut self.state, child_state);
@@ -129,13 +132,14 @@ impl<'a, Ctx> Painter<'a, Ctx> {
span: start_i..end_i, span: start_i..end_i,
children: child_state.children, children: child_state.children,
parent: child_state.parent, parent: child_state.parent,
textures: child_state.textures,
}, },
self.sensors_map, self.sensors_map,
); );
} }
pub fn draw_texture(&mut self, handle: &TextureHandle) { pub fn draw_texture(&mut self, handle: &TextureHandle) {
self.primitives.drawn_textures.push(handle.clone()); self.state.textures.push(handle.clone());
self.write(handle.inner); self.write(handle.inner);
} }

View File

@@ -273,6 +273,7 @@ pub struct WidgetInstance {
pub span: Range<usize>, pub span: Range<usize>,
pub children: Vec<Id>, pub children: Vec<Id>,
pub parent: Option<Id>, pub parent: Option<Id>,
pub textures: Vec<TextureHandle>,
} }
pub type ActiveWidgets = HashMap<Id, WidgetInstance>; pub type ActiveWidgets = HashMap<Id, WidgetInstance>;

View File

@@ -264,6 +264,10 @@ impl UiRenderer {
label: Some("ui rsc"), label: Some("ui rsc"),
}) })
} }
pub fn view_count(&self) -> usize {
self.textures.view_count()
}
} }
pub struct UiLimits { pub struct UiLimits {

View File

@@ -4,7 +4,7 @@ use std::{
}; };
use crate::{ use crate::{
layout::{Color, TextureHandle, UiRegion}, layout::{Color, UiRegion},
render::{ArrBuf, data::PrimitiveInstance}, render::{ArrBuf, data::PrimitiveInstance},
}; };
use bytemuck::Pod; use bytemuck::Pod;
@@ -14,8 +14,6 @@ pub struct Primitives {
pub(super) instances: Vec<PrimitiveInstance>, pub(super) instances: Vec<PrimitiveInstance>,
pub(super) run: Vec<PrimitiveInstance>, pub(super) run: Vec<PrimitiveInstance>,
pub(super) data: PrimitiveData, pub(super) data: PrimitiveData,
// ensure drawn textures don't get freed
pub(crate) drawn_textures: Vec<TextureHandle>,
pub updated: bool, pub updated: bool,
run_start: usize, run_start: usize,
} }
@@ -26,7 +24,6 @@ impl Default for Primitives {
instances: Default::default(), instances: Default::default(),
run: Default::default(), run: Default::default(),
data: Default::default(), data: Default::default(),
drawn_textures: Default::default(),
updated: true, updated: true,
run_start: 0, run_start: 0,
} }
@@ -117,7 +114,6 @@ impl Primitives {
self.instances.clear(); self.instances.clear();
self.run.clear(); self.run.clear();
self.data.clear(); self.data.clear();
self.drawn_textures.clear();
} }
pub fn set<P: Primitive>(&mut self, handle: &PrimitiveHandle<P>, data: P) { pub fn set<P: Primitive>(&mut self, handle: &PrimitiveHandle<P>, data: P) {

View File

@@ -7,6 +7,7 @@ pub struct GpuTextures {
device: Device, device: Device,
queue: Queue, queue: Queue,
views: Vec<TextureView>, views: Vec<TextureView>,
view_count: usize,
samplers: Vec<Sampler>, samplers: Vec<Sampler>,
null_view: TextureView, null_view: TextureView,
no_views: Vec<TextureView>, no_views: Vec<TextureView>,
@@ -23,19 +24,19 @@ impl GpuTextures {
TextureUpdate::Free(i) => self.free(i), TextureUpdate::Free(i) => self.free(i),
} }
} }
// if changed {
// println!("{}", self.views.len());
// }
changed changed
} }
fn set(&mut self, i: u32, image: &DynamicImage) { fn set(&mut self, i: u32, image: &DynamicImage) {
self.view_count += 1;
let view = self.create_view(image); let view = self.create_view(image);
self.views[i as usize] = view; self.views[i as usize] = view;
} }
fn free(&mut self, i: u32) { fn free(&mut self, i: u32) {
self.view_count -= 1;
self.views[i as usize] = self.null_view.clone(); self.views[i as usize] = self.null_view.clone();
} }
fn push(&mut self, image: &DynamicImage) { fn push(&mut self, image: &DynamicImage) {
self.view_count += 1;
let view = self.create_view(image); let view = self.create_view(image);
self.views.push(view); self.views.push(view);
} }
@@ -74,6 +75,7 @@ impl GpuTextures {
samplers: vec![default_sampler(device)], samplers: vec![default_sampler(device)],
no_views: vec![null_view.clone()], no_views: vec![null_view.clone()],
null_view, null_view,
view_count: 0,
} }
} }
@@ -91,6 +93,10 @@ impl GpuTextures {
pub fn samplers(&self) -> Vec<&Sampler> { pub fn samplers(&self) -> Vec<&Sampler> {
self.samplers.iter().by_ref().collect() self.samplers.iter().by_ref().collect()
} }
pub fn view_count(&self) -> usize {
self.view_count
}
} }
pub fn null_texture_view(device: &Device) -> TextureView { pub fn null_texture_view(device: &Device) -> TextureView {

View File

@@ -23,7 +23,7 @@ pub struct Client {
pub struct ClientUi { pub struct ClientUi {
info: WidgetId<Text>, info: WidgetId<Text>,
old_num: usize, old_info: String,
} }
impl Client { impl Client {
@@ -153,11 +153,19 @@ impl Client {
del_button.label("del button"), del_button.label("del button"),
info_sect.label("info sect"), info_sect.label("info sect"),
) )
.stack().label("main stack"), .stack()
.label("main stack"),
) )
.span(Dir::DOWN, [fixed(40), ratio(1)]).label("root"), .span(Dir::DOWN, [fixed(40), ratio(1)])
.label("root"),
); );
(ui, ClientUi { info, old_num: 0 }) (
ui,
ClientUi {
info,
old_info: String::new(),
},
)
} }
pub fn new(window: Arc<Window>, ui: ClientUi) -> Self { pub fn new(window: Arc<Window>, ui: ClientUi) -> Self {
@@ -187,10 +195,14 @@ impl Client {
} }
_ => (), _ => (),
} }
let num = ui.num_widgets(); let new = format!(
if num != self.ui.old_num { "widgets: {}\nviews: {}",
ui[&self.ui.info].content = format!("widgets: {}", num); ui.num_widgets(),
self.ui.old_num = num; self.renderer.ui.view_count()
);
if new != self.ui.old_info {
ui[&self.ui.info].content = new.clone();
self.ui.old_info = new;
} }
if ui.needs_redraw() { if ui.needs_redraw() {
self.renderer.window().request_redraw(); self.renderer.window().request_redraw();

View File

@@ -17,7 +17,7 @@ pub struct Renderer {
config: SurfaceConfiguration, config: SurfaceConfiguration,
encoder: CommandEncoder, encoder: CommandEncoder,
staging_belt: StagingBelt, staging_belt: StagingBelt,
ui: UiRenderer, pub ui: UiRenderer,
} }
impl Renderer { impl Renderer {