From e6d47afa310699f928acd7a719307e41c33e8cd2 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Mon, 21 Mar 2022 22:58:16 +0000 Subject: [PATCH] Use a hash map rather than an array in vram manager --- agb/src/display/tiled/vram_manager.rs | 28 +++++++++++++-------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/agb/src/display/tiled/vram_manager.rs b/agb/src/display/tiled/vram_manager.rs index bb93599..9db99db 100644 --- a/agb/src/display/tiled/vram_manager.rs +++ b/agb/src/display/tiled/vram_manager.rs @@ -1,12 +1,12 @@ use core::{alloc::Layout, ptr::NonNull}; -use alloc::vec; use alloc::vec::Vec; use crate::{ agb_alloc::{block_allocator::BlockAllocator, bump_allocator::StartEnd}, display::palette16, dma::dma_copy16, + hash_map::HashMap, memory_mapped::MemoryMapped1DArray, }; @@ -61,7 +61,7 @@ impl<'a> TileSet<'a> { } fn num_tiles(&self) -> usize { - self.tiles.len() / self.format.tile_size() + self.tiles.len() / self.format.tile_size() * 4 } } @@ -104,18 +104,20 @@ pub struct VRamManager<'a> { generation: u16, free_pointer: Option, - tile_set_to_vram: Vec>>, + tile_set_to_vram: HashMap<(u16, u16), TileReference>, reference_counts: Vec<(u16, Option<(TileSetReference, u16)>)>, } impl<'a> VRamManager<'a> { pub(crate) fn new() -> Self { + let tile_set_to_vram: HashMap<(u16, u16), TileReference> = HashMap::with_capacity(256); + Self { tilesets: Vec::new(), generation: 0, free_pointer: None, - tile_set_to_vram: Default::default(), + tile_set_to_vram, reference_counts: Default::default(), } } @@ -124,7 +126,6 @@ impl<'a> VRamManager<'a> { let generation = self.generation; self.generation = self.generation.wrapping_add(1); - let num_tiles = tileset.num_tiles(); let tileset = ArenaStorageItem::Data(tileset, generation); let index = if let Some(ptr) = self.free_pointer.take() { @@ -145,10 +146,6 @@ impl<'a> VRamManager<'a> { self.tilesets.len() - 1 }; - self.tile_set_to_vram - .resize(self.tilesets.len(), Default::default()); - self.tile_set_to_vram[index] = vec![Default::default(); num_tiles]; - TileSetReference::new(index as u16, generation) } @@ -185,10 +182,10 @@ impl<'a> VRamManager<'a> { } pub(crate) fn add_tile(&mut self, tile_set_ref: TileSetReference, tile: u16) -> TileIndex { - let reference = self.tile_set_to_vram[tile_set_ref.id as usize][tile as usize]; + let reference = self.tile_set_to_vram.get(&(tile_set_ref.id, tile)); if let Some(reference) = reference { - let index = Self::index_from_reference(reference); + let index = Self::index_from_reference(*reference); self.reference_counts[index].0 += 1; return TileIndex::new(index); } @@ -210,7 +207,7 @@ impl<'a> VRamManager<'a> { panic!("Tile set ref must point to existing tile set"); }; - let tile_size_in_half_words = TileFormat::FourBpp.tile_size() / 2; + let tile_size_in_half_words = tile_slice.len() / 2; unsafe { dma_copy16( @@ -224,7 +221,8 @@ impl<'a> VRamManager<'a> { let index = Self::index_from_reference(tile_reference); - self.tile_set_to_vram[tile_set_ref.id as usize][tile as usize] = Some(tile_reference); + self.tile_set_to_vram + .insert((tile_set_ref.id, tile), tile_reference); self.reference_counts .resize(self.reference_counts.len().max(index + 1), (0, None)); @@ -250,11 +248,11 @@ impl<'a> VRamManager<'a> { let tile_reference = Self::reference_from_index(tile_index); unsafe { - TILE_ALLOCATOR.dealloc(tile_reference.0.cast().as_ptr(), TILE_LAYOUT); + TILE_ALLOCATOR.dealloc_no_normalise(tile_reference.0.cast().as_ptr(), TILE_LAYOUT); } let tile_ref = self.reference_counts[index].1.unwrap(); - self.tile_set_to_vram[tile_ref.0.id as usize][tile_ref.1 as usize] = None; + self.tile_set_to_vram.remove(&(tile_ref.0.id, tile_ref.1)); self.reference_counts[index].1 = None; }