Skip to content

Commit

Permalink
Make loader Send and Sync
Browse files Browse the repository at this point in the history
This is a requirement for loading entities and maps asynchronously without blocking the main render thread.
  • Loading branch information
hasenbanck committed Dec 31, 2024
1 parent 1c9394d commit 52ddb26
Show file tree
Hide file tree
Showing 12 changed files with 132 additions and 104 deletions.
2 changes: 1 addition & 1 deletion korangar/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ korangar_interface = { workspace = true, features = ["serde", "cgmath"] }
korangar_networking = { workspace = true, features = ["debug"] }
korangar_util = { workspace = true, features = ["interface"] }
lunify = { workspace = true }
mlua = { workspace = true, features = ["lua51", "vendored"] }
mlua = { workspace = true, features = ["lua51", "send", "vendored"] }
num = { workspace = true }
option-ext = { workspace = true }
pollster = { workspace = true }
Expand Down
2 changes: 1 addition & 1 deletion korangar/src/interface/cursor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub struct MouseCursor {
}

impl MouseCursor {
pub fn new(sprite_loader: &mut SpriteLoader, action_loader: &mut ActionLoader) -> Self {
pub fn new(sprite_loader: &SpriteLoader, action_loader: &ActionLoader) -> Self {
let sprite = sprite_loader.get("cursors.spr").unwrap();
let actions = action_loader.get("cursors.act").unwrap();
let animation_state = SpriteAnimationState::new(ClientTick(0));
Expand Down
4 changes: 2 additions & 2 deletions korangar/src/inventory/skills.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ pub struct SkillTree {
impl SkillTree {
pub fn fill(
&mut self,
sprite_loader: &mut SpriteLoader,
action_loader: &mut ActionLoader,
sprite_loader: &SpriteLoader,
action_loader: &ActionLoader,
skill_data: Vec<SkillInformation>,
client_tick: ClientTick,
) {
Expand Down
23 changes: 14 additions & 9 deletions korangar/src/loaders/action/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::num::{NonZeroU32, NonZeroUsize};
use std::sync::Arc;
use std::sync::{Arc, Mutex};

use korangar_audio::AudioEngine;
#[cfg(feature = "debug")]
Expand All @@ -20,22 +20,22 @@ const MAX_CACHE_SIZE: usize = 64 * 1024 * 1024;
pub struct ActionLoader {
game_file_loader: Arc<GameFileLoader>,
audio_engine: Arc<AudioEngine<GameFileLoader>>,
cache: SimpleCache<String, Arc<Actions>>,
cache: Mutex<SimpleCache<String, Arc<Actions>>>,
}

impl ActionLoader {
pub fn new(game_file_loader: Arc<GameFileLoader>, audio_engine: Arc<AudioEngine<GameFileLoader>>) -> Self {
Self {
game_file_loader,
audio_engine,
cache: SimpleCache::new(
cache: Mutex::new(SimpleCache::new(
NonZeroU32::new(MAX_CACHE_COUNT).unwrap(),
NonZeroUsize::new(MAX_CACHE_SIZE).unwrap(),
),
)),
}
}

fn load(&mut self, path: &str) -> Result<Arc<Actions>, LoadError> {
fn load(&self, path: &str) -> Result<Arc<Actions>, LoadError> {
#[cfg(feature = "debug")]
let timer = Timer::new_dynamic(format!("load actions from {}", path.magenta()));

Expand Down Expand Up @@ -99,18 +99,23 @@ impl ActionLoader {
actions_data: saved_actions_data,
});

self.cache.insert(path.to_string(), sprite.clone()).unwrap();
self.cache.lock().unwrap().insert(path.to_string(), sprite.clone()).unwrap();

#[cfg(feature = "debug")]
timer.stop();

Ok(sprite)
}

pub fn get(&mut self, path: &str) -> Result<Arc<Actions>, LoadError> {
match self.cache.get(path) {
pub fn get(&self, path: &str) -> Result<Arc<Actions>, LoadError> {
let mut lock = self.cache.lock().unwrap();
match lock.get(path) {
Some(sprite) => Ok(sprite.clone()),
None => self.load(path),
None => {
// We need to drop to avoid a deadlock here.
drop(lock);
self.load(path)
}
}
}
}
35 changes: 22 additions & 13 deletions korangar/src/loaders/animation/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::cmp::{max, min};
use std::num::{NonZeroU32, NonZeroUsize};
use std::sync::Arc;
use std::sync::{Arc, Mutex};

#[cfg(feature = "debug")]
use cgmath::SquareMatrix;
Expand All @@ -17,23 +17,23 @@ const MAX_CACHE_COUNT: u32 = 256;
const MAX_CACHE_SIZE: usize = 64 * 1024 * 1024;

pub struct AnimationLoader {
cache: SimpleCache<Vec<String>, Arc<AnimationData>>,
cache: Mutex<SimpleCache<Vec<String>, Arc<AnimationData>>>,
}

impl AnimationLoader {
pub fn new() -> Self {
Self {
cache: SimpleCache::new(
cache: Mutex::new(SimpleCache::new(
NonZeroU32::new(MAX_CACHE_COUNT).unwrap(),
NonZeroUsize::new(MAX_CACHE_SIZE).unwrap(),
),
)),
}
}

pub fn load(
&mut self,
sprite_loader: &mut SpriteLoader,
action_loader: &mut ActionLoader,
&self,
sprite_loader: &SpriteLoader,
action_loader: &ActionLoader,
entity_type: EntityType,
entity_part_files: &[String],
) -> Result<Arc<AnimationData>, LoadError> {
Expand Down Expand Up @@ -301,21 +301,30 @@ impl AnimationLoader {
entity_type,
});

self.cache.insert(entity_part_files.to_vec(), animation_data.clone()).unwrap();
self.cache
.lock()
.unwrap()
.insert(entity_part_files.to_vec(), animation_data.clone())
.unwrap();

Ok(animation_data)
}

pub fn get(
&mut self,
sprite_loader: &mut SpriteLoader,
action_loader: &mut ActionLoader,
&self,
sprite_loader: &SpriteLoader,
action_loader: &ActionLoader,
entity_type: EntityType,
entity_part_files: &[String],
) -> Result<Arc<AnimationData>, LoadError> {
match self.cache.get(entity_part_files) {
let mut lock = self.cache.lock().unwrap();
match lock.get(entity_part_files) {
Some(animation_data) => Ok(animation_data.clone()),
None => self.load(sprite_loader, action_loader, entity_type, entity_part_files),
None => {
// We need to drop to avoid a deadlock here.
drop(lock);
self.load(sprite_loader, action_loader, entity_type, entity_part_files)
}
}
}
}
Expand Down
23 changes: 14 additions & 9 deletions korangar/src/loaders/effect/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::num::{NonZeroU32, NonZeroUsize};
use std::sync::Arc;
use std::sync::{Arc, Mutex};

use cgmath::Deg;
#[cfg(feature = "debug")]
Expand All @@ -22,21 +22,21 @@ const MAX_CACHE_SIZE: usize = 64 * 1024 * 1024;

pub struct EffectLoader {
game_file_loader: Arc<GameFileLoader>,
cache: SimpleCache<String, Arc<Effect>>,
cache: Mutex<SimpleCache<String, Arc<Effect>>>,
}

impl EffectLoader {
pub fn new(game_file_loader: Arc<GameFileLoader>) -> Self {
Self {
game_file_loader,
cache: SimpleCache::new(
cache: Mutex::new(SimpleCache::new(
NonZeroU32::new(MAX_CACHE_COUNT).unwrap(),
NonZeroUsize::new(MAX_CACHE_SIZE).unwrap(),
),
)),
}
}

fn load(&mut self, path: &str, texture_loader: &TextureLoader) -> Result<Arc<Effect>, LoadError> {
fn load(&self, path: &str, texture_loader: &TextureLoader) -> Result<Arc<Effect>, LoadError> {
#[cfg(feature = "debug")]
let timer = Timer::new_dynamic(format!("load effect from {}", path.magenta()));

Expand Down Expand Up @@ -148,18 +148,23 @@ impl EffectLoader {
.collect(),
));

self.cache.insert(path.to_string(), effect.clone()).unwrap();
self.cache.lock().unwrap().insert(path.to_string(), effect.clone()).unwrap();

#[cfg(feature = "debug")]
timer.stop();

Ok(effect)
}

pub fn get(&mut self, path: &str, texture_loader: &TextureLoader) -> Result<Arc<Effect>, LoadError> {
match self.cache.get(path) {
pub fn get(&self, path: &str, texture_loader: &TextureLoader) -> Result<Arc<Effect>, LoadError> {
let mut lock = self.cache.lock().unwrap();
match lock.get(path) {
Some(effect) => Ok(effect.clone()),
None => self.load(path, texture_loader),
None => {
// We need to drop to avoid a deadlock here.
drop(lock);
self.load(path, texture_loader)
}
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions korangar/src/loaders/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ pub struct MapLoader {

impl MapLoader {
pub fn load(
&mut self,
&self,
resource_file: String,
model_loader: &mut ModelLoader,
model_loader: &ModelLoader,
texture_loader: Arc<TextureLoader>,
#[cfg(feature = "debug")] tile_texture_mapping: &[AtlasAllocation],
) -> Result<Map, LoadError> {
Expand Down Expand Up @@ -236,7 +236,7 @@ impl MapLoader {
}

fn generate_vertex_buffer_and_atlas_texture(
&mut self,
&self,
resource_file: &str,
mut texture_atlas_factory: TextureAtlasFactory,
mut deferred_vertex_generation: Vec<DeferredVertexGeneration>,
Expand Down
2 changes: 1 addition & 1 deletion korangar/src/loaders/model/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ impl ModelLoader {
}

pub fn load(
&mut self,
&self,
texture_atlas_factory: &mut TextureAtlasFactory,
vertex_offset: &mut usize,
model_file: &str,
Expand Down
23 changes: 14 additions & 9 deletions korangar/src/loaders/sprite/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::num::{NonZeroU32, NonZeroUsize};
use std::sync::Arc;
use std::sync::{Arc, Mutex};

use image::RgbaImage;
#[cfg(feature = "debug")]
Expand Down Expand Up @@ -40,7 +40,7 @@ pub struct SpriteLoader {
device: Arc<Device>,
queue: Arc<Queue>,
game_file_loader: Arc<GameFileLoader>,
cache: SimpleCache<String, Arc<Sprite>>,
cache: Mutex<SimpleCache<String, Arc<Sprite>>>,
}

impl SpriteLoader {
Expand All @@ -49,14 +49,14 @@ impl SpriteLoader {
device,
queue,
game_file_loader,
cache: SimpleCache::new(
cache: Mutex::new(SimpleCache::new(
NonZeroU32::new(MAX_CACHE_COUNT).unwrap(),
NonZeroUsize::new(MAX_CACHE_SIZE).unwrap(),
),
)),
}
}

fn load(&mut self, path: &str) -> Result<Arc<Sprite>, LoadError> {
fn load(&self, path: &str) -> Result<Arc<Sprite>, LoadError> {
#[cfg(feature = "debug")]
let timer = Timer::new_dynamic(format!("load sprite from {}", path.magenta()));

Expand Down Expand Up @@ -183,18 +183,23 @@ impl SpriteLoader {
#[cfg(feature = "debug")]
sprite_data: cloned_sprite_data,
});
let _ = self.cache.insert(path.to_string(), sprite.clone());
let _ = self.cache.lock().unwrap().insert(path.to_string(), sprite.clone());

#[cfg(feature = "debug")]
timer.stop();

Ok(sprite)
}

pub fn get(&mut self, path: &str) -> Result<Arc<Sprite>, LoadError> {
match self.cache.get(path) {
pub fn get(&self, path: &str) -> Result<Arc<Sprite>, LoadError> {
let mut lock = self.cache.lock().unwrap();
match lock.get(path) {
Some(sprite) => Ok(sprite.clone()),
None => self.load(path),
None => {
// We need to drop to avoid a deadlock here.
drop(lock);
self.load(path)
}
}
}
}
4 changes: 2 additions & 2 deletions korangar/src/loaders/texture/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,8 +346,8 @@ impl TextureLoader {
}

pub fn get(&self, path: &str, image_type: ImageType) -> Result<Arc<Texture>, LoadError> {
let mut lock = self.cache.lock();
match lock.as_mut().unwrap().get(&(path.into(), image_type)) {
let mut lock = self.cache.lock().unwrap();
match lock.get(&(path.into(), image_type)) {
Some(texture) => Ok(texture.clone()),
None => {
// We need to drop to avoid a deadlock here.
Expand Down
Loading

0 comments on commit 52ddb26

Please sign in to comment.