pbrt/src/utils/containers.rs

89 lines
2.1 KiB
Rust

use parking_lot::Mutex;
use shared::core::geometry::{Bounds2i, Point2i};
use shared::utils::containers::DeviceArray2D;
use std::collections::HashSet;
use std::hash::Hash;
use std::ops::{Deref, DerefMut};
use std::sync::Arc;
pub struct InternCache<T> {
cache: Mutex<HashSet<Arc<T>>>,
}
impl<T> InternCache<T>
where
T: Eq + Clone + Hash,
{
pub fn new() -> Self {
Self {
cache: Mutex::new(HashSet::new()),
}
}
pub fn lookup(&self, value: T) -> Arc<T> {
let mut lock = self.cache.lock();
if let Some(existing) = lock.get(&value) {
return existing.clone();
}
let new_item = Arc::new(value);
lock.insert(Arc::clone(&new_item));
new_item
}
}
#[derive(Debug, Clone)]
pub struct Array2D<T> {
pub device: DeviceArray2D<T>,
values: Vec<T>,
}
impl<T> Deref for Array2D<T> {
type Target = DeviceArray2D<T>;
fn deref(&self) -> &Self::Target {
&self.device
}
}
impl<T> DerefMut for Array2D<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.device
}
}
impl<T> Array2D<T> {
pub fn as_slice(&self) -> &[T] {
&self.values
}
fn from_vec(extent: Bounds2i, mut values: Vec<T>) -> Self {
let width = extent.p_max.x() - extent.p_min.x();
let device = DeviceArray2D {
extent,
values: values.as_mut_ptr().into(),
stride: width,
};
Self { device, values }
}
}
impl<T: Default + Clone> Array2D<T> {
pub fn new(extent: Bounds2i) -> Self {
let n = extent.area() as usize;
let storage = vec![T::default(); n];
Self::from_vec(extent, storage)
}
pub fn new_dims(nx: i32, ny: i32) -> Self {
let extent = Bounds2i::from_points(Point2i::new(0, 0), Point2i::new(nx, ny));
Self::new(extent)
}
pub fn new_filled(nx: i32, ny: i32, val: T) -> Self {
let extent = Bounds2i::from_points(Point2i::new(0, 0), Point2i::new(nx, ny));
let n = (nx * ny) as usize;
let storage = vec![val; n];
Self::from_vec(extent, storage)
}
}