rafx_framework/resources/
pool.rs1use rafx_api::{RafxDescriptorSetArray, RafxDeviceContext, RafxResult};
2use std::collections::VecDeque;
3use std::num::Wrapping;
4
5pub type PoolResourceAllocatorAllocFn<T> =
7 dyn Fn(&RafxDeviceContext, u32) -> RafxResult<T> + Send + Sync;
8
9pub trait PooledResourceImpl {
11 fn reset(&mut self) -> RafxResult<()>;
12}
13
14struct PoolResourceInFlight<T: PooledResourceImpl> {
15 pool: T,
16 live_until_frame: Wrapping<u32>,
17}
18
19pub struct PooledResourceAllocator<T: PooledResourceImpl> {
24 device_context: RafxDeviceContext,
25
26 allocate_fn: Box<PoolResourceAllocatorAllocFn<T>>,
28
29 in_flight_pools: VecDeque<PoolResourceInFlight<T>>,
33
34 reset_pools: Vec<T>,
36
37 max_in_flight_frames: Wrapping<u32>,
39
40 frame_index: Wrapping<u32>,
42
43 created_pool_count: u32,
45
46 max_pool_count: u32,
48}
49
50impl<T: PooledResourceImpl> PooledResourceAllocator<T> {
51 pub fn new<F: Fn(&RafxDeviceContext, u32) -> RafxResult<T> + Send + Sync + 'static>(
57 device_context: &RafxDeviceContext,
58 max_in_flight_frames: u32,
59 max_pool_count: u32,
60 allocate_fn: F,
61 ) -> Self {
62 PooledResourceAllocator {
63 device_context: device_context.clone(),
64 allocate_fn: Box::new(allocate_fn),
65 in_flight_pools: Default::default(),
66 reset_pools: Default::default(),
67 max_in_flight_frames: Wrapping(max_in_flight_frames),
68 frame_index: Wrapping(0),
69 created_pool_count: 0,
70 max_pool_count,
71 }
72 }
73
74 pub fn allocate_pool(&mut self) -> RafxResult<T> {
78 self.reset_pools.pop().map(Ok).unwrap_or_else(|| {
79 let pool_index = self.created_pool_count;
80 self.created_pool_count += 1;
81 assert!(self.created_pool_count <= self.max_pool_count);
82 (self.allocate_fn)(&self.device_context, pool_index)
83 })
84 }
85
86 pub fn retire_pool(
88 &mut self,
89 pool: T,
90 ) {
91 self.in_flight_pools.push_back(PoolResourceInFlight {
92 pool,
93 live_until_frame: self.frame_index + self.max_in_flight_frames,
94 });
95 }
96
97 pub fn update(&mut self) -> RafxResult<()> {
100 self.frame_index += Wrapping(1);
101
102 let mut pools_to_drain = 0;
104 for in_flight_pool in &self.in_flight_pools {
105 if in_flight_pool.live_until_frame - self.frame_index > Wrapping(std::u32::MAX / 2) {
108 pools_to_drain += 1;
109 } else {
110 break;
111 }
112 }
113
114 let pools_to_reset: Vec<_> = self.in_flight_pools.drain(0..pools_to_drain).collect();
116 for mut pool_to_reset in pools_to_reset {
117 T::reset(&mut pool_to_reset.pool)?;
118 self.reset_pools.push(pool_to_reset.pool);
119 }
120
121 Ok(())
122 }
123
124 pub fn destroy(&mut self) -> RafxResult<()> {
127 for pool in self.in_flight_pools.drain(..) {
128 std::mem::drop(pool.pool);
129 }
130
131 for pool in self.reset_pools.drain(..) {
132 std::mem::drop(pool);
133 }
134
135 Ok(())
136 }
137}
138
139impl<T: PooledResourceImpl> Drop for PooledResourceAllocator<T> {
141 fn drop(&mut self) {
142 assert!(self.in_flight_pools.is_empty());
143 assert!(self.reset_pools.is_empty())
144 }
145}
146
147impl PooledResourceImpl for RafxDescriptorSetArray {
151 fn reset(&mut self) -> RafxResult<()> {
152 Ok(())
153 }
154}
155
156pub type DescriptorSetArrayPoolAllocator = PooledResourceAllocator<RafxDescriptorSetArray>;