Skip to content

Commit 37ac9a3

Browse files
authored
Include an unused list of DynamicTile16 useful for reducing vram usage (#1136)
We don't free vram until after vblank, so if we end up generating a bunch of unused DynamicTiles, then even though we're going to free them eventually, it's best to not use too much as it'll limit the amount of rendering we can do in one go. After: <img width="290" height="180" alt="image" src="https://github.com/user-attachments/assets/761f752c-fdb1-4a77-a960-e65c75d2ef5d" /> Before: <img width="290" height="180" alt="image" src="https://github.com/user-attachments/assets/6be10151-2bfb-4565-9870-5094816aeece" /> The actual number of used tiles is the same, but now we're using fewer while doing the actual rendering. - [x] no changelog update needed
2 parents 787a8de + 0ed9e17 commit 37ac9a3

1 file changed

Lines changed: 32 additions & 7 deletions

File tree

examples/dynamic-isometric/src/isometric_render.rs

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ use agb::{
6565
hash_map::{HashMap, HashSet},
6666
};
6767
use alloc::{rc::Rc, vec::Vec};
68-
use core::{array, hash::Hash, ops::Deref};
68+
use core::{hash::Hash, ops::Deref};
6969

7070
use crate::tiles;
7171

@@ -88,11 +88,23 @@ pub enum TileType {
8888
pub struct TileCache {
8989
cache: HashMap<TileSpec, [TileHolder; 2]>,
9090
tiles: HashSet<TileHolder>,
91+
/// We hold on to `unused` tiles here which are ones we rendered onto but then didn't end up
92+
/// needing because they are already in the cache. Because dynamic tiles keep using vram until
93+
/// the next vblank, we end up using more vram then actually necessary. So if we don't actually
94+
/// use the tile, we put it here and then render the next one on it. This doesn't reduce the size
95+
/// of the `tiles` cache, but it _does_ reduce the amount of vram we're wasting between vblank.
96+
unused: Vec<DynamicTile16>,
9197
}
9298

9399
#[derive(Clone)]
94100
pub struct TileHolder(Rc<DynamicTile16>);
95101

102+
impl TileHolder {
103+
fn into_inner(self) -> Option<DynamicTile16> {
104+
Rc::into_inner(self.0)
105+
}
106+
}
107+
96108
impl Hash for TileHolder {
97109
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
98110
self.0.data().hash(state);
@@ -138,11 +150,20 @@ impl TileCache {
138150
let tile_spec = map.get_from_gba_tile(gba_tile_pos.x, gba_tile_pos.y);
139151

140152
self.cache.entry(tile_spec).or_insert_with(|| {
141-
let genned_tiles = build_combined_tile(tile_spec);
153+
let render_targets = [
154+
self.unused.pop().unwrap_or_default(),
155+
self.unused.pop().unwrap_or_default(),
156+
];
157+
158+
let genned_tiles = build_combined_tile(tile_spec, render_targets);
142159

143160
genned_tiles.map(|genned_tile| {
144161
let tile_holder = TileHolder(Rc::new(genned_tile));
145162
if let Some(existing_tile) = self.tiles.get(&tile_holder) {
163+
if let Some(unwrapped_tile) = tile_holder.into_inner() {
164+
self.unused.push(unwrapped_tile);
165+
}
166+
146167
existing_tile.clone()
147168
} else {
148169
self.tiles.insert(tile_holder.clone());
@@ -157,7 +178,10 @@ impl TileCache {
157178
}
158179
}
159180

160-
fn build_combined_tile(tile_spec: TileSpec) -> [DynamicTile16; 2] {
181+
fn build_combined_tile(
182+
tile_spec: TileSpec,
183+
render_targets: [DynamicTile16; 2],
184+
) -> [DynamicTile16; 2] {
161185
let TileSpec {
162186
quadrant,
163187
me,
@@ -209,14 +233,13 @@ fn build_combined_tile(tile_spec: TileSpec) -> [DynamicTile16; 2] {
209233
}
210234
};
211235

212-
array::from_fn(|i| {
213-
let i = i as u16;
214-
236+
let mut i = 0;
237+
render_targets.map(|tile| {
215238
fn get_tile(offset: u16) -> &'static [u32] {
216239
tiles::ISOMETRIC.tiles.get_tile_data(offset)
217240
}
218241

219-
let mut tile = DynamicTile16::new().fill_with(0);
242+
let mut tile = tile.fill_with(0);
220243

221244
let me_tile = get_tile(get_tile_id(quadrant.offset(), me, false) + i);
222245
let them_tile = get_tile(get_tile_id(quadrant.reverse().offset(), them, false) + i);
@@ -240,6 +263,8 @@ fn build_combined_tile(tile_spec: TileSpec) -> [DynamicTile16; 2] {
240263
blit_16_colour(tile.data_mut(), first);
241264
blit_16_colour(tile.data_mut(), second);
242265

266+
i += 1;
267+
243268
tile
244269
})
245270
}

0 commit comments

Comments
 (0)