simplify AssetStorage and Handles

This commit is contained in:
Carter Anderson 2020-01-11 12:32:38 -08:00
parent 41722830bd
commit 4d903df33c
11 changed files with 52 additions and 98 deletions

View File

@ -43,9 +43,9 @@ fn setup(world: &mut World) {
let cube_handle = { let cube_handle = {
let mut mesh_storage = world let mut mesh_storage = world
.resources .resources
.get_mut::<AssetStorage<Mesh, MeshType>>() .get_mut::<AssetStorage<Mesh>>()
.unwrap(); .unwrap();
mesh_storage.add(cube, "cube") mesh_storage.add(cube)
}; };
world.insert( world.insert(

View File

@ -33,11 +33,11 @@ fn setup(world: &mut World) {
let (cube_handle, plane_handle) = { let (cube_handle, plane_handle) = {
let mut mesh_storage = world let mut mesh_storage = world
.resources .resources
.get_mut::<AssetStorage<Mesh, MeshType>>() .get_mut::<AssetStorage<Mesh>>()
.unwrap(); .unwrap();
( (
mesh_storage.add(cube, "cube"), mesh_storage.add(cube),
mesh_storage.add(plane, "plane"), mesh_storage.add(plane),
) )
}; };

View File

@ -16,11 +16,11 @@ fn setup(world: &mut World) {
let (cube_handle, plane_handle) = { let (cube_handle, plane_handle) = {
let mut mesh_storage = world let mut mesh_storage = world
.resources .resources
.get_mut::<AssetStorage<Mesh, MeshType>>() .get_mut::<AssetStorage<Mesh>>()
.unwrap(); .unwrap();
( (
mesh_storage.add(cube, "cube"), mesh_storage.add(cube),
mesh_storage.add(plane, "plane"), mesh_storage.add(plane),
) )
}; };

View File

@ -14,9 +14,9 @@ fn setup(world: &mut World) {
let cube_handle = { let cube_handle = {
let mut mesh_storage = world let mut mesh_storage = world
.resources .resources
.get_mut::<AssetStorage<Mesh, MeshType>>() .get_mut::<AssetStorage<Mesh>>()
.unwrap(); .unwrap();
mesh_storage.add(cube, "cube") mesh_storage.add(cube)
}; };
world.insert( world.insert(

View File

@ -77,7 +77,7 @@ impl AppBuilder {
pub fn add_default_resources(mut self) -> Self { pub fn add_default_resources(mut self) -> Self {
let resources = &mut self.world.resources; let resources = &mut self.world.resources;
resources.insert(Time::new()); resources.insert(Time::new());
resources.insert(AssetStorage::<Mesh, MeshType>::new()); resources.insert(AssetStorage::<Mesh>::new());
self self
} }

View File

@ -2,113 +2,67 @@ mod gltf;
pub use self::gltf::load_gltf; pub use self::gltf::load_gltf;
use std::{ use std::{collections::HashMap, marker::PhantomData};
collections::HashMap,
marker::PhantomData,
ops::Drop,
sync::{Arc, RwLock},
};
pub struct Handle<T> { pub struct Handle<T> {
pub id: Arc<RwLock<usize>>, pub id: usize,
marker: PhantomData<T>, marker: PhantomData<T>,
free_indices: Arc<RwLock<Vec<usize>>>,
} }
impl<T> Clone for Handle<T> { impl<T> Clone for Handle<T> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Handle { Handle {
id: self.id.clone(), id: self.id.clone(),
free_indices: self.free_indices.clone(),
marker: PhantomData, marker: PhantomData,
} }
} }
} }
impl<T> Drop for Handle<T> {
fn drop(&mut self) {
// TODO: Maybe this should be 1
// TODO: Is this even necessary?
if Arc::strong_count(&self.id) == 0 {
let id = *self.id.read().unwrap();
self.free_indices.write().unwrap().push(id);
}
}
}
pub trait Asset<D> { pub trait Asset<D> {
fn load(descriptor: D) -> Self; fn load(descriptor: D) -> Self;
} }
pub struct AssetStorage<T, D> pub struct AssetStorage<T>
where
T: Asset<D>,
{ {
assets: Vec<Option<T>>, assets: HashMap<usize, T>,
free_indices: Arc<RwLock<Vec<usize>>>, names: HashMap<String, usize>,
names: HashMap<String, Arc<RwLock<usize>>>, current_index: usize,
marker: PhantomData<D>,
} }
impl<T, D> AssetStorage<T, D> impl<T> AssetStorage<T>
where
T: Asset<D>,
{ {
pub fn new() -> AssetStorage<T, D> { pub fn new() -> AssetStorage<T> {
AssetStorage { AssetStorage {
assets: Vec::new(), assets: HashMap::new(),
free_indices: Arc::new(RwLock::new(Vec::new())),
names: HashMap::new(), names: HashMap::new(),
marker: PhantomData, current_index: 0,
} }
} }
pub fn get_named(&self, name: &str) -> Option<Handle<T>> { pub fn get_named(&mut self, name: &str) -> Option<&mut T> {
match self.names.get(name) { match self.names.get(name) {
Some(id) => Some(Handle { Some(id) => self.assets.get_mut(id),
id: id.clone(),
marker: PhantomData,
free_indices: self.free_indices.clone(),
}),
None => None, None => None,
} }
} }
pub fn add(&mut self, asset: T, name: &str) -> Handle<T> { pub fn add(&mut self, asset: T) -> Handle<T> {
match self.free_indices.write().unwrap().pop() { let id = self.current_index;
Some(id) => { self.current_index += 1;
self.assets[id as usize] = Some(asset); self.assets.insert(id, asset);
let handle = Arc::new(RwLock::new(id));
self.names.insert(name.to_string(), handle.clone());
Handle { Handle {
id: handle, id,
marker: PhantomData, marker: PhantomData,
free_indices: self.free_indices.clone(),
}
}
None => {
self.assets.push(Some(asset));
let id = self.assets.len() - 1;
let handle = Arc::new(RwLock::new(id));
self.names.insert(name.to_string(), handle.clone());
Handle {
id: handle,
marker: PhantomData,
free_indices: self.free_indices.clone(),
}
}
} }
} }
pub fn add_named(&mut self, asset: T, name: &str) -> Handle<T> {
let handle = self.add(asset);
self.names.insert(name.to_string(), handle.id);
handle
}
pub fn get(&mut self, id: usize) -> Option<&mut T> { pub fn get(&mut self, id: usize) -> Option<&mut T> {
if id >= self.assets.len() { self.assets.get_mut(&id)
None
} else {
if let Some(ref mut asset) = self.assets[id] {
Some(asset)
} else {
None
}
}
} }
} }

View File

@ -137,13 +137,13 @@ impl Pipeline for ForwardPipeline {
let mut mesh_storage = world let mut mesh_storage = world
.resources .resources
.get_mut::<AssetStorage<Mesh, MeshType>>() .get_mut::<AssetStorage<Mesh>>()
.unwrap(); .unwrap();
let mut last_mesh_id = None; let mut last_mesh_id = None;
let mesh_query = let mesh_query =
<(Read<Material>, Read<Handle<Mesh>>)>::query().filter(!component::<Instanced>()); <(Read<Material>, Read<Handle<Mesh>>)>::query().filter(!component::<Instanced>());
for (material, mesh) in mesh_query.iter(world) { for (material, mesh) in mesh_query.iter(world) {
let current_mesh_id = *mesh.id.read().unwrap(); let current_mesh_id = mesh.id;
let mut should_load_mesh = last_mesh_id == None; let mut should_load_mesh = last_mesh_id == None;
if let Some(last) = last_mesh_id { if let Some(last) = last_mesh_id {
@ -151,14 +151,14 @@ impl Pipeline for ForwardPipeline {
} }
if should_load_mesh { if should_load_mesh {
if let Some(mesh_asset) = mesh_storage.get(*mesh.id.read().unwrap()) { if let Some(mesh_asset) = mesh_storage.get(mesh.id) {
mesh_asset.setup_buffers(&render_graph.device); mesh_asset.setup_buffers(&render_graph.device);
pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0); pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0);
pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]); pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]);
}; };
} }
if let Some(ref mesh_asset) = mesh_storage.get(*mesh.id.read().unwrap()) { if let Some(ref mesh_asset) = mesh_storage.get(mesh.id) {
pass.set_bind_group(1, material.bind_group.as_ref().unwrap(), &[]); pass.set_bind_group(1, material.bind_group.as_ref().unwrap(), &[]);
pass.draw_indexed(0..mesh_asset.indices.len() as u32, 0, 0..1); pass.draw_indexed(0..mesh_asset.indices.len() as u32, 0, 0..1);
}; };

View File

@ -52,7 +52,7 @@ impl ForwardInstancedPipeline {
.iter(world) .iter(world)
.zip(temp_buf_data.data.chunks_exact_mut(size)) .zip(temp_buf_data.data.chunks_exact_mut(size))
{ {
last_mesh_id = Some(*mesh.id.read().unwrap()); last_mesh_id = Some(mesh.id);
let (_, _, translation) = transform.0.to_scale_rotation_translation(); let (_, _, translation) = transform.0.to_scale_rotation_translation();
slot.copy_from_slice( slot.copy_from_slice(
SimpleMaterialUniforms { SimpleMaterialUniforms {
@ -89,7 +89,7 @@ impl ForwardInstancedPipeline {
let mut last_mesh_id = None; let mut last_mesh_id = None;
let mut data = Vec::with_capacity(entities_count); let mut data = Vec::with_capacity(entities_count);
for (material, transform, mesh, _) in entities.iter(world) { for (material, transform, mesh, _) in entities.iter(world) {
last_mesh_id = Some(*mesh.id.read().unwrap()); last_mesh_id = Some(mesh.id);
let (_, _, translation) = transform.0.to_scale_rotation_translation(); let (_, _, translation) = transform.0.to_scale_rotation_translation();
data.push(SimpleMaterialUniforms { data.push(SimpleMaterialUniforms {
@ -263,7 +263,7 @@ impl Pipeline for ForwardInstancedPipeline {
let mut mesh_storage = world let mut mesh_storage = world
.resources .resources
.get_mut::<AssetStorage<Mesh, MeshType>>() .get_mut::<AssetStorage<Mesh>>()
.unwrap(); .unwrap();
for instance_buffer_info in self.instance_buffer_infos.as_ref().unwrap().iter() { for instance_buffer_info in self.instance_buffer_infos.as_ref().unwrap().iter() {
if let Some(mesh_asset) = mesh_storage.get(instance_buffer_info.mesh_id) { if let Some(mesh_asset) = mesh_storage.get(instance_buffer_info.mesh_id) {

View File

@ -171,10 +171,10 @@ impl Pipeline for ForwardShadowPassNew {
let mut mesh_storage = world let mut mesh_storage = world
.resources .resources
.get_mut::<AssetStorage<Mesh, MeshType>>() .get_mut::<AssetStorage<Mesh>>()
.unwrap(); .unwrap();
for (material, mesh) in mesh_query.iter(world) { for (material, mesh) in mesh_query.iter(world) {
if let Some(mesh_asset) = mesh_storage.get(*mesh.id.read().unwrap()) { if let Some(mesh_asset) = mesh_storage.get(mesh.id) {
mesh_asset.setup_buffers(&render_graph.device); mesh_asset.setup_buffers(&render_graph.device);
pass.set_bind_group(1, material.bind_group.as_ref().unwrap(), &[]); pass.set_bind_group(1, material.bind_group.as_ref().unwrap(), &[]);
pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0); pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0);

View File

@ -159,10 +159,10 @@ impl Pipeline for ShadowPipeline {
let mut mesh_storage = world let mut mesh_storage = world
.resources .resources
.get_mut::<AssetStorage<Mesh, MeshType>>() .get_mut::<AssetStorage<Mesh>>()
.unwrap(); .unwrap();
for (material, mesh) in mesh_query.iter(world) { for (material, mesh) in mesh_query.iter(world) {
if let Some(mesh_asset) = mesh_storage.get(*mesh.id.read().unwrap()) { if let Some(mesh_asset) = mesh_storage.get(mesh.id) {
mesh_asset.setup_buffers(&render_graph.device); mesh_asset.setup_buffers(&render_graph.device);
pass.set_bind_group(1, material.bind_group.as_ref().unwrap(), &[]); pass.set_bind_group(1, material.bind_group.as_ref().unwrap(), &[]);

View File

@ -65,7 +65,7 @@ impl UiPipeline {
wgpu::BufferUsage::COPY_SRC | wgpu::BufferUsage::VERTEX, wgpu::BufferUsage::COPY_SRC | wgpu::BufferUsage::VERTEX,
); );
let mesh_id = *self.quad.as_ref().unwrap().id.read().unwrap(); let mesh_id = self.quad.as_ref().unwrap().id;
let mut instance_buffer_infos = Vec::new(); let mut instance_buffer_infos = Vec::new();
instance_buffer_infos.push(InstanceBufferInfo { instance_buffer_infos.push(InstanceBufferInfo {
@ -114,7 +114,7 @@ impl Pipeline for UiPipeline {
{ {
let mut mesh_storage = world let mut mesh_storage = world
.resources .resources
.get_mut::<AssetStorage<Mesh, MeshType>>() .get_mut::<AssetStorage<Mesh>>()
.unwrap(); .unwrap();
let quad = Mesh::load(MeshType::Quad { let quad = Mesh::load(MeshType::Quad {
@ -123,7 +123,7 @@ impl Pipeline for UiPipeline {
south_west: math::vec2(-0.5, -0.5), south_west: math::vec2(-0.5, -0.5),
south_east: math::vec2(0.5, -0.5), south_east: math::vec2(0.5, -0.5),
}); });
self.quad = Some(mesh_storage.add(quad, "ui_quad")); self.quad = Some(mesh_storage.add(quad));
} }
let pipeline_layout = let pipeline_layout =
@ -220,7 +220,7 @@ impl Pipeline for UiPipeline {
let mut mesh_storage = world let mut mesh_storage = world
.resources .resources
.get_mut::<AssetStorage<Mesh, MeshType>>() .get_mut::<AssetStorage<Mesh>>()
.unwrap(); .unwrap();
for instance_buffer_info in instance_buffer_infos.as_ref().unwrap().iter() { for instance_buffer_info in instance_buffer_infos.as_ref().unwrap().iter() {
if let Some(mesh_asset) = mesh_storage.get(instance_buffer_info.mesh_id) { if let Some(mesh_asset) = mesh_storage.get(instance_buffer_info.mesh_id) {