From 0ed14f548e7eb457b69480d008eefb6f1e77dd94 Mon Sep 17 00:00:00 2001 From: Matt Kleinschafer Date: Thu, 11 Apr 2024 08:58:23 +1000 Subject: [PATCH] Tidy up --- common/src/collections/arena.rs | 237 ++++++++++++++++---------------- samples/flappy-bird/src/main.rs | 5 +- 2 files changed, 119 insertions(+), 123 deletions(-) diff --git a/common/src/collections/arena.rs b/common/src/collections/arena.rs index 9232f755..1a4d92d9 100644 --- a/common/src/collections/arena.rs +++ b/common/src/collections/arena.rs @@ -1,6 +1,6 @@ -use crate::unsafe_mutable_alias; +use std::mem::replace; -// TODO: implement a free list and next_free option on the arena +use crate::unsafe_mutable_alias; /// Represents a safe index into an [`Arena`]. /// @@ -21,80 +21,6 @@ pub trait ArenaIndex { fn ordinal(&self) -> u32; } -/// Creates a new, opaque arena index type. -/// -/// The type is implicitly convertible to and from [`u64`], [`u32`], and -/// [`ArenaIndex`], and can be used as a key in the [`Arena`] structure. -#[macro_export] -macro_rules! impl_arena_index { - ($name:ident) => { - $crate::impl_arena_index!($name, ""); - }; - ($name:ident, $comment:literal) => { - #[doc = $comment] - #[repr(transparent)] - #[derive(Default, Copy, Clone, Debug, Eq, PartialEq, Hash)] - pub struct $name(u64); - - impl $name { - /// A sentinel value representing an empty index. - pub const NONE: Self = Self(0); - } - - impl $crate::ArenaIndex for $name { - #[inline(always)] - fn from_parts(ordinal: u32, generation: u32) -> Self { - Self((ordinal as u64) | ((generation as u64) << 32)) - } - - #[inline(always)] - fn generation(&self) -> u32 { - (self.0 >> 32) as u32 - } - - #[inline(always)] - fn ordinal(&self) -> u32 { - self.0 as u32 - } - } - - impl From for $name { - #[inline] - fn from(value: u32) -> Self { - ::from_parts(value, 0) - } - } - - impl From<$name> for u32 { - #[inline(always)] - fn from(value: $name) -> Self { - value.0 as u32 - } - } - - impl From for $name { - #[inline(always)] - fn from(packed: u64) -> Self { - Self(packed) - } - } - - impl From<$name> for u64 { - #[inline(always)] - fn from(value: $name) -> Self { - value.0 - } - } - - impl $crate::FromRandom for $name { - #[inline] - fn from_random(random: &mut $crate::Random) -> Self { - Self::from(random.next_u64()) - } - } - }; -} - /// A simple generational arena of elements of type [`T`] . /// /// An arena exposes safe externalized indices in the form of [`ArenaIndex`]es @@ -102,12 +28,12 @@ macro_rules! impl_arena_index { /// /// An arena is a contiguous block of memory that is used to store a collection /// of elements. When an element is removed from the arena, the slot that it -/// occupied remains empty until the next insert.. This means that the order of +/// occupied remains empty until the next insert. This means that the order of /// elements in the arena is not guaranteed to be the same as the order in which /// they were inserted. #[derive(Debug)] pub struct Arena { - entries: Vec>>, + entries: Vec>, current_generation: u32, is_generation_dirty: bool, _key: std::marker::PhantomData, @@ -115,9 +41,9 @@ pub struct Arena { /// A single entry in an `Arena`. #[derive(Debug)] -struct ArenaEntry { - value: V, - generation: u32, +enum ArenaEntry { + Vacant, + Occupied { value: T, generation: u32 }, } impl Default for Arena { @@ -157,7 +83,7 @@ impl Arena { let mut count = 0; for entry in &self.entries { - if entry.is_some() { + if matches!(entry, ArenaEntry::Occupied { .. }) { count += 1; } } @@ -172,18 +98,16 @@ impl Arena { /// Returns a reference to the item at the given index. pub fn get(&self, key: K) -> Option<&V> { - let ordinal = key.ordinal(); - let generation = key.generation(); - // sanity check external index + let ordinal = key.ordinal(); if ordinal as usize >= self.entries.len() { return None; } // if this entry exists and the generation matches - if let Some(Some(entry)) = self.entries.get(ordinal as usize) { - if entry.generation == generation { - return Some(&entry.value); + if let Some(ArenaEntry::Occupied { value, generation }) = self.entries.get(ordinal as usize) { + if *generation == key.generation() { + return Some(value); } } @@ -192,56 +116,53 @@ impl Arena { /// Returns a mutable reference to the item at the given index. pub fn get_mut(&mut self, key: K) -> Option<&mut V> { - let ordinal = key.ordinal(); - let generation = key.generation(); - // sanity check external index + let ordinal = key.ordinal(); if ordinal as usize >= self.entries.len() { return None; } // if this entry exists and the generation matches - if let Some(Some(entry)) = self.entries.get_mut(ordinal as usize) { - if entry.generation == generation { - return Some(&mut entry.value); + if let Some(ArenaEntry::Occupied { value, generation }) = self.entries.get_mut(ordinal as usize) { + if *generation == key.generation() { + return Some(value); } } None } - /// Inserts an entry to the arena and returns it's index. + /// Inserts an entry to the arena and returns its index. pub fn insert(&mut self, value: V) -> K { let key = self.allocate_key(); let ordinal = key.ordinal(); let generation = key.generation(); - self.entries[ordinal as usize] = Some(ArenaEntry { - value, - generation: generation, - }); + self.entries[ordinal as usize] = ArenaEntry::Occupied { value, generation }; key } /// Removes an item from the arena. pub fn remove(&mut self, key: K) -> Option { - let ordinal = key.ordinal(); - let generation = key.generation(); - // sanity check external index + let ordinal = key.ordinal(); if ordinal as usize >= self.entries.len() { return None; } // if this is the relevant entry and the generation matches - if let Some(entry) = &self.entries[ordinal as usize] { - if generation == entry.generation { - let entry = self.entries[ordinal as usize].take().unwrap(); - self.is_generation_dirty = true; + if let ArenaEntry::Occupied { generation, .. } = &self.entries[ordinal as usize] { + if *generation == key.generation() { + let dest = &mut self.entries[ordinal as usize]; + let entry = replace(dest, ArenaEntry::Vacant); + + if let ArenaEntry::Occupied { value, .. } = entry { + self.is_generation_dirty = true; - return Some(entry.value); + return Some(value); + } } } @@ -266,10 +187,10 @@ impl Arena { fn next(&mut self) -> Option { while let Some(entry) = self.arena.entries.get(self.index) { - if let Some(value) = entry { + if let ArenaEntry::Occupied { value, .. } = entry { self.index += 1; - return Some(&value.value); + return Some(value); } self.index += 1; @@ -299,12 +220,10 @@ impl Arena { fn next(&mut self) -> Option { while let Some(entry) = self.arena.entries.get_mut(self.index) { - if let Some(value) = entry.as_mut() { + if let ArenaEntry::Occupied { value, .. } = entry { self.index += 1; - let value = unsafe { unsafe_mutable_alias(value) }; // elide the lifetime - - return Some(&mut value.value); + return Some(unsafe { unsafe_mutable_alias(value) }); } self.index += 1; @@ -334,12 +253,12 @@ impl Arena { fn next(&mut self) -> Option { while let Some(entry) = self.arena.entries.get(self.index) { - if let Some(value) = entry { - let key = K::from_parts(self.index as u32, value.generation); + if let ArenaEntry::Occupied { value, generation } = entry { + let key = K::from_parts(self.index as u32, *generation); self.index += 1; - return Some((key, &value.value)); + return Some((key, &value)); } self.index += 1; @@ -369,13 +288,13 @@ impl Arena { fn next(&mut self) -> Option { while let Some(entry) = self.arena.entries.get_mut(self.index) { - if let Some(value) = entry.as_mut() { - let key = K::from_parts(self.index as u32, value.generation); + if let ArenaEntry::Occupied { value, generation } = entry { + let key = K::from_parts(self.index as u32, *generation); let value = unsafe { unsafe_mutable_alias(value) }; // elide the lifetime self.index += 1; - return Some((key, &mut value.value)); + return Some((key, value)); } self.index += 1; @@ -403,13 +322,13 @@ impl Arena { // scan through existing entries and find an empty slot for index in 0..self.entries.len() { - if self.entries[index].is_none() { + if matches!(self.entries[index], ArenaEntry::Vacant { .. }) { return K::from_parts(index as u32, self.current_generation); } } - // otherwise allocate a new entry - self.entries.push(None); + // otherwise allocate a new empty entry + self.entries.push(ArenaEntry::Vacant); K::from_parts((self.entries.len() - 1) as u32, self.current_generation) } @@ -448,6 +367,80 @@ impl FromIterator for Arena { } } +/// Creates a new, opaque arena index type. +/// +/// The type is implicitly convertible to and from [`u64`], [`u32`], and +/// [`ArenaIndex`], and can be used as a key in the [`Arena`] structure. +#[macro_export] +macro_rules! impl_arena_index { + ($name:ident) => { + $crate::impl_arena_index!($name, ""); + }; + ($name:ident, $comment:literal) => { + #[doc = $comment] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Debug, Eq, PartialEq, Hash)] + pub struct $name(u64); + + impl $name { + /// A sentinel value representing an empty index. + pub const NONE: Self = Self(0); + } + + impl $crate::ArenaIndex for $name { + #[inline(always)] + fn from_parts(ordinal: u32, generation: u32) -> Self { + Self((ordinal as u64) | ((generation as u64) << 32)) + } + + #[inline(always)] + fn generation(&self) -> u32 { + (self.0 >> 32) as u32 + } + + #[inline(always)] + fn ordinal(&self) -> u32 { + self.0 as u32 + } + } + + impl From for $name { + #[inline] + fn from(value: u32) -> Self { + ::from_parts(value, 0) + } + } + + impl From<$name> for u32 { + #[inline(always)] + fn from(value: $name) -> Self { + value.0 as u32 + } + } + + impl From for $name { + #[inline(always)] + fn from(packed: u64) -> Self { + Self(packed) + } + } + + impl From<$name> for u64 { + #[inline(always)] + fn from(value: $name) -> Self { + value.0 + } + } + + impl $crate::FromRandom for $name { + #[inline] + fn from_random(random: &mut $crate::Random) -> Self { + Self::from(random.next_u64()) + } + } + }; +} + #[cfg(test)] mod tests { use super::*; diff --git a/samples/flappy-bird/src/main.rs b/samples/flappy-bird/src/main.rs index 8d5df11f..6a45e792 100644 --- a/samples/flappy-bird/src/main.rs +++ b/samples/flappy-bird/src/main.rs @@ -27,7 +27,10 @@ fn main() { let mut queue = RenderQueue::new(); let mut game = Game::new(&graphics); - material.set_uniform("u_projectionView", Mat4::IDENTITY); + material.set_uniform( + "u_projectionView", + Mat4::orthographic_rh_gl(0.0, 800.0, 0.0, 600.0, -1.0, 1.0), + ); game.initialize();