rafx_framework/resources/
dyn_resources.rs1use super::ResourceId;
2use crate::resources::resource_arc::ResourceWithHash;
3use crate::resources::resource_lookup::ImageResource;
4use crate::resources::ResourceArc;
5use crate::ResourceDropSink;
6use crate::{BufferResource, ImageViewResource};
7use crossbeam_channel::{Receiver, Sender};
8use rafx_api::RafxTexture;
9use rafx_api::{RafxBuffer, RafxDeviceContext, RafxResult, RafxTextureBindType};
10use std::hash::Hash;
11use std::sync::atomic::{AtomicU32, AtomicU64, Ordering};
12use std::sync::Arc;
13
14#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
15pub struct DynResourceIndex(u64);
16
17impl From<ResourceId> for DynResourceIndex {
18 fn from(resource_id: ResourceId) -> Self {
19 DynResourceIndex(resource_id.0)
20 }
21}
22
23impl Into<ResourceId> for DynResourceIndex {
24 fn into(self) -> ResourceId {
25 ResourceId(self.0)
26 }
27}
28
29pub struct DynResourceAllocatorInner<ResourceT>
38where
39 ResourceT: Clone,
40{
41 drop_tx: Sender<ResourceWithHash<ResourceT>>,
42 next_index: AtomicU64,
43 active_count: Arc<AtomicU32>,
44}
45
46pub struct DynResourceAllocator<ResourceT>
47where
48 ResourceT: Clone,
49{
50 inner: Arc<DynResourceAllocatorInner<ResourceT>>,
51}
52
53impl<ResourceT> DynResourceAllocator<ResourceT>
54where
55 ResourceT: Clone + std::fmt::Debug,
56{
57 fn new(
58 drop_tx: Sender<ResourceWithHash<ResourceT>>,
59 allocator_index: u32,
60 active_count: Arc<AtomicU32>,
61 ) -> Self {
62 let next_index = ((allocator_index as u64) << 32) + 1;
63
64 let inner = DynResourceAllocatorInner {
65 drop_tx,
66 next_index: AtomicU64::new(next_index),
67 active_count,
68 };
69
70 DynResourceAllocator {
71 inner: Arc::new(inner),
72 }
73 }
74
75 fn insert(
76 &self,
77 resource: ResourceT,
78 ) -> ResourceArc<ResourceT> {
79 let resource_index =
83 DynResourceIndex(self.inner.next_index.fetch_add(1, Ordering::Relaxed));
84 self.inner.active_count.fetch_add(1, Ordering::Relaxed);
85
86 log::trace!(
87 "insert resource {} {:?}",
88 core::any::type_name::<ResourceT>(),
89 resource
90 );
91
92 ResourceArc::new(resource, resource_index.into(), self.inner.drop_tx.clone())
93 }
94}
95
96pub struct DynResourceAllocatorManagerInner<ResourceT>
97where
98 ResourceT: Clone,
99{
100 drop_tx: Sender<ResourceWithHash<ResourceT>>,
101 drop_rx: Receiver<ResourceWithHash<ResourceT>>,
102 next_allocator_index: AtomicU32,
103 active_count: Arc<AtomicU32>,
104}
105
106impl<ResourceT> DynResourceAllocatorManagerInner<ResourceT>
107where
108 ResourceT: Clone + std::fmt::Debug,
109{
110 fn create_allocator(&self) -> DynResourceAllocator<ResourceT> {
111 let allocator_index = self.next_allocator_index.fetch_add(1, Ordering::Relaxed);
112 DynResourceAllocator::new(
113 self.drop_tx.clone(),
114 allocator_index,
115 self.active_count.clone(),
116 )
117 }
118}
119
120pub struct DynResourceAllocatorProvider<ResourceT>
121where
122 ResourceT: Clone,
123{
124 inner: Arc<DynResourceAllocatorManagerInner<ResourceT>>,
125}
126
127impl<ResourceT> DynResourceAllocatorProvider<ResourceT>
128where
129 ResourceT: Clone + std::fmt::Debug,
130{
131 fn create_allocator(&self) -> DynResourceAllocator<ResourceT> {
132 self.inner.create_allocator()
133 }
134}
135
136pub struct DynResourceAllocatorManager<ResourceT>
137where
138 ResourceT: Clone,
139{
140 inner: Arc<DynResourceAllocatorManagerInner<ResourceT>>,
141 drop_sink: ResourceDropSink<ResourceT>,
142}
143
144impl<ResourceT> DynResourceAllocatorManager<ResourceT>
145where
146 ResourceT: Clone + std::fmt::Debug,
147{
148 fn new(max_frames_in_flight: u32) -> Self {
149 let (drop_tx, drop_rx) = crossbeam_channel::unbounded();
150 let drop_sink = ResourceDropSink::new(max_frames_in_flight);
151
152 let inner = DynResourceAllocatorManagerInner {
153 drop_tx,
154 drop_rx,
155 next_allocator_index: AtomicU32::new(1),
156 active_count: Arc::new(AtomicU32::new(0)),
157 };
158
159 DynResourceAllocatorManager {
160 inner: Arc::new(inner),
161 drop_sink,
162 }
163 }
164
165 fn create_allocator(&self) -> DynResourceAllocator<ResourceT> {
166 self.inner.create_allocator()
167 }
168
169 fn create_allocator_provider(&self) -> DynResourceAllocatorProvider<ResourceT> {
170 DynResourceAllocatorProvider {
171 inner: self.inner.clone(),
172 }
173 }
174
175 fn handle_dropped_resources(&mut self) {
176 for dropped in self.inner.drop_rx.try_iter() {
177 log::trace!(
178 "dropping {} {:?}",
179 core::any::type_name::<ResourceT>(),
180 dropped.resource
181 );
182 self.drop_sink.retire(dropped.resource);
183 self.inner.active_count.fetch_sub(1, Ordering::Relaxed);
184 }
185 }
186
187 #[profiling::function]
188 fn on_frame_complete(&mut self) -> RafxResult<()> {
189 self.handle_dropped_resources();
190 self.drop_sink.on_frame_complete()?;
191 Ok(())
192 }
193
194 fn destroy(&mut self) -> RafxResult<()> {
195 self.handle_dropped_resources();
196
197 if self.len() > 0 {
198 log::warn!(
199 "{} resource count {} > 0, resources will leak",
200 core::any::type_name::<ResourceT>(),
201 self.len()
202 );
203 }
204
205 self.drop_sink.destroy()?;
206 Ok(())
207 }
208
209 fn len(&self) -> usize {
210 self.inner.active_count.load(Ordering::Relaxed) as usize
211 }
212}
213
214pub struct DynResourceAllocatorSet {
216 pub device_context: RafxDeviceContext,
217 pub images: DynResourceAllocator<ImageResource>,
218 pub image_views: DynResourceAllocator<ImageViewResource>,
219 pub buffers: DynResourceAllocator<BufferResource>,
220}
221
222impl DynResourceAllocatorSet {
223 pub fn insert_texture(
224 &self,
225 image: RafxTexture,
226 ) -> ResourceArc<ImageResource> {
227 let image_resource = ImageResource {
228 image_key: None,
229 image,
230 };
231 self.images.insert(image_resource)
232 }
233
234 pub fn insert_image_view(
235 &self,
236 image: &ResourceArc<ImageResource>,
237 texture_bind_type: Option<RafxTextureBindType>,
238 ) -> RafxResult<ResourceArc<ImageViewResource>> {
239 Ok(self.insert_image_view_raw(image.clone(), texture_bind_type))
240 }
241
242 pub fn insert_image_view_raw(
243 &self,
244 image: ResourceArc<ImageResource>,
245 texture_bind_type: Option<RafxTextureBindType>,
246 ) -> ResourceArc<ImageViewResource> {
247 let image_view_resource = ImageViewResource {
248 image,
249 texture_bind_type,
250 image_view_key: None,
251 };
252
253 self.image_views.insert(image_view_resource)
254 }
255
256 pub fn insert_buffer(
257 &self,
258 buffer: RafxBuffer,
259 ) -> ResourceArc<BufferResource> {
260 let buffer_resource = BufferResource {
261 buffer_key: None,
262 buffer: Arc::new(buffer),
263 };
264
265 self.buffers.insert(buffer_resource)
266 }
267}
268
269#[derive(Debug)]
270pub struct ResourceMetrics {
271 pub image_count: usize,
272 pub image_view_count: usize,
273 pub buffer_count: usize,
274}
275
276pub struct DynResourceAllocatorSetProvider {
277 pub device_context: RafxDeviceContext,
278 pub images: DynResourceAllocatorProvider<ImageResource>,
279 pub image_views: DynResourceAllocatorProvider<ImageViewResource>,
280 pub buffers: DynResourceAllocatorProvider<BufferResource>,
281}
282
283impl DynResourceAllocatorSetProvider {
284 pub fn get_allocator(&self) -> DynResourceAllocatorSet {
285 DynResourceAllocatorSet {
286 device_context: self.device_context.clone(),
287 images: self.images.create_allocator(),
288 image_views: self.image_views.create_allocator(),
289 buffers: self.buffers.create_allocator(),
290 }
291 }
292}
293
294pub struct DynResourceAllocatorSetManager {
295 pub device_context: RafxDeviceContext,
296 pub images: DynResourceAllocatorManager<ImageResource>,
297 pub image_views: DynResourceAllocatorManager<ImageViewResource>,
298 pub buffers: DynResourceAllocatorManager<BufferResource>,
299}
300
301impl DynResourceAllocatorSetManager {
302 pub fn new(
303 device_context: &RafxDeviceContext,
304 max_frames_in_flight: u32,
305 ) -> Self {
306 DynResourceAllocatorSetManager {
307 device_context: device_context.clone(),
308 images: DynResourceAllocatorManager::new(max_frames_in_flight),
309 image_views: DynResourceAllocatorManager::new(max_frames_in_flight),
310 buffers: DynResourceAllocatorManager::new(max_frames_in_flight),
311 }
312 }
313
314 pub fn create_allocator_provider(&self) -> DynResourceAllocatorSetProvider {
315 DynResourceAllocatorSetProvider {
316 device_context: self.device_context.clone(),
317 images: self.images.create_allocator_provider(),
318 image_views: self.image_views.create_allocator_provider(),
319 buffers: self.buffers.create_allocator_provider(),
320 }
321 }
322
323 pub fn get_allocator(&self) -> DynResourceAllocatorSet {
324 DynResourceAllocatorSet {
325 device_context: self.device_context.clone(),
326 images: self.images.create_allocator(),
327 image_views: self.image_views.create_allocator(),
328 buffers: self.buffers.create_allocator(),
329 }
330 }
331
332 #[profiling::function]
333 pub fn on_frame_complete(&mut self) -> RafxResult<()> {
334 self.buffers.on_frame_complete()?;
335 self.images.on_frame_complete()?;
336 self.image_views.on_frame_complete()?;
337 Ok(())
338 }
339
340 pub fn destroy(&mut self) -> RafxResult<()> {
341 self.image_views.destroy()?;
344 self.images.destroy()?;
345 self.buffers.destroy()?;
346 Ok(())
347 }
348
349 pub fn metrics(&self) -> ResourceMetrics {
350 ResourceMetrics {
351 image_count: self.images.len(),
352 image_view_count: self.image_views.len(),
353 buffer_count: self.buffers.len(),
354 }
355 }
356}