pub mod alias;
pub mod fifo;
pub mod hash;
pub mod lazy;
use {
crate::driver::{
CommandBuffer, DriverError,
accel_struct::{
AccelerationStructure, AccelerationStructureInfo, AccelerationStructureInfoBuilder,
},
buffer::{Buffer, BufferInfo, BufferInfoBuilder},
image::{Image, ImageInfo, ImageInfoBuilder},
},
derive_builder::{Builder, UninitializedFieldError},
std::{
fmt::Debug,
mem::ManuallyDrop,
ops::{Deref, DerefMut},
sync::{Arc, Weak},
thread::panicking,
},
};
#[cfg(feature = "parking_lot")]
use parking_lot::Mutex;
#[cfg(not(feature = "parking_lot"))]
use std::sync::Mutex;
type Cache<T> = Arc<Mutex<Vec<T>>>;
type CacheRef<T> = Weak<Mutex<Vec<T>>>;
fn lease_command_buffer(cache: &mut Vec<CommandBuffer>) -> Option<CommandBuffer> {
for idx in 0..cache.len() {
if unsafe {
let cmd_buf = cache.get_unchecked(idx);
cmd_buf
.device
.get_fence_status(cmd_buf.fence)
.unwrap_or_default()
} {
return Some(cache.swap_remove(idx));
}
}
None
}
#[derive(Debug)]
pub struct Lease<T> {
cache_ref: CacheRef<T>,
item: ManuallyDrop<T>,
}
impl<T> Lease<T> {
#[inline(always)]
fn new(cache_ref: CacheRef<T>, item: T) -> Self {
Self {
cache_ref,
item: ManuallyDrop::new(item),
}
}
}
impl<T> AsRef<T> for Lease<T> {
fn as_ref(&self) -> &T {
&self.item
}
}
impl<T> AsMut<T> for Lease<T> {
fn as_mut(&mut self) -> &mut T {
&mut self.item
}
}
impl<T> Deref for Lease<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.item
}
}
impl<T> DerefMut for Lease<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.item
}
}
impl<T> Drop for Lease<T> {
#[profiling::function]
fn drop(&mut self) {
if panicking() {
return;
}
if let Some(cache) = self.cache_ref.upgrade() {
#[cfg_attr(not(feature = "parking_lot"), allow(unused_mut))]
let mut cache = cache.lock();
#[cfg(not(feature = "parking_lot"))]
let mut cache = cache.unwrap();
if cache.len() == cache.capacity() {
cache.pop();
}
cache.push(unsafe { ManuallyDrop::take(&mut self.item) });
} else {
unsafe {
ManuallyDrop::drop(&mut self.item);
}
}
}
}
pub trait Pool<I, T> {
fn lease(&mut self, info: I) -> Result<Lease<T>, DriverError>;
}
macro_rules! lease_builder {
($info:ident => $item:ident) => {
paste::paste! {
impl<T> Pool<[<$info Builder>], $item> for T where T: Pool<$info, $item> {
fn lease(&mut self, builder: [<$info Builder>]) -> Result<Lease<$item>, DriverError> {
let info = builder.build();
self.lease(info)
}
}
}
};
}
lease_builder!(AccelerationStructureInfo => AccelerationStructure);
lease_builder!(BufferInfo => Buffer);
lease_builder!(ImageInfo => Image);
#[derive(Builder, Clone, Copy, Debug)]
#[builder(
build_fn(private, name = "fallible_build", error = "PoolInfoBuilderError"),
derive(Clone, Copy, Debug),
pattern = "owned"
)]
#[non_exhaustive]
pub struct PoolInfo {
#[builder(default = "PoolInfo::DEFAULT_RESOURCE_CAPACITY", setter(strip_option))]
pub accel_struct_capacity: usize,
#[builder(default = "PoolInfo::DEFAULT_RESOURCE_CAPACITY", setter(strip_option))]
pub buffer_capacity: usize,
#[builder(default = "PoolInfo::DEFAULT_RESOURCE_CAPACITY", setter(strip_option))]
pub image_capacity: usize,
}
impl PoolInfo {
pub const DEFAULT_RESOURCE_CAPACITY: usize = 16;
pub const fn with_capacity(resource_capacity: usize) -> Self {
Self {
accel_struct_capacity: resource_capacity,
buffer_capacity: resource_capacity,
image_capacity: resource_capacity,
}
}
fn default_cache<T>() -> Cache<T> {
Cache::new(Mutex::new(Vec::with_capacity(
Self::DEFAULT_RESOURCE_CAPACITY,
)))
}
fn explicit_cache<T>(capacity: usize) -> Cache<T> {
Cache::new(Mutex::new(Vec::with_capacity(capacity)))
}
}
impl Default for PoolInfo {
fn default() -> Self {
PoolInfoBuilder::default().into()
}
}
impl From<PoolInfoBuilder> for PoolInfo {
fn from(info: PoolInfoBuilder) -> Self {
info.build()
}
}
impl From<usize> for PoolInfo {
fn from(value: usize) -> Self {
Self {
accel_struct_capacity: value,
buffer_capacity: value,
image_capacity: value,
}
}
}
impl PoolInfoBuilder {
pub fn build(self) -> PoolInfo {
self.fallible_build()
.expect("All required fields set at initialization")
}
}
#[derive(Debug)]
struct PoolInfoBuilderError;
impl From<UninitializedFieldError> for PoolInfoBuilderError {
fn from(_: UninitializedFieldError) -> Self {
Self
}
}