From 3922c76efe69d1051a46edc3dac883bdb0205f1b Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Mon, 2 Dec 2019 10:48:08 -0800 Subject: [PATCH] fix asset loading. no more temp! --- examples/simple.rs | 39 ++++++++++++++++-- src/application.rs | 12 +++--- src/asset/mod.rs | 29 +++++++++----- .../src/local_to_world_system.rs | 1 + src/lib.rs | 1 - src/render/camera.rs | 4 -- src/render/forward/mod.rs | 6 +-- src/render/material.rs | 21 ++++++++++ src/render/mesh.rs | 2 +- src/render/mod.rs | 9 ++--- src/render/shadow/mod.rs | 6 +-- src/temp.rs | 40 ------------------- tiny-town/README.md | 5 ++- tiny-town/src/main.rs | 26 +++++++++++- 14 files changed, 121 insertions(+), 80 deletions(-) create mode 100644 src/render/material.rs delete mode 100644 src/temp.rs diff --git a/examples/simple.rs b/examples/simple.rs index e099f9bcc8..4d6fb0d513 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -1,9 +1,40 @@ -use bevy::{Application}; -use legion::prelude::*; +use bevy::*; +use bevy::{render::*, asset::{Asset, AssetStorage}, math}; fn main() { - // Create a world to store our entities let universe = Universe::new(); let mut world = universe.create_world(); + // Create a query which finds all `Position` and `Velocity` components + // let mut query = Read::::query(); + let cube = Mesh::load(MeshType::Cube); + let plane = Mesh::load(MeshType::Plane{ size: 10 }); + let mut mesh_storage = AssetStorage::::new(); + + // this currently breaks because Arcs cant be modified after they are cloned :( + let mesh_handle = mesh_storage.add(cube); + let plane_handle = mesh_storage.add(plane); + world.resources.insert(mesh_storage); + + world.insert((), vec![ + ( + Material { color: math::vec4(0.1, 0.6, 0.1, 1.0), bind_group: None, uniform_buf: None }, + plane_handle.clone(), + LocalToWorld(math::translation(&math::vec3(0.0, 0.0, 0.0))), + Translation::new(0.0, 0.0, 0.0) + ), + ( + Material { color: math::vec4(0.1, 0.1, 0.6, 1.0), bind_group: None, uniform_buf: None }, + mesh_handle.clone(), + LocalToWorld(math::translation(&math::vec3(3.0, 0.0, 0.0))), + Translation::new(0.0, 0.0, 0.0) + ), + ( + Material { color: math::vec4(0.6, 0.1, 0.1, 1.0), bind_group: None, uniform_buf: None }, + mesh_handle, + LocalToWorld::identity(), + Translation::new(0.0, 0.0, 0.0) + ), + ]); + Application::run(universe, world); -} +} \ No newline at end of file diff --git a/src/application.rs b/src/application.rs index fd74b0d9a7..bd9a7c23d5 100644 --- a/src/application.rs +++ b/src/application.rs @@ -10,7 +10,7 @@ use legion::prelude::*; use std::sync::Arc; use std::mem; -use crate::{temp::*, vertex::*, render::*, math, LocalToWorld, Translation, ApplicationStage}; +use crate::{vertex::*, render::*, math, LocalToWorld, ApplicationStage}; pub struct Application { @@ -45,9 +45,9 @@ impl Application { }); - let mut entities = >::query(); + let mut entities = >::query(); for mut entity in entities.iter(&mut world) { - let entity_uniform_size = mem::size_of::() as wgpu::BufferAddress; + let entity_uniform_size = mem::size_of::() as wgpu::BufferAddress; let uniform_buf = device.create_buffer(&wgpu::BufferDescriptor { size: entity_uniform_size, usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, @@ -204,9 +204,9 @@ impl Application { device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }); { - let mut entities = <(Read, Read)>::query(); + let mut entities = <(Read, Read)>::query(); let entities_count = entities.iter(&mut self.world).count(); - let size = mem::size_of::(); + let size = mem::size_of::(); let temp_buf_data = device .create_buffer_mapped(entities_count * size, wgpu::BufferUsage::COPY_SRC); @@ -214,7 +214,7 @@ impl Application { .zip(temp_buf_data.data.chunks_exact_mut(size)) { slot.copy_from_slice( - EntityUniforms { + MaterialUniforms { model: transform.0.into(), color: [ entity.color.x as f32, diff --git a/src/asset/mod.rs b/src/asset/mod.rs index d7323dae1a..b4bc5a71b5 100644 --- a/src/asset/mod.rs +++ b/src/asset/mod.rs @@ -1,10 +1,20 @@ -use std::{sync::Arc, marker::PhantomData, ops::Drop}; +use std::{sync::{Arc, RwLock}, marker::PhantomData, ops::Drop}; pub struct Handle { - pub id: Arc, + pub id: Arc>, marker: PhantomData, - free_indices: Arc> + free_indices: Arc>> +} + +impl Clone for Handle { + fn clone(&self) -> Self { + Handle { + id: self.id.clone(), + free_indices: self.free_indices.clone(), + marker: PhantomData + } + } } impl Drop for Handle { @@ -12,7 +22,8 @@ impl Drop for Handle { // TODO: Maybe this should be 1 // TODO: Is this even necessary? if Arc::strong_count(&self.id) == 0 { - Arc::get_mut(&mut self.free_indices).unwrap().push(*self.id); + let id = *self.id.read().unwrap(); + self.free_indices.write().unwrap().push(id); } } } @@ -23,7 +34,7 @@ pub trait Asset { pub struct AssetStorage where T: Asset { assets: Vec>, - free_indices: Arc>, + free_indices: Arc>>, marker: PhantomData, } @@ -31,17 +42,17 @@ impl AssetStorage where T: Asset { pub fn new() -> AssetStorage { AssetStorage { assets: Vec::new(), - free_indices: Arc::new(Vec::new()), + free_indices: Arc::new(RwLock::new(Vec::new())), marker: PhantomData, } } pub fn add(&mut self, asset: T) -> Handle { - match Arc::get_mut(&mut self.free_indices).unwrap().pop() { + match self.free_indices.write().unwrap().pop() { Some(id) => { self.assets[id as usize] = Some(asset); Handle { - id: Arc::new(id), + id: Arc::new(RwLock::new(id)), marker: PhantomData, free_indices: self.free_indices.clone() } @@ -49,7 +60,7 @@ impl AssetStorage where T: Asset { None => { self.assets.push(Some(asset)); Handle { - id: Arc::new(self.assets.len() - 1), + id: Arc::new(RwLock::new(self.assets.len() - 1)), marker: PhantomData, free_indices: self.free_indices.clone() } diff --git a/src/legion_transform/src/local_to_world_system.rs b/src/legion_transform/src/local_to_world_system.rs index 4ac3598a02..08a45e3628 100644 --- a/src/legion_transform/src/local_to_world_system.rs +++ b/src/legion_transform/src/local_to_world_system.rs @@ -218,6 +218,7 @@ pub fn build(_: &mut World) -> Box { }); // Just to issue warnings: Scale + NonUniformScale + #[allow(unused_unsafe)] unsafe { l.iter_entities_immutable(world).for_each( |(entity, (mut _ltw, _scale, _non_uniform_scale))| { diff --git a/src/lib.rs b/src/lib.rs index 4481cc57d7..ed650184c0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,6 @@ pub mod render; pub mod asset; mod application; mod vertex; -pub mod temp; mod core; pub use application::Application; diff --git a/src/render/camera.rs b/src/render/camera.rs index aeb416010f..1e8634da01 100644 --- a/src/render/camera.rs +++ b/src/render/camera.rs @@ -1,9 +1,5 @@ use crate::math; -pub struct Camera { - projection: math::Mat4, -} - pub fn get_projection_view_matrix(eye: &math::Vec3, fov: f32, aspect_ratio: f32, near: f32, far: f32) -> math::Mat4 { let projection = math::perspective(aspect_ratio, fov, near, far); diff --git a/src/render/forward/mod.rs b/src/render/forward/mod.rs index 314bacd7ad..72a0ba1ccc 100644 --- a/src/render/forward/mod.rs +++ b/src/render/forward/mod.rs @@ -1,4 +1,4 @@ -use crate::{render::*, temp::*, asset::*, render::mesh::*}; +use crate::{render::*, asset::*, render::mesh::*}; use legion::prelude::*; use std::{mem, sync::Arc}; use zerocopy::{AsBytes, FromBytes}; @@ -21,7 +21,7 @@ pub struct ForwardPass { impl Pass for ForwardPass { fn render(&mut self, device: &Device, frame: &SwapChainOutput, encoder: &mut CommandEncoder, world: &mut World) { - let mut mesh_query = <(Read, Read>)>::query(); + let mut mesh_query = <(Read, Read>)>::query(); let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { attachment: &frame.view, @@ -50,7 +50,7 @@ impl Pass for ForwardPass { let mut mesh_storage = world.resources.get_mut::>().unwrap(); for (entity, mesh) in mesh_query.iter_immutable(world) { - if let Some(mesh_asset) = mesh_storage.get(*mesh.id) { + if let Some(mesh_asset) = mesh_storage.get(*mesh.id.read().unwrap()) { mesh_asset.setup_buffers(device); pass.set_bind_group(1, entity.bind_group.as_ref().unwrap(), &[]); pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0); diff --git a/src/render/material.rs b/src/render/material.rs new file mode 100644 index 0000000000..005460aebf --- /dev/null +++ b/src/render/material.rs @@ -0,0 +1,21 @@ +use zerocopy::{AsBytes, FromBytes}; +use crate::math; + +pub struct Material { + pub color: math::Vec4, + pub bind_group: Option, + pub uniform_buf: Option, +} + +#[repr(C)] +#[derive(Clone, Copy, AsBytes, FromBytes)] +pub struct RenderedUniforms { + pub transform: [[f32; 4]; 4], +} + +#[repr(C)] +#[derive(Clone, Copy, AsBytes, FromBytes)] +pub struct MaterialUniforms { + pub model: [[f32; 4]; 4], + pub color: [f32; 4], +} \ No newline at end of file diff --git a/src/render/mesh.rs b/src/render/mesh.rs index daba7c0c52..02f2856ccb 100644 --- a/src/render/mesh.rs +++ b/src/render/mesh.rs @@ -1,6 +1,6 @@ use crate::{vertex::Vertex, asset::Asset}; use wgpu::{Buffer, Device}; -use zerocopy::{AsBytes, FromBytes}; +use zerocopy::AsBytes; pub enum MeshType { Cube, diff --git a/src/render/mod.rs b/src/render/mod.rs index 7b1a3f439d..12f20ed4e2 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -5,20 +5,17 @@ mod forward; mod shadow; mod light; mod pass; +mod material; pub use forward::{ForwardPass, ForwardUniforms}; pub use shadow::ShadowPass; pub use light::*; pub use shader::*; pub use pass::*; - -use wgpu::BindGroup; +pub use material::*; +pub use mesh::*; pub struct UniformBuffer { pub buffer: wgpu::Buffer, pub size: u64, -} - -pub struct Rendered { - pub bind_group: Option, } \ No newline at end of file diff --git a/src/render/shadow/mod.rs b/src/render/shadow/mod.rs index 1f9faf67e4..5fa4e3cfdb 100644 --- a/src/render/shadow/mod.rs +++ b/src/render/shadow/mod.rs @@ -1,4 +1,4 @@ -use crate::{render::*, temp::*, asset::*, render::mesh::*}; +use crate::{render::*, asset::*}; use wgpu::{BindGroupLayout, CommandEncoder, Device, VertexBufferDescriptor, SwapChainOutput}; use legion::prelude::*; use zerocopy::AsBytes; @@ -23,7 +23,7 @@ pub struct ShadowUniforms { impl Pass for ShadowPass { fn render(&mut self, device: &Device, _: &SwapChainOutput, encoder: &mut CommandEncoder, world: &mut World) { let mut light_query = >::query(); - let mut mesh_query = <(Read, Read>)>::query(); + let mut mesh_query = <(Read, Read>)>::query(); let light_count = light_query.iter(world).count(); if self.lights_are_dirty { @@ -75,7 +75,7 @@ impl Pass for ShadowPass { let mut mesh_storage = world.resources.get_mut::>().unwrap(); for (entity, mesh) in mesh_query.iter_immutable(world) { - if let Some(mut mesh_asset) = mesh_storage.get(*mesh.id) { + if let Some(mesh_asset) = mesh_storage.get(*mesh.id.read().unwrap()) { mesh_asset.setup_buffers(device); pass.set_bind_group(1, entity.bind_group.as_ref().unwrap(), &[]); diff --git a/src/temp.rs b/src/temp.rs deleted file mode 100644 index ee5537005b..0000000000 --- a/src/temp.rs +++ /dev/null @@ -1,40 +0,0 @@ -use std::{sync::Arc}; -use zerocopy::{AsBytes, FromBytes}; -use crate::math; - -pub struct CubeEnt { - pub color: math::Vec4, - pub bind_group: Option, - pub uniform_buf: Option, -} - -#[repr(C)] -#[derive(Clone, Copy, AsBytes, FromBytes)] -pub struct EntityUniforms { - pub model: [[f32; 4]; 4], - pub color: [f32; 4], -} - -#[allow(dead_code)] -pub fn create_texels(size: usize) -> Vec { - use std::iter; - - (0 .. size * size) - .flat_map(|id| { - // get high five for recognizing this ;) - let cx = 3.0 * (id % size) as f32 / (size - 1) as f32 - 2.0; - let cy = 2.0 * (id / size) as f32 / (size - 1) as f32 - 1.0; - let (mut x, mut y, mut count) = (cx, cy, 0); - while count < 0xFF && x * x + y * y < 4.0 { - let old_x = x; - x = x * x - y * y + cx; - y = 2.0 * old_x * y + cy; - count += 1; - } - iter::once(0xFF - (count * 5) as u8) - .chain(iter::once(0xFF - (count * 15) as u8)) - .chain(iter::once(0xFF - (count * 50) as u8)) - .chain(iter::once(1)) - }) - .collect() -} \ No newline at end of file diff --git a/tiny-town/README.md b/tiny-town/README.md index 0d9d87bdc8..7bfd75f916 100644 --- a/tiny-town/README.md +++ b/tiny-town/README.md @@ -1,6 +1,9 @@ ```bash -# run using this command +# run using one of these commands +# lld linker makes compiles faster +# rust backtrace gives you a nice backtrace on panics env RUSTFLAGS="-C link-arg=-fuse-ld=lld" cargo run --release +env RUSTFLAGS="-C link-arg=-fuse-ld=lld" RUST_BACKTRACE=1 cargo run --release ``` \ No newline at end of file diff --git a/tiny-town/src/main.rs b/tiny-town/src/main.rs index 799b4a61ae..0458e99410 100644 --- a/tiny-town/src/main.rs +++ b/tiny-town/src/main.rs @@ -1,5 +1,6 @@ use bevy::*; use bevy::{render::mesh::{Mesh, MeshType}, asset::{Asset, AssetStorage}, temp::*, math}; +use std::clone::Clone; fn main() { let universe = Universe::new(); @@ -7,12 +8,33 @@ fn main() { // Create a query which finds all `Position` and `Velocity` components // let mut query = Read::::query(); let cube = Mesh::load(MeshType::Cube); + let plane = Mesh::load(MeshType::Plane{ size: 10 }); let mut mesh_storage = AssetStorage::::new(); - let handle = mesh_storage.add(cube); + + // this currently breaks because Arcs cant be modified after they are cloned :( + let mesh_handle = mesh_storage.add(cube); + let plane_handle = mesh_storage.add(plane); world.resources.insert(mesh_storage); world.insert((), vec![ - (CubeEnt { color: math::Vec4::identity(), bind_group: None, uniform_buf: None }, handle, LocalToWorld::identity(), Translation::new(0.0, 0.0, 0.0)) + ( + Material { color: math::vec4(0.0, 1.0, 0.0, 1.0), bind_group: None, uniform_buf: None }, + plane_handle.clone(), + LocalToWorld(math::translation(&math::vec3(0.0, 0.0, 0.0))), + Translation::new(0.0, 0.0, 0.0) + ), + ( + Material { color: math::vec4(0.0, 1.0, 0.0, 1.0), bind_group: None, uniform_buf: None }, + mesh_handle.clone(), + LocalToWorld(math::translation(&math::vec3(3.0, 0.0, 0.0))), + Translation::new(0.0, 0.0, 0.0) + ), + ( + Material { color: math::vec4(1.0, 0.0, 0.0, 1.0), bind_group: None, uniform_buf: None }, + mesh_handle, + LocalToWorld::identity(), + Translation::new(0.0, 0.0, 0.0) + ), ]); Application::run(universe, world);