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!
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;
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::<T>() > 0);
let array_mem_size = {
let alignment_padding = alignment_offset(size_of::<T>(), align_of::<T>());
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
/// 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);

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())?;
// 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 {

View File

@ -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<Assembly, PsyParseError> {
let mut builder = AssemblyBuilder::new();
pub fn parse_assembly<'a>(arena: &'a MemArena,
tree: &'a DataTree)
-> Result<Assembly<'a>, 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<Assembly, PsyParseError> {
// 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!();

View File

@ -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<Instance>,
pub light_instances: Vec<Instance>,
pub xforms: Vec<Matrix4x4>,
pub instances: &'a [Instance],
pub light_instances: &'a [Instance],
pub xforms: &'a [Matrix4x4],
// Object list
pub objects: Vec<Object>,
// Assembly list
pub assemblies: Vec<Assembly>,
pub assemblies: Vec<Assembly<'a>>,
// 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<Instance>,
xforms: Vec<Matrix4x4>,
@ -137,14 +141,15 @@ pub struct AssemblyBuilder {
object_map: HashMap<String, usize>, // map Name -> Index
// Assembly list
assemblies: Vec<Assembly>,
assemblies: Vec<Assembly<'a>>,
assembly_map: HashMap<String, usize>, // 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,

View File

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

View File

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