Avoid unnecessary computation/cloning in renderer
This commit is contained in:
		
							parent
							
								
									600148c781
								
							
						
					
					
						commit
						a82389224f
					
				
							
								
								
									
										30
									
								
								src/vram.rs
								
								
								
								
							
							
						
						
									
										30
									
								
								src/vram.rs
								
								
								
								
							| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
use std::{
 | 
			
		||||
    collections::{hash_map::Entry, HashMap},
 | 
			
		||||
    collections::{hash_map::Entry, HashMap, HashSet},
 | 
			
		||||
    hash::Hash,
 | 
			
		||||
    sync::{Arc, Mutex},
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -11,12 +11,12 @@ use egui::{
 | 
			
		|||
};
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
 | 
			
		||||
pub trait VramResource: Sized + PartialEq + Eq + Hash {
 | 
			
		||||
pub trait VramResource: Sized + Clone + PartialEq + Eq + Hash {
 | 
			
		||||
    fn to_uri(&self) -> String;
 | 
			
		||||
    fn from_uri(uri: &str) -> Option<Self>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: Serialize + for<'a> Deserialize<'a> + PartialEq + Eq + Hash> VramResource for T {
 | 
			
		||||
impl<T: Serialize + for<'a> Deserialize<'a> + Clone + PartialEq + Eq + Hash> VramResource for T {
 | 
			
		||||
    fn to_uri(&self) -> String {
 | 
			
		||||
        format!("vram://{}", serde_json::to_string(self).unwrap())
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +28,7 @@ impl<T: Serialize + for<'a> Deserialize<'a> + PartialEq + Eq + Hash> VramResourc
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
pub enum VramImage {
 | 
			
		||||
    Unchanged(Arc<ColorImage>),
 | 
			
		||||
    Unchanged(Option<Arc<ColorImage>>),
 | 
			
		||||
    Changed(ColorImage),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -40,11 +40,12 @@ impl VramImage {
 | 
			
		|||
    pub fn write(&mut self, coords: (usize, usize), shade: u8) {
 | 
			
		||||
        match self {
 | 
			
		||||
            Self::Unchanged(image) => {
 | 
			
		||||
                let value = image[coords];
 | 
			
		||||
                if value.r() == shade {
 | 
			
		||||
                if image.as_ref().is_none_or(|i| i[coords].r() == shade) {
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                let Some(mut new_image) = image.take().map(Arc::unwrap_or_clone) else {
 | 
			
		||||
                    return;
 | 
			
		||||
                };
 | 
			
		||||
                let mut new_image = ColorImage::clone(image);
 | 
			
		||||
                new_image[coords] = Color32::from_gray(shade);
 | 
			
		||||
                *self = Self::Changed(new_image);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -59,7 +60,7 @@ impl VramImage {
 | 
			
		|||
            Self::Unchanged(_) => None,
 | 
			
		||||
            Self::Changed(image) => {
 | 
			
		||||
                let arced = Arc::new(std::mem::take(image));
 | 
			
		||||
                *self = Self::Unchanged(arced.clone());
 | 
			
		||||
                *self = Self::Unchanged(Some(arced.clone()));
 | 
			
		||||
                Some(arced)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -81,6 +82,7 @@ pub struct VramTextureLoader<T: VramImageLoader> {
 | 
			
		|||
    id: String,
 | 
			
		||||
    loader: Mutex<T>,
 | 
			
		||||
    cache: Mutex<HashMap<T::Resource, (TextureHandle, VramImage)>>,
 | 
			
		||||
    seen: Mutex<HashSet<T::Resource>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: VramImageLoader> VramTextureLoader<T> {
 | 
			
		||||
| 
						 | 
				
			
			@ -89,8 +91,16 @@ impl<T: VramImageLoader> VramTextureLoader<T> {
 | 
			
		|||
            id: loader.id().to_string(),
 | 
			
		||||
            loader: Mutex::new(loader),
 | 
			
		||||
            cache: Mutex::new(HashMap::new()),
 | 
			
		||||
            seen: Mutex::new(HashSet::new()),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn begin_pass(&self) {
 | 
			
		||||
        let mut cache = self.cache.lock().unwrap();
 | 
			
		||||
        let mut seen = self.seen.lock().unwrap();
 | 
			
		||||
        cache.retain(|res, _| seen.contains(res));
 | 
			
		||||
        seen.clear();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: VramImageLoader> TextureLoader for VramTextureLoader<T> {
 | 
			
		||||
| 
						 | 
				
			
			@ -113,8 +123,10 @@ impl<T: VramImageLoader> TextureLoader for VramTextureLoader<T> {
 | 
			
		|||
                "Only TextureOptions::NEAREST are supported".into(),
 | 
			
		||||
            ));
 | 
			
		||||
        }
 | 
			
		||||
        let loader = self.loader.lock().unwrap();
 | 
			
		||||
        let mut cache = self.cache.lock().unwrap();
 | 
			
		||||
        let mut seen = self.seen.lock().unwrap();
 | 
			
		||||
        seen.insert(resource.clone());
 | 
			
		||||
        let loader = self.loader.lock().unwrap();
 | 
			
		||||
        let resources = cache.iter_mut().map(|(k, v)| (k, &mut v.1));
 | 
			
		||||
        loader.update(resources);
 | 
			
		||||
        for (handle, image) in cache.values_mut() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,7 +18,7 @@ use super::utils::{parse_palette, CharacterGrid, GENERIC_PALETTE};
 | 
			
		|||
 | 
			
		||||
pub struct BgMapWindow {
 | 
			
		||||
    sim_id: SimId,
 | 
			
		||||
    loader: Option<BgMapLoader>,
 | 
			
		||||
    loader: Arc<VramTextureLoader<BgMapLoader>>,
 | 
			
		||||
    bgmaps: MemoryView,
 | 
			
		||||
    cell_index: usize,
 | 
			
		||||
    cell_index_str: String,
 | 
			
		||||
| 
						 | 
				
			
			@ -31,7 +31,7 @@ impl BgMapWindow {
 | 
			
		|||
    pub fn new(sim_id: SimId, memory: &mut MemoryMonitor) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            sim_id,
 | 
			
		||||
            loader: Some(BgMapLoader::new(sim_id, memory)),
 | 
			
		||||
            loader: Arc::new(VramTextureLoader::new(BgMapLoader::new(sim_id, memory))),
 | 
			
		||||
            bgmaps: memory.view(sim_id, 0x00020000, 0x1d800),
 | 
			
		||||
            cell_index: 0,
 | 
			
		||||
            cell_index_str: "0".into(),
 | 
			
		||||
| 
						 | 
				
			
			@ -188,11 +188,11 @@ impl AppWindow for BgMapWindow {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    fn on_init(&mut self, ctx: &Context, _render_state: &egui_wgpu::RenderState) {
 | 
			
		||||
        let loader = self.loader.take().unwrap();
 | 
			
		||||
        ctx.add_texture_loader(Arc::new(VramTextureLoader::new(loader)));
 | 
			
		||||
        ctx.add_texture_loader(self.loader.clone());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn show(&mut self, ctx: &Context) {
 | 
			
		||||
        self.loader.begin_pass();
 | 
			
		||||
        CentralPanel::default().show(ctx, |ui| {
 | 
			
		||||
            ui.horizontal_top(|ui| {
 | 
			
		||||
                StripBuilder::new(ui)
 | 
			
		||||
| 
						 | 
				
			
			@ -219,7 +219,7 @@ fn parse_cell(cell: u16) -> (usize, bool, bool, usize) {
 | 
			
		|||
    (char_index, vflip, hflip, palette_index)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Hash)]
 | 
			
		||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
 | 
			
		||||
enum BgMapResource {
 | 
			
		||||
    BgMap { index: usize, generic_palette: bool },
 | 
			
		||||
    Cell { index: usize, generic_palette: bool },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -77,7 +77,7 @@ impl Display for VramPalette {
 | 
			
		|||
 | 
			
		||||
pub struct CharacterDataWindow {
 | 
			
		||||
    sim_id: SimId,
 | 
			
		||||
    loader: Option<CharDataLoader>,
 | 
			
		||||
    loader: Arc<VramTextureLoader<CharDataLoader>>,
 | 
			
		||||
    brightness: MemoryView,
 | 
			
		||||
    palettes: MemoryView,
 | 
			
		||||
    palette: VramPalette,
 | 
			
		||||
| 
						 | 
				
			
			@ -91,7 +91,7 @@ impl CharacterDataWindow {
 | 
			
		|||
    pub fn new(sim_id: SimId, memory: &mut MemoryMonitor) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            sim_id,
 | 
			
		||||
            loader: Some(CharDataLoader::new(sim_id, memory)),
 | 
			
		||||
            loader: Arc::new(VramTextureLoader::new(CharDataLoader::new(sim_id, memory))),
 | 
			
		||||
            brightness: memory.view(sim_id, 0x0005f824, 8),
 | 
			
		||||
            palettes: memory.view(sim_id, 0x0005f860, 16),
 | 
			
		||||
            palette: VramPalette::Generic,
 | 
			
		||||
| 
						 | 
				
			
			@ -250,11 +250,11 @@ impl AppWindow for CharacterDataWindow {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    fn on_init(&mut self, ctx: &Context, _render_state: &egui_wgpu::RenderState) {
 | 
			
		||||
        let loader = self.loader.take().unwrap();
 | 
			
		||||
        ctx.add_texture_loader(Arc::new(VramTextureLoader::new(loader)));
 | 
			
		||||
        ctx.add_texture_loader(self.loader.clone());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn show(&mut self, ctx: &Context) {
 | 
			
		||||
        self.loader.begin_pass();
 | 
			
		||||
        CentralPanel::default().show(ctx, |ui| {
 | 
			
		||||
            ui.horizontal_top(|ui| {
 | 
			
		||||
                StripBuilder::new(ui)
 | 
			
		||||
| 
						 | 
				
			
			@ -273,7 +273,7 @@ impl AppWindow for CharacterDataWindow {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Hash)]
 | 
			
		||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
 | 
			
		||||
enum CharDataResource {
 | 
			
		||||
    Character { palette: VramPalette, index: usize },
 | 
			
		||||
    CharacterData { palette: VramPalette },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue