fix asset loading. no more temp!

This commit is contained in:
Carter Anderson 2019-12-02 10:48:08 -08:00
parent a96f3cfda5
commit 3922c76efe
14 changed files with 121 additions and 80 deletions

View file

@ -1,9 +1,40 @@
use bevy::{Application}; use bevy::*;
use legion::prelude::*; use bevy::{render::*, asset::{Asset, AssetStorage}, math};
fn main() { fn main() {
// Create a world to store our entities
let universe = Universe::new(); let universe = Universe::new();
let mut world = universe.create_world(); let mut world = universe.create_world();
// Create a query which finds all `Position` and `Velocity` components
// let mut query = Read::<Transform>::query();
let cube = Mesh::load(MeshType::Cube);
let plane = Mesh::load(MeshType::Plane{ size: 10 });
let mut mesh_storage = AssetStorage::<Mesh, MeshType>::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); Application::run(universe, world);
} }

View file

@ -10,7 +10,7 @@ use legion::prelude::*;
use std::sync::Arc; use std::sync::Arc;
use std::mem; use std::mem;
use crate::{temp::*, vertex::*, render::*, math, LocalToWorld, Translation, ApplicationStage}; use crate::{vertex::*, render::*, math, LocalToWorld, ApplicationStage};
pub struct Application pub struct Application
{ {
@ -45,9 +45,9 @@ impl Application {
}); });
let mut entities = <Write<CubeEnt>>::query(); let mut entities = <Write<Material>>::query();
for mut entity in entities.iter(&mut world) { for mut entity in entities.iter(&mut world) {
let entity_uniform_size = mem::size_of::<EntityUniforms>() as wgpu::BufferAddress; let entity_uniform_size = mem::size_of::<MaterialUniforms>() as wgpu::BufferAddress;
let uniform_buf = device.create_buffer(&wgpu::BufferDescriptor { let uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
size: entity_uniform_size, size: entity_uniform_size,
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
@ -204,9 +204,9 @@ impl Application {
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }); device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
{ {
let mut entities = <(Read<CubeEnt>, Read<LocalToWorld>)>::query(); let mut entities = <(Read<Material>, Read<LocalToWorld>)>::query();
let entities_count = entities.iter(&mut self.world).count(); let entities_count = entities.iter(&mut self.world).count();
let size = mem::size_of::<EntityUniforms>(); let size = mem::size_of::<MaterialUniforms>();
let temp_buf_data = device let temp_buf_data = device
.create_buffer_mapped(entities_count * size, wgpu::BufferUsage::COPY_SRC); .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)) .zip(temp_buf_data.data.chunks_exact_mut(size))
{ {
slot.copy_from_slice( slot.copy_from_slice(
EntityUniforms { MaterialUniforms {
model: transform.0.into(), model: transform.0.into(),
color: [ color: [
entity.color.x as f32, entity.color.x as f32,

View file

@ -1,10 +1,20 @@
use std::{sync::Arc, marker::PhantomData, ops::Drop}; use std::{sync::{Arc, RwLock}, marker::PhantomData, ops::Drop};
pub struct Handle<T> pub struct Handle<T>
{ {
pub id: Arc<usize>, pub id: Arc<RwLock<usize>>,
marker: PhantomData<T>, marker: PhantomData<T>,
free_indices: Arc<Vec<usize>> free_indices: Arc<RwLock<Vec<usize>>>
}
impl<T> Clone for Handle<T> {
fn clone(&self) -> Self {
Handle {
id: self.id.clone(),
free_indices: self.free_indices.clone(),
marker: PhantomData
}
}
} }
impl<T> Drop for Handle<T> { impl<T> Drop for Handle<T> {
@ -12,7 +22,8 @@ impl<T> Drop for Handle<T> {
// TODO: Maybe this should be 1 // TODO: Maybe this should be 1
// TODO: Is this even necessary? // TODO: Is this even necessary?
if Arc::strong_count(&self.id) == 0 { 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<D> {
pub struct AssetStorage<T, D> where T: Asset<D> { pub struct AssetStorage<T, D> where T: Asset<D> {
assets: Vec<Option<T>>, assets: Vec<Option<T>>,
free_indices: Arc<Vec<usize>>, free_indices: Arc<RwLock<Vec<usize>>>,
marker: PhantomData<D>, marker: PhantomData<D>,
} }
@ -31,17 +42,17 @@ impl<T, D> AssetStorage<T, D> where T: Asset<D> {
pub fn new() -> AssetStorage<T, D> { pub fn new() -> AssetStorage<T, D> {
AssetStorage { AssetStorage {
assets: Vec::new(), assets: Vec::new(),
free_indices: Arc::new(Vec::new()), free_indices: Arc::new(RwLock::new(Vec::new())),
marker: PhantomData, marker: PhantomData,
} }
} }
pub fn add(&mut self, asset: T) -> Handle<T> { pub fn add(&mut self, asset: T) -> Handle<T> {
match Arc::get_mut(&mut self.free_indices).unwrap().pop() { match self.free_indices.write().unwrap().pop() {
Some(id) => { Some(id) => {
self.assets[id as usize] = Some(asset); self.assets[id as usize] = Some(asset);
Handle { Handle {
id: Arc::new(id), id: Arc::new(RwLock::new(id)),
marker: PhantomData, marker: PhantomData,
free_indices: self.free_indices.clone() free_indices: self.free_indices.clone()
} }
@ -49,7 +60,7 @@ impl<T, D> AssetStorage<T, D> where T: Asset<D> {
None => { None => {
self.assets.push(Some(asset)); self.assets.push(Some(asset));
Handle { Handle {
id: Arc::new(self.assets.len() - 1), id: Arc::new(RwLock::new(self.assets.len() - 1)),
marker: PhantomData, marker: PhantomData,
free_indices: self.free_indices.clone() free_indices: self.free_indices.clone()
} }

View file

@ -218,6 +218,7 @@ pub fn build(_: &mut World) -> Box<dyn Schedulable> {
}); });
// Just to issue warnings: Scale + NonUniformScale // Just to issue warnings: Scale + NonUniformScale
#[allow(unused_unsafe)]
unsafe { unsafe {
l.iter_entities_immutable(world).for_each( l.iter_entities_immutable(world).for_each(
|(entity, (mut _ltw, _scale, _non_uniform_scale))| { |(entity, (mut _ltw, _scale, _non_uniform_scale))| {

View file

@ -2,7 +2,6 @@ pub mod render;
pub mod asset; pub mod asset;
mod application; mod application;
mod vertex; mod vertex;
pub mod temp;
mod core; mod core;
pub use application::Application; pub use application::Application;

View file

@ -1,9 +1,5 @@
use crate::math; 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 { 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); let projection = math::perspective(aspect_ratio, fov, near, far);

View file

@ -1,4 +1,4 @@
use crate::{render::*, temp::*, asset::*, render::mesh::*}; use crate::{render::*, asset::*, render::mesh::*};
use legion::prelude::*; use legion::prelude::*;
use std::{mem, sync::Arc}; use std::{mem, sync::Arc};
use zerocopy::{AsBytes, FromBytes}; use zerocopy::{AsBytes, FromBytes};
@ -21,7 +21,7 @@ pub struct ForwardPass {
impl Pass for ForwardPass { impl Pass for ForwardPass {
fn render(&mut self, device: &Device, frame: &SwapChainOutput, encoder: &mut CommandEncoder, world: &mut World) { fn render(&mut self, device: &Device, frame: &SwapChainOutput, encoder: &mut CommandEncoder, world: &mut World) {
let mut mesh_query = <(Read<CubeEnt>, Read<Handle<Mesh>>)>::query(); let mut mesh_query = <(Read<Material>, Read<Handle<Mesh>>)>::query();
let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
attachment: &frame.view, attachment: &frame.view,
@ -50,7 +50,7 @@ impl Pass for ForwardPass {
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh, MeshType>>().unwrap(); let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh, MeshType>>().unwrap();
for (entity, mesh) in mesh_query.iter_immutable(world) { 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); mesh_asset.setup_buffers(device);
pass.set_bind_group(1, entity.bind_group.as_ref().unwrap(), &[]); pass.set_bind_group(1, entity.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);

21
src/render/material.rs Normal file
View file

@ -0,0 +1,21 @@
use zerocopy::{AsBytes, FromBytes};
use crate::math;
pub struct Material {
pub color: math::Vec4,
pub bind_group: Option<wgpu::BindGroup>,
pub uniform_buf: Option<wgpu::Buffer>,
}
#[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],
}

View file

@ -1,6 +1,6 @@
use crate::{vertex::Vertex, asset::Asset}; use crate::{vertex::Vertex, asset::Asset};
use wgpu::{Buffer, Device}; use wgpu::{Buffer, Device};
use zerocopy::{AsBytes, FromBytes}; use zerocopy::AsBytes;
pub enum MeshType { pub enum MeshType {
Cube, Cube,

View file

@ -5,20 +5,17 @@ mod forward;
mod shadow; mod shadow;
mod light; mod light;
mod pass; mod pass;
mod material;
pub use forward::{ForwardPass, ForwardUniforms}; pub use forward::{ForwardPass, ForwardUniforms};
pub use shadow::ShadowPass; pub use shadow::ShadowPass;
pub use light::*; pub use light::*;
pub use shader::*; pub use shader::*;
pub use pass::*; pub use pass::*;
pub use material::*;
use wgpu::BindGroup; pub use mesh::*;
pub struct UniformBuffer { pub struct UniformBuffer {
pub buffer: wgpu::Buffer, pub buffer: wgpu::Buffer,
pub size: u64, pub size: u64,
}
pub struct Rendered {
pub bind_group: Option<BindGroup>,
} }

View file

@ -1,4 +1,4 @@
use crate::{render::*, temp::*, asset::*, render::mesh::*}; use crate::{render::*, asset::*};
use wgpu::{BindGroupLayout, CommandEncoder, Device, VertexBufferDescriptor, SwapChainOutput}; use wgpu::{BindGroupLayout, CommandEncoder, Device, VertexBufferDescriptor, SwapChainOutput};
use legion::prelude::*; use legion::prelude::*;
use zerocopy::AsBytes; use zerocopy::AsBytes;
@ -23,7 +23,7 @@ pub struct ShadowUniforms {
impl Pass for ShadowPass { impl Pass for ShadowPass {
fn render(&mut self, device: &Device, _: &SwapChainOutput, encoder: &mut CommandEncoder, world: &mut World) { fn render(&mut self, device: &Device, _: &SwapChainOutput, encoder: &mut CommandEncoder, world: &mut World) {
let mut light_query = <Read<Light>>::query(); let mut light_query = <Read<Light>>::query();
let mut mesh_query = <(Read<CubeEnt>, Read<Handle<Mesh>>)>::query(); let mut mesh_query = <(Read<Material>, Read<Handle<Mesh>>)>::query();
let light_count = light_query.iter(world).count(); let light_count = light_query.iter(world).count();
if self.lights_are_dirty { if self.lights_are_dirty {
@ -75,7 +75,7 @@ impl Pass for ShadowPass {
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh, MeshType>>().unwrap(); let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh, MeshType>>().unwrap();
for (entity, mesh) in mesh_query.iter_immutable(world) { 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); mesh_asset.setup_buffers(device);
pass.set_bind_group(1, entity.bind_group.as_ref().unwrap(), &[]); pass.set_bind_group(1, entity.bind_group.as_ref().unwrap(), &[]);

View file

@ -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<wgpu::BindGroup>,
pub uniform_buf: Option<wgpu::Buffer>,
}
#[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<u8> {
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()
}

View file

@ -1,6 +1,9 @@
```bash ```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" cargo run --release
env RUSTFLAGS="-C link-arg=-fuse-ld=lld" RUST_BACKTRACE=1 cargo run --release
``` ```

View file

@ -1,5 +1,6 @@
use bevy::*; use bevy::*;
use bevy::{render::mesh::{Mesh, MeshType}, asset::{Asset, AssetStorage}, temp::*, math}; use bevy::{render::mesh::{Mesh, MeshType}, asset::{Asset, AssetStorage}, temp::*, math};
use std::clone::Clone;
fn main() { fn main() {
let universe = Universe::new(); let universe = Universe::new();
@ -7,12 +8,33 @@ fn main() {
// Create a query which finds all `Position` and `Velocity` components // Create a query which finds all `Position` and `Velocity` components
// let mut query = Read::<Transform>::query(); // let mut query = Read::<Transform>::query();
let cube = Mesh::load(MeshType::Cube); let cube = Mesh::load(MeshType::Cube);
let plane = Mesh::load(MeshType::Plane{ size: 10 });
let mut mesh_storage = AssetStorage::<Mesh, MeshType>::new(); let mut mesh_storage = AssetStorage::<Mesh, MeshType>::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.resources.insert(mesh_storage);
world.insert((), vec![ 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); Application::run(universe, world);