1use {
4 super::{Cache, Lease, Pool, PoolInfo, lease_command_buffer},
5 crate::driver::{
6 CommandBuffer, CommandBufferInfo, DescriptorPool, DescriptorPoolInfo, DriverError,
7 RenderPass, RenderPassInfo,
8 accel_struct::{AccelerationStructure, AccelerationStructureInfo},
9 buffer::{Buffer, BufferInfo},
10 device::Device,
11 image::{Image, ImageInfo},
12 },
13 log::debug,
14 paste::paste,
15 std::{collections::HashMap, sync::Arc},
16};
17
18#[cfg(feature = "parking_lot")]
19use parking_lot::Mutex;
20
21#[cfg(not(feature = "parking_lot"))]
22use std::sync::Mutex;
23
24#[derive(Debug)]
40pub struct HashPool {
41 acceleration_structure_cache: HashMap<AccelerationStructureInfo, Cache<AccelerationStructure>>,
42 buffer_cache: HashMap<BufferInfo, Cache<Buffer>>,
43 command_buffer_cache: HashMap<u32, Cache<CommandBuffer>>,
44 descriptor_pool_cache: HashMap<DescriptorPoolInfo, Cache<DescriptorPool>>,
45 device: Arc<Device>,
46 image_cache: HashMap<ImageInfo, Cache<Image>>,
47 info: PoolInfo,
48 render_pass_cache: HashMap<RenderPassInfo, Cache<RenderPass>>,
49}
50
51impl HashPool {
52 pub fn new(device: &Arc<Device>) -> Self {
54 Self::with_capacity(device, PoolInfo::default())
55 }
56
57 pub fn with_capacity(device: &Arc<Device>, info: impl Into<PoolInfo>) -> Self {
59 let info: PoolInfo = info.into();
60 let device = Arc::clone(device);
61
62 Self {
63 acceleration_structure_cache: Default::default(),
64 buffer_cache: Default::default(),
65 command_buffer_cache: Default::default(),
66 descriptor_pool_cache: Default::default(),
67 device,
68 image_cache: Default::default(),
69 info,
70 render_pass_cache: Default::default(),
71 }
72 }
73
74 pub fn clear(&mut self) {
76 self.clear_accel_structs();
77 self.clear_buffers();
78 self.clear_images();
79 }
80}
81
82macro_rules! resource_mgmt_fns {
83 ($fn_plural:literal, $doc_singular:literal, $ty:ty, $field:ident) => {
84 paste! {
85 impl HashPool {
86 #[doc = "Clears the pool of " $doc_singular " resources."]
87 pub fn [<clear_ $fn_plural>](&mut self) {
88 self.$field.clear();
89 }
90
91 #[doc = "Clears the pool of all " $doc_singular " resources matching the given
92information."]
93 pub fn [<clear_ $fn_plural _by_info>](
94 &mut self,
95 info: impl Into<$ty>,
96 ) {
97 self.$field.remove(&info.into());
98 }
99
100 #[doc = "Retains only the " $doc_singular " resources specified by the predicate.\n
101\nIn other words, remove all " $doc_singular " resources for which `f(" $ty ")` returns `false`.\n
102\n"]
103 pub fn [<retain_ $fn_plural>]<F>(&mut self, mut f: F)
110 where
111 F: FnMut($ty) -> bool,
112 {
113 self.$field.retain(|&info, _| f(info))
114 }
115 }
116 }
117 };
118}
119
120resource_mgmt_fns!(
121 "accel_structs",
122 "acceleration structure",
123 AccelerationStructureInfo,
124 acceleration_structure_cache
125);
126resource_mgmt_fns!("buffers", "buffer", BufferInfo, buffer_cache);
127resource_mgmt_fns!("images", "image", ImageInfo, image_cache);
128
129impl Pool<CommandBufferInfo, CommandBuffer> for HashPool {
130 #[profiling::function]
131 fn lease(&mut self, info: CommandBufferInfo) -> Result<Lease<CommandBuffer>, DriverError> {
132 let cache_ref = self
133 .command_buffer_cache
134 .entry(info.queue_family_index)
135 .or_insert_with(PoolInfo::default_cache);
136 let mut item = {
137 #[cfg_attr(not(feature = "parking_lot"), allow(unused_mut))]
138 let mut cache = cache_ref.lock();
139
140 #[cfg(not(feature = "parking_lot"))]
141 let mut cache = cache.unwrap();
142
143 lease_command_buffer(&mut cache)
144 }
145 .map(Ok)
146 .unwrap_or_else(|| {
147 debug!("Creating new {}", stringify!(CommandBuffer));
148
149 CommandBuffer::create(&self.device, info)
150 })?;
151
152 CommandBuffer::drop_fenced(&mut item);
154
155 Ok(Lease::new(Arc::downgrade(cache_ref), item))
156 }
157}
158
159impl Pool<DescriptorPoolInfo, DescriptorPool> for HashPool {
160 #[profiling::function]
161 fn lease(&mut self, info: DescriptorPoolInfo) -> Result<Lease<DescriptorPool>, DriverError> {
162 let cache_ref = self
163 .descriptor_pool_cache
164 .entry(info.clone())
165 .or_insert_with(PoolInfo::default_cache);
166 let item = {
167 #[cfg_attr(not(feature = "parking_lot"), allow(unused_mut))]
168 let mut cache = cache_ref.lock();
169
170 #[cfg(not(feature = "parking_lot"))]
171 let mut cache = cache.unwrap();
172
173 cache.pop()
174 }
175 .map(Ok)
176 .unwrap_or_else(|| {
177 debug!("Creating new {}", stringify!(DescriptorPool));
178
179 DescriptorPool::create(&self.device, info)
180 })?;
181
182 Ok(Lease::new(Arc::downgrade(cache_ref), item))
183 }
184}
185
186impl Pool<RenderPassInfo, RenderPass> for HashPool {
187 #[profiling::function]
188 fn lease(&mut self, info: RenderPassInfo) -> Result<Lease<RenderPass>, DriverError> {
189 let cache_ref = if let Some(cache) = self.render_pass_cache.get(&info) {
190 cache
191 } else {
192 self.render_pass_cache
194 .entry(info.clone())
195 .or_insert_with(PoolInfo::default_cache)
196 };
197 let item = {
198 #[cfg_attr(not(feature = "parking_lot"), allow(unused_mut))]
199 let mut cache = cache_ref.lock();
200
201 #[cfg(not(feature = "parking_lot"))]
202 let mut cache = cache.unwrap();
203
204 cache.pop()
205 }
206 .map(Ok)
207 .unwrap_or_else(|| {
208 debug!("Creating new {}", stringify!(RenderPass));
209
210 RenderPass::create(&self.device, info)
211 })?;
212
213 Ok(Lease::new(Arc::downgrade(cache_ref), item))
214 }
215}
216
217macro_rules! lease {
219 ($info:ident => $item:ident, $capacity:ident) => {
220 paste::paste! {
221 impl Pool<$info, $item> for HashPool {
222 #[profiling::function]
223 fn lease(&mut self, info: $info) -> Result<Lease<$item>, DriverError> {
224 let cache_ref = self.[<$item:snake _cache>].entry(info)
225 .or_insert_with(|| {
226 Cache::new(Mutex::new(Vec::with_capacity(self.info.$capacity)))
227 });
228 let item = {
229 #[cfg_attr(not(feature = "parking_lot"), allow(unused_mut))]
230 let mut cache = cache_ref.lock();
231
232 #[cfg(not(feature = "parking_lot"))]
233 let mut cache = cache.unwrap();
234
235 cache.pop()
236 }
237 .map(Ok)
238 .unwrap_or_else(|| {
239 debug!("Creating new {}", stringify!($item));
240
241 $item::create(&self.device, info)
242 })?;
243
244 Ok(Lease::new(Arc::downgrade(cache_ref), item))
245 }
246 }
247 }
248 };
249}
250
251lease!(AccelerationStructureInfo => AccelerationStructure, accel_struct_capacity);
252lease!(BufferInfo => Buffer, buffer_capacity);
253lease!(ImageInfo => Image, image_capacity);