#Asset caching ?!

7 messages · Page 1 of 1 (latest)

tawny trout
#

Hello, i noticed that my code creates the same Images, Materials, Meshes, ... on over and over again. So i tried to find ways around this issue.

I have now prototyped a 'MaterialRegistry'' that i can add as resource and use as 'ResMut<MaterialRegistry>' in my systems.
But it could be the wrong way, maybe i bevy supports some kind of Systems that have access to data, without relying on locks and statics.
The prototype was now just created for StandardMaterial, but if i am on the correct track, i will code a more general solution:

pub struct MaterialRegistry {
  current_handles: HashMap<usize, Handle<StandardMaterial>>
}

/// MaterialRegistry can store often used materials by indexing it by a `create` function that creates the materials one time
/// and returns the stored material on subsequent calls, see function get_or_create
impl MaterialRegistry {
  
  pub fn new() -> Self {
    MaterialRegistry{ current_handles: HashMap::new() }
  }


  /// creates material created by create function and returns stored Material Handle in subsequent calls.
  pub fn get_or_create(&mut self, assets: &mut ResMut<Assets<StandardMaterial>>, create: fn(&mut ResMut<Assets<StandardMaterial>>) -> Handle<StandardMaterial>) -> Handle<StandardMaterial> {

    let address = create as usize;
    info!("material at: {}", address);

    if let Some(result) = self.current_handles.get(&address) {
      return result.as_weak(); // not sure if i should return as_weak() here or just a clone ?
    } else {
      let mut handle = create(assets);
      handle.make_strong(assets);
      let result = handle.as_weak(); // not sure if i should return as_weak() here or just a clone ?
      self.current_handles.insert(address, handle);
      return result;
    }
  }
}
#

usage:

fn get_red_color(materials: &mut ResMut<Assets<StandardMaterial>>) -> Handle<StandardMaterial> {
    get_color_material(materials, Color::RED)
}


pub fn spawn_enemy(
    meshes: &mut ResMut<Assets<Mesh>>,
    materials: &mut ResMut<Assets<StandardMaterial>>,
    material_pool: &mut ResMut<MaterialRegistry>,
    commands: &mut Commands,
) {
...
  // the function pointer identifies the material, the 'get_red_color' function is only called once.
  let material = material_pool.get_or_create(materials, get_red_color);
...

}

wraith widget
#

so it's basically just lazy initialisation?

#

could just create the material once, store the handle in a resource

pub struct EnemyMaterial(Handle<StandardMaterial>);```
#

and grab that when needed

tawny trout
#

sounds like a neat solution as well, so basicaly the systems can drop:
materials: &mut ResMut<Assets<StandardMaterial>>
and would have a
enemy_material: &Res<EnemyMaterial>
probably would even result into a larger degree of parallelisation of running systems - afaik

wraith widget
#

and it removes the need to check "have I already created this yet or not?" every time you try to get the material