diff --git a/mem_arena/src/lib.rs b/mem_arena/src/lib.rs index 33a125b..65a00a9 100644 --- a/mem_arena/src/lib.rs +++ b/mem_arena/src/lib.rs @@ -71,6 +71,8 @@ impl MemArena { /// /// CAUTION: the memory returned is uninitialized. Make sure to initalize before using! pub unsafe fn alloc_uninitialized<'a, T: Copy>(&'a self) -> &'a mut T { + assert!(size_of::() > 0); + let memory = self.alloc_raw(size_of::(), align_of::()) as *mut T; memory.as_mut().unwrap() @@ -103,6 +105,8 @@ impl MemArena { /// Allocates memory for `len` values of type `T`, returning a mutable slice to it. /// All elements are initialized to the given `value`. pub unsafe fn alloc_array_uninitialized<'a, T: Copy>(&'a self, len: usize) -> &'a mut [T] { + assert!(size_of::() > 0); + let array_mem_size = { let alignment_padding = alignment_offset(size_of::(), align_of::()); let aligned_type_size = size_of::() + alignment_padding; @@ -119,13 +123,17 @@ impl MemArena { /// CAUTION: this returns uninitialized memory. Make sure to initialize the /// memory after calling. unsafe fn alloc_raw(&self, size: usize, alignment: usize) -> *mut u8 { - assert!(size > 0); assert!(alignment > 0); let mut blocks = self.blocks.borrow_mut(); + + // If it's a zero-size allocation, just point to the beginning of the curent block. + if size == 0 { + return blocks.first_mut().unwrap().as_mut_ptr(); + } // If the desired size is considered a "large allocation", give it its own memory block. - if size > self.large_alloc_threshold { + else if size > self.large_alloc_threshold { blocks.push(Vec::with_capacity(size + alignment - 1)); blocks.last_mut().unwrap().set_len(size + alignment - 1); diff --git a/src/parse/psy.rs b/src/parse/psy.rs index f9aeb78..9fdc817 100644 --- a/src/parse/psy.rs +++ b/src/parse/psy.rs @@ -72,7 +72,8 @@ pub fn parse_scene<'a>(arena: &'a MemArena, let world = parse_world(arena, tree.iter_children_with_type("World").nth(0).unwrap())?; // Parse root scene assembly - let assembly = parse_assembly(tree.iter_children_with_type("Assembly").nth(0).unwrap())?; + let assembly = parse_assembly(arena, + tree.iter_children_with_type("Assembly").nth(0).unwrap())?; // Put scene together let scene_name = if let &DataTree::Internal { ident, .. } = tree { diff --git a/src/parse/psy_assembly.rs b/src/parse/psy_assembly.rs index ae06a47..95562ef 100644 --- a/src/parse/psy_assembly.rs +++ b/src/parse/psy_assembly.rs @@ -2,6 +2,8 @@ use std::result::Result; +use mem_arena::MemArena; + use scene::{Assembly, AssemblyBuilder, Object}; use super::DataTree; @@ -10,8 +12,10 @@ use super::psy_mesh_surface::parse_mesh_surface; use super::psy::{parse_matrix, PsyParseError}; -pub fn parse_assembly(tree: &DataTree) -> Result { - let mut builder = AssemblyBuilder::new(); +pub fn parse_assembly<'a>(arena: &'a MemArena, + tree: &'a DataTree) + -> Result, PsyParseError> { + let mut builder = AssemblyBuilder::new(arena); if tree.is_internal() { for child in tree.iter_children() { @@ -19,7 +23,7 @@ pub fn parse_assembly(tree: &DataTree) -> Result { // Sub-Assembly "Assembly" => { if let &DataTree::Internal { ident: Some(ident), .. } = child { - builder.add_assembly(ident, parse_assembly(&child)?); + builder.add_assembly(ident, parse_assembly(arena, &child)?); } else { // TODO: error condition of some kind, because no ident panic!(); diff --git a/src/scene/assembly.rs b/src/scene/assembly.rs index d7572e8..61eb8a2 100644 --- a/src/scene/assembly.rs +++ b/src/scene/assembly.rs @@ -1,5 +1,7 @@ use std::collections::HashMap; +use mem_arena::MemArena; + use accel::{LightAccel, LightTree}; use accel::BVH; use bbox::{BBox, transform_bbox_slice_from}; @@ -13,17 +15,17 @@ use transform_stack::TransformStack; #[derive(Debug)] -pub struct Assembly { +pub struct Assembly<'a> { // Instance list - pub instances: Vec, - pub light_instances: Vec, - pub xforms: Vec, + pub instances: &'a [Instance], + pub light_instances: &'a [Instance], + pub xforms: &'a [Matrix4x4], // Object list pub objects: Vec, // Assembly list - pub assemblies: Vec, + pub assemblies: Vec>, // Object accel pub object_accel: BVH, @@ -32,7 +34,7 @@ pub struct Assembly { pub light_accel: LightTree, } -impl Assembly { +impl<'a> Assembly<'a> { // Returns (light_color, shadow_vector, pdf, selection_pdf) pub fn sample_lights(&self, xform_stack: &mut TransformStack, @@ -119,15 +121,17 @@ impl Assembly { } } -impl Boundable for Assembly { - fn bounds<'a>(&'a self) -> &'a [BBox] { +impl<'a> Boundable for Assembly<'a> { + fn bounds<'b>(&'b self) -> &'b [BBox] { self.object_accel.bounds() } } #[derive(Debug)] -pub struct AssemblyBuilder { +pub struct AssemblyBuilder<'a> { + arena: &'a MemArena, + // Instance list instances: Vec, xforms: Vec, @@ -137,14 +141,15 @@ pub struct AssemblyBuilder { object_map: HashMap, // map Name -> Index // Assembly list - assemblies: Vec, + assemblies: Vec>, assembly_map: HashMap, // map Name -> Index } -impl AssemblyBuilder { - pub fn new() -> AssemblyBuilder { +impl<'a> AssemblyBuilder<'a> { + pub fn new(arena: &'a MemArena) -> AssemblyBuilder<'a> { AssemblyBuilder { + arena: arena, instances: Vec::new(), xforms: Vec::new(), objects: Vec::new(), @@ -165,7 +170,7 @@ impl AssemblyBuilder { self.objects.push(obj); } - pub fn add_assembly(&mut self, name: &str, asmb: Assembly) { + pub fn add_assembly(&mut self, name: &str, asmb: Assembly<'a>) { // Make sure the name hasn't already been used. if self.name_exists(name) { panic!("Attempted to add assembly to another assembly with a name that already \ @@ -221,13 +226,7 @@ impl AssemblyBuilder { self.object_map.contains_key(name) || self.assembly_map.contains_key(name) } - pub fn build(mut self) -> Assembly { - // Shrink storage to minimum. - self.instances.shrink_to_fit(); - self.xforms.shrink_to_fit(); - self.objects.shrink_to_fit(); - self.assemblies.shrink_to_fit(); - + pub fn build(mut self) -> Assembly<'a> { // Calculate instance bounds, used for building object accel and light accel. let (bis, bbs) = self.instance_bounds(); @@ -276,9 +275,9 @@ impl AssemblyBuilder { }); Assembly { - instances: self.instances, - light_instances: light_instances, - xforms: self.xforms, + instances: self.arena.copy_slice(&self.instances), + light_instances: self.arena.copy_slice(&light_instances), + xforms: self.arena.copy_slice(&self.xforms), objects: self.objects, assemblies: self.assemblies, object_accel: object_accel, diff --git a/src/scene/scene.rs b/src/scene/scene.rs index ad8f4a6..48fb497 100644 --- a/src/scene/scene.rs +++ b/src/scene/scene.rs @@ -15,7 +15,7 @@ pub struct Scene<'a> { pub name: Option, pub camera: Camera<'a>, pub world: World<'a>, - pub root: Assembly, + pub root: Assembly<'a>, } impl<'a> Scene<'a> { diff --git a/src/tracer.rs b/src/tracer.rs index c466354..592224d 100644 --- a/src/tracer.rs +++ b/src/tracer.rs @@ -36,7 +36,7 @@ impl<'a> Tracer<'a> { } struct TracerInner<'a> { - root: &'a Assembly, + root: &'a Assembly<'a>, xform_stack: TransformStack, isects: Vec, }