texture freeing + render updates done a bit nicer

This commit is contained in:
2025-08-23 13:02:00 -04:00
parent 5fe63e311c
commit 6fbdf9fbc8
10 changed files with 176 additions and 108 deletions

View File

@@ -1,48 +1,81 @@
use image::DynamicImage;
use crate::render::TexturePrimitive;
use crate::{UiMsg, UiMsgSender, render::TexturePrimitive, util::RefCounter};
/// TODO: proper resource management
pub struct TextureHandle {
pub inner: TexturePrimitive,
counter: RefCounter,
send: UiMsgSender,
}
/// a texture manager for a ui
/// note that this is heavily oriented towards wgpu's renderer so the primitives don't need mapped
#[derive(Default)]
pub struct Textures {
/// TODO: these are images, not views rn
views: Vec<DynamicImage>,
changed: bool,
free: Vec<u32>,
images: Vec<Option<DynamicImage>>,
updates: Vec<Update>,
}
pub struct TextureUpdates<'a> {
pub images: Option<&'a [DynamicImage]>,
pub enum TextureUpdate<'a> {
Push(&'a DynamicImage),
Set(u32, &'a DynamicImage),
Free(u32),
}
enum Update {
Push(u32),
Set(u32),
Free(u32),
}
impl Textures {
pub fn add(&mut self, image: DynamicImage) -> TextureHandle {
let view_idx = self.views.len() as u32;
self.views.push(image);
pub fn add(&mut self, image: DynamicImage, send: UiMsgSender) -> TextureHandle {
let view_idx = self.push(image);
// 0 == default in renderer; TODO: actually create samplers here
let sampler_idx = 0;
self.changed = true;
TextureHandle {
inner: TexturePrimitive {
view_idx,
sampler_idx,
},
counter: RefCounter::new(),
send,
}
}
pub fn updates(&mut self) -> TextureUpdates<'_> {
if self.changed {
self.changed = false;
TextureUpdates {
images: Some(&self.views),
}
fn push(&mut self, image: DynamicImage) -> u32 {
if let Some(i) = self.free.pop() {
self.images[i as usize] = Some(image);
self.updates.push(Update::Set(i));
i
} else {
TextureUpdates { images: None }
let i = self.images.len() as u32;
self.images.push(Some(image));
self.updates.push(Update::Push(i));
i
}
}
pub fn free(&mut self, idx: u32) {
self.images[idx as usize] = None;
self.updates.push(Update::Free(idx));
self.free.push(idx);
}
pub fn updates(&mut self) -> impl Iterator<Item = TextureUpdate<'_>> {
self.updates.drain(..).map(|u| match u {
Update::Push(i) => TextureUpdate::Push(self.images[i as usize].as_ref().unwrap()),
Update::Set(i) => TextureUpdate::Set(i, self.images[i as usize].as_ref().unwrap()),
Update::Free(i) => TextureUpdate::Free(i),
})
}
}
impl Drop for TextureHandle {
fn drop(&mut self) {
if self.counter.drop() {
let _ = self.send.send(UiMsg::FreeTexture(self.inner.view_idx));
}
}
}