Use a hash map rather than an array in vram manager

This commit is contained in:
Gwilym Kuiper 2022-03-21 22:58:16 +00:00
parent 9170acb1a8
commit e6d47afa31

View file

@ -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<usize>,
tile_set_to_vram: Vec<Vec<Option<TileReference>>>,
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;
}