Assembly type now partially uses MemArena.

This commit is contained in:
Nathan Vegdahl 2017-04-09 18:27:01 -07:00
parent fc15fa9192
commit e9e202933f
6 changed files with 43 additions and 31 deletions

View File

@ -71,6 +71,8 @@ impl MemArena {
/// ///
/// CAUTION: the memory returned is uninitialized. Make sure to initalize before using! /// 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 { pub unsafe fn alloc_uninitialized<'a, T: Copy>(&'a self) -> &'a mut T {
assert!(size_of::<T>() > 0);
let memory = self.alloc_raw(size_of::<T>(), align_of::<T>()) as *mut T; let memory = self.alloc_raw(size_of::<T>(), align_of::<T>()) as *mut T;
memory.as_mut().unwrap() memory.as_mut().unwrap()
@ -103,6 +105,8 @@ impl MemArena {
/// Allocates memory for `len` values of type `T`, returning a mutable slice to it. /// Allocates memory for `len` values of type `T`, returning a mutable slice to it.
/// All elements are initialized to the given `value`. /// All elements are initialized to the given `value`.
pub unsafe fn alloc_array_uninitialized<'a, T: Copy>(&'a self, len: usize) -> &'a mut [T] { pub unsafe fn alloc_array_uninitialized<'a, T: Copy>(&'a self, len: usize) -> &'a mut [T] {
assert!(size_of::<T>() > 0);
let array_mem_size = { let array_mem_size = {
let alignment_padding = alignment_offset(size_of::<T>(), align_of::<T>()); let alignment_padding = alignment_offset(size_of::<T>(), align_of::<T>());
let aligned_type_size = size_of::<T>() + alignment_padding; let aligned_type_size = size_of::<T>() + alignment_padding;
@ -119,13 +123,17 @@ impl MemArena {
/// CAUTION: this returns uninitialized memory. Make sure to initialize the /// CAUTION: this returns uninitialized memory. Make sure to initialize the
/// memory after calling. /// memory after calling.
unsafe fn alloc_raw(&self, size: usize, alignment: usize) -> *mut u8 { unsafe fn alloc_raw(&self, size: usize, alignment: usize) -> *mut u8 {
assert!(size > 0);
assert!(alignment > 0); assert!(alignment > 0);
let mut blocks = self.blocks.borrow_mut(); 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 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.push(Vec::with_capacity(size + alignment - 1));
blocks.last_mut().unwrap().set_len(size + alignment - 1); blocks.last_mut().unwrap().set_len(size + alignment - 1);

View File

@ -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())?; let world = parse_world(arena, tree.iter_children_with_type("World").nth(0).unwrap())?;
// Parse root scene assembly // 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 // Put scene together
let scene_name = if let &DataTree::Internal { ident, .. } = tree { let scene_name = if let &DataTree::Internal { ident, .. } = tree {

View File

@ -2,6 +2,8 @@
use std::result::Result; use std::result::Result;
use mem_arena::MemArena;
use scene::{Assembly, AssemblyBuilder, Object}; use scene::{Assembly, AssemblyBuilder, Object};
use super::DataTree; use super::DataTree;
@ -10,8 +12,10 @@ use super::psy_mesh_surface::parse_mesh_surface;
use super::psy::{parse_matrix, PsyParseError}; use super::psy::{parse_matrix, PsyParseError};
pub fn parse_assembly(tree: &DataTree) -> Result<Assembly, PsyParseError> { pub fn parse_assembly<'a>(arena: &'a MemArena,
let mut builder = AssemblyBuilder::new(); tree: &'a DataTree)
-> Result<Assembly<'a>, PsyParseError> {
let mut builder = AssemblyBuilder::new(arena);
if tree.is_internal() { if tree.is_internal() {
for child in tree.iter_children() { for child in tree.iter_children() {
@ -19,7 +23,7 @@ pub fn parse_assembly(tree: &DataTree) -> Result<Assembly, PsyParseError> {
// Sub-Assembly // Sub-Assembly
"Assembly" => { "Assembly" => {
if let &DataTree::Internal { ident: Some(ident), .. } = child { if let &DataTree::Internal { ident: Some(ident), .. } = child {
builder.add_assembly(ident, parse_assembly(&child)?); builder.add_assembly(ident, parse_assembly(arena, &child)?);
} else { } else {
// TODO: error condition of some kind, because no ident // TODO: error condition of some kind, because no ident
panic!(); panic!();

View File

@ -1,5 +1,7 @@
use std::collections::HashMap; use std::collections::HashMap;
use mem_arena::MemArena;
use accel::{LightAccel, LightTree}; use accel::{LightAccel, LightTree};
use accel::BVH; use accel::BVH;
use bbox::{BBox, transform_bbox_slice_from}; use bbox::{BBox, transform_bbox_slice_from};
@ -13,17 +15,17 @@ use transform_stack::TransformStack;
#[derive(Debug)] #[derive(Debug)]
pub struct Assembly { pub struct Assembly<'a> {
// Instance list // Instance list
pub instances: Vec<Instance>, pub instances: &'a [Instance],
pub light_instances: Vec<Instance>, pub light_instances: &'a [Instance],
pub xforms: Vec<Matrix4x4>, pub xforms: &'a [Matrix4x4],
// Object list // Object list
pub objects: Vec<Object>, pub objects: Vec<Object>,
// Assembly list // Assembly list
pub assemblies: Vec<Assembly>, pub assemblies: Vec<Assembly<'a>>,
// Object accel // Object accel
pub object_accel: BVH, pub object_accel: BVH,
@ -32,7 +34,7 @@ pub struct Assembly {
pub light_accel: LightTree, pub light_accel: LightTree,
} }
impl Assembly { impl<'a> Assembly<'a> {
// Returns (light_color, shadow_vector, pdf, selection_pdf) // Returns (light_color, shadow_vector, pdf, selection_pdf)
pub fn sample_lights(&self, pub fn sample_lights(&self,
xform_stack: &mut TransformStack, xform_stack: &mut TransformStack,
@ -119,15 +121,17 @@ impl Assembly {
} }
} }
impl Boundable for Assembly { impl<'a> Boundable for Assembly<'a> {
fn bounds<'a>(&'a self) -> &'a [BBox] { fn bounds<'b>(&'b self) -> &'b [BBox] {
self.object_accel.bounds() self.object_accel.bounds()
} }
} }
#[derive(Debug)] #[derive(Debug)]
pub struct AssemblyBuilder { pub struct AssemblyBuilder<'a> {
arena: &'a MemArena,
// Instance list // Instance list
instances: Vec<Instance>, instances: Vec<Instance>,
xforms: Vec<Matrix4x4>, xforms: Vec<Matrix4x4>,
@ -137,14 +141,15 @@ pub struct AssemblyBuilder {
object_map: HashMap<String, usize>, // map Name -> Index object_map: HashMap<String, usize>, // map Name -> Index
// Assembly list // Assembly list
assemblies: Vec<Assembly>, assemblies: Vec<Assembly<'a>>,
assembly_map: HashMap<String, usize>, // map Name -> Index assembly_map: HashMap<String, usize>, // map Name -> Index
} }
impl AssemblyBuilder { impl<'a> AssemblyBuilder<'a> {
pub fn new() -> AssemblyBuilder { pub fn new(arena: &'a MemArena) -> AssemblyBuilder<'a> {
AssemblyBuilder { AssemblyBuilder {
arena: arena,
instances: Vec::new(), instances: Vec::new(),
xforms: Vec::new(), xforms: Vec::new(),
objects: Vec::new(), objects: Vec::new(),
@ -165,7 +170,7 @@ impl AssemblyBuilder {
self.objects.push(obj); 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. // Make sure the name hasn't already been used.
if self.name_exists(name) { if self.name_exists(name) {
panic!("Attempted to add assembly to another assembly with a name that already \ 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) self.object_map.contains_key(name) || self.assembly_map.contains_key(name)
} }
pub fn build(mut self) -> Assembly { pub fn build(mut self) -> Assembly<'a> {
// Shrink storage to minimum.
self.instances.shrink_to_fit();
self.xforms.shrink_to_fit();
self.objects.shrink_to_fit();
self.assemblies.shrink_to_fit();
// Calculate instance bounds, used for building object accel and light accel. // Calculate instance bounds, used for building object accel and light accel.
let (bis, bbs) = self.instance_bounds(); let (bis, bbs) = self.instance_bounds();
@ -276,9 +275,9 @@ impl AssemblyBuilder {
}); });
Assembly { Assembly {
instances: self.instances, instances: self.arena.copy_slice(&self.instances),
light_instances: light_instances, light_instances: self.arena.copy_slice(&light_instances),
xforms: self.xforms, xforms: self.arena.copy_slice(&self.xforms),
objects: self.objects, objects: self.objects,
assemblies: self.assemblies, assemblies: self.assemblies,
object_accel: object_accel, object_accel: object_accel,

View File

@ -15,7 +15,7 @@ pub struct Scene<'a> {
pub name: Option<String>, pub name: Option<String>,
pub camera: Camera<'a>, pub camera: Camera<'a>,
pub world: World<'a>, pub world: World<'a>,
pub root: Assembly, pub root: Assembly<'a>,
} }
impl<'a> Scene<'a> { impl<'a> Scene<'a> {

View File

@ -36,7 +36,7 @@ impl<'a> Tracer<'a> {
} }
struct TracerInner<'a> { struct TracerInner<'a> {
root: &'a Assembly, root: &'a Assembly<'a>,
xform_stack: TransformStack, xform_stack: TransformStack,
isects: Vec<SurfaceIntersection>, isects: Vec<SurfaceIntersection>,
} }