1use {
4 super::{
5 BufferHostMappingCompatibility, Cache, Lease, Pool, PoolConfig, compatible_buffer_info,
6 with_cache,
7 },
8 crate::driver::{
9 DriverError,
10 accel_struct::{AccelerationStructure, AccelerationStructureInfo},
11 buffer::{Buffer, BufferInfo},
12 cmd_buf::{CommandBuffer, CommandBufferInfo},
13 descriptor_set::{DescriptorPool, DescriptorPoolInfo},
14 device::Device,
15 image::{Image, ImageInfo},
16 render_pass::{RenderPass, RenderPassInfo},
17 },
18 log::debug,
19 std::{collections::HashMap, sync::Arc},
20};
21
22#[derive(Debug)]
49#[read_only::cast]
50pub struct FifoPool {
51 accel_struct_cache: Cache<AccelerationStructure>,
52 buffer_cache: Cache<Buffer>,
53 command_buffer_cache: HashMap<u32, Cache<CommandBuffer>>,
54 descriptor_pool_cache: Cache<DescriptorPool>,
55
56 #[readonly]
60 pub device: Device,
61
62 image_cache: Cache<Image>,
63
64 #[readonly]
68 pub info: PoolConfig,
69
70 render_pass_cache: HashMap<RenderPassInfo, Cache<RenderPass>>,
71}
72
73impl FifoPool {
74 pub fn new(device: &Device) -> Self {
76 Self::with_capacity(device, PoolConfig::default())
77 }
78
79 pub fn with_capacity(device: &Device, info: impl Into<PoolConfig>) -> Self {
81 let info: PoolConfig = info.into();
82 let device = device.clone();
83
84 Self {
85 accel_struct_cache: PoolConfig::explicit_cache(info.accel_struct_capacity),
86 buffer_cache: PoolConfig::explicit_cache(info.buffer_capacity),
87 command_buffer_cache: Default::default(),
88 descriptor_pool_cache: PoolConfig::default_cache(),
89 device,
90 image_cache: PoolConfig::explicit_cache(info.image_capacity),
91 info,
92 render_pass_cache: Default::default(),
93 }
94 }
95
96 pub fn clear(&mut self) {
98 self.clear_accel_structs();
99 self.clear_buffers();
100 self.clear_images();
101 }
102
103 pub fn clear_accel_structs(&mut self) {
105 self.accel_struct_cache = PoolConfig::explicit_cache(self.info.accel_struct_capacity);
106 }
107
108 pub fn clear_buffers(&mut self) {
110 self.buffer_cache = PoolConfig::explicit_cache(self.info.buffer_capacity);
111 }
112
113 pub fn clear_images(&mut self) {
115 self.image_cache = PoolConfig::explicit_cache(self.info.image_capacity);
116 }
117}
118
119impl Pool<AccelerationStructureInfo, AccelerationStructure> for FifoPool {
120 #[profiling::function]
121 fn resource(
122 &mut self,
123 info: AccelerationStructureInfo,
124 ) -> Result<Lease<AccelerationStructure>, DriverError> {
125 let cache_ref = Arc::downgrade(&self.accel_struct_cache);
126
127 {
128 profiling::scope!("check cache");
129
130 if let Some(item) = with_cache(&self.accel_struct_cache, |cache| {
131 for idx in 0..cache.len() {
133 let item = unsafe { cache.get_unchecked(idx) };
134 if item.info.size >= info.size
135 && item.info.acceleration_structure_type == info.acceleration_structure_type
136 {
137 let item = cache.swap_remove(idx);
138
139 return Some(Lease::new(cache_ref.clone(), item));
140 }
141 }
142
143 None
144 }) {
145 return Ok(item);
146 }
147 }
148
149 debug!("Creating new {}", stringify!(AccelerationStructure));
150
151 let item = AccelerationStructure::create(&self.device, info)?;
152
153 Ok(Lease::new(cache_ref, item))
154 }
155}
156
157impl Pool<BufferInfo, Buffer> for FifoPool {
158 #[profiling::function]
159 fn resource(&mut self, info: BufferInfo) -> Result<Lease<Buffer>, DriverError> {
160 let cache_ref = Arc::downgrade(&self.buffer_cache);
161
162 {
163 profiling::scope!("check cache");
164
165 if let Some(item) = with_cache(&self.buffer_cache, |cache| {
166 for idx in 0..cache.len() {
169 let item = unsafe { cache.get_unchecked(idx) };
170 if compatible_buffer_info(
171 &item.info,
172 &info,
173 BufferHostMappingCompatibility::Exact,
174 ) {
175 let item = cache.swap_remove(idx);
176
177 return Some(Lease::new(cache_ref.clone(), item));
178 }
179 }
180
181 None
182 }) {
183 return Ok(item);
184 }
185 }
186
187 debug!("Creating new {}", stringify!(Buffer));
188
189 let item = Buffer::create(&self.device, info)?;
190
191 Ok(Lease::new(cache_ref, item))
192 }
193}
194
195impl Pool<CommandBufferInfo, CommandBuffer> for FifoPool {
196 #[profiling::function]
197 fn resource(&mut self, info: CommandBufferInfo) -> Result<Lease<CommandBuffer>, DriverError> {
198 let cache_ref = self
199 .command_buffer_cache
200 .entry(info.queue_family_index)
201 .or_insert_with(PoolConfig::default_cache);
202
203 let item = with_cache(cache_ref, Vec::pop).map(Ok).unwrap_or_else(|| {
204 debug!("Creating new {}", stringify!(CommandBuffer));
205
206 CommandBuffer::create(&self.device, info)
207 })?;
208
209 Ok(Lease::new(Arc::downgrade(cache_ref), item))
213 }
214}
215
216impl Pool<DescriptorPoolInfo, DescriptorPool> for FifoPool {
217 #[profiling::function]
218 fn resource(&mut self, info: DescriptorPoolInfo) -> Result<Lease<DescriptorPool>, DriverError> {
219 let cache_ref = Arc::downgrade(&self.descriptor_pool_cache);
220
221 {
222 profiling::scope!("check cache");
223
224 if let Some(item) = with_cache(&self.descriptor_pool_cache, |cache| {
225 for idx in 0..cache.len() {
227 let item = unsafe { cache.get_unchecked(idx) };
228 if item.info.max_sets >= info.max_sets
229 && item.info.acceleration_structure_count
230 >= info.acceleration_structure_count
231 && item.info.combined_image_sampler_count
232 >= info.combined_image_sampler_count
233 && item.info.input_attachment_count >= info.input_attachment_count
234 && item.info.sampled_image_count >= info.sampled_image_count
235 && item.info.sampler_count >= info.sampler_count
236 && item.info.storage_buffer_count >= info.storage_buffer_count
237 && item.info.storage_buffer_dynamic_count
238 >= info.storage_buffer_dynamic_count
239 && item.info.storage_image_count >= info.storage_image_count
240 && item.info.storage_texel_buffer_count >= info.storage_texel_buffer_count
241 && item.info.uniform_buffer_count >= info.uniform_buffer_count
242 && item.info.uniform_buffer_dynamic_count
243 >= info.uniform_buffer_dynamic_count
244 && item.info.uniform_texel_buffer_count >= info.uniform_texel_buffer_count
245 {
246 let item = cache.swap_remove(idx);
247
248 return Some(Lease::new(cache_ref.clone(), item));
249 }
250 }
251
252 None
253 }) {
254 return Ok(item);
255 }
256 }
257
258 debug!("Creating new {}", stringify!(DescriptorPool));
259
260 let item = DescriptorPool::create(&self.device, info)?;
261
262 Ok(Lease::new(cache_ref, item))
263 }
264}
265
266impl Pool<ImageInfo, Image> for FifoPool {
267 #[profiling::function]
268 fn resource(&mut self, info: ImageInfo) -> Result<Lease<Image>, DriverError> {
269 let cache_ref = Arc::downgrade(&self.image_cache);
270
271 {
272 profiling::scope!("check cache");
273
274 if let Some(item) = with_cache(&self.image_cache, |cache| {
275 for idx in 0..cache.len() {
278 let item = unsafe { cache.get_unchecked(idx) };
279 if item.info.array_layer_count == info.array_layer_count
280 && item.info.alloc_dedicated == info.alloc_dedicated
281 && item.info.depth == info.depth
282 && item.info.format == info.format
283 && item.info.height == info.height
284 && item.info.mip_level_count == info.mip_level_count
285 && item.info.sample_count == info.sample_count
286 && item.info.sharing_mode == info.sharing_mode
287 && item.info.tiling == info.tiling
288 && item.info.image_type == info.image_type
289 && item.info.width == info.width
290 && item.info.flags.contains(info.flags)
291 && item.info.usage.contains(info.usage)
292 {
293 let item = cache.swap_remove(idx);
294
295 return Some(Lease::new(cache_ref.clone(), item));
296 }
297 }
298
299 None
300 }) {
301 return Ok(item);
302 }
303 }
304
305 debug!("Creating new {}", stringify!(Image));
306
307 let item = Image::create(&self.device, info)?;
308
309 Ok(Lease::new(cache_ref, item))
310 }
311}
312
313impl Pool<RenderPassInfo, RenderPass> for FifoPool {
314 #[profiling::function]
315 fn resource(&mut self, info: RenderPassInfo) -> Result<Lease<RenderPass>, DriverError> {
316 let cache_ref = if let Some(cache) = self.render_pass_cache.get(&info) {
317 cache
318 } else {
319 self.render_pass_cache
321 .entry(info.clone())
322 .or_insert_with(PoolConfig::default_cache)
323 };
324 let item = with_cache(cache_ref, |cache| cache.pop())
325 .map(Ok)
326 .unwrap_or_else(|| {
327 debug!("Creating new {}", stringify!(RenderPass));
328
329 RenderPass::create(&self.device, info)
330 })?;
331
332 Ok(Lease::new(Arc::downgrade(cache_ref), item))
333 }
334}