1use crate::binding::{BindingRequirements, BindingUtil};
2use bit_set::BitSet;
3use librashader_common::map::FastHashMap;
4use librashader_common::{ImageFormat, Size};
5use librashader_reflect::reflect::semantics::BindingMeta;
6use std::collections::VecDeque;
7use std::ops::{Index, IndexMut};
8
9#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
10pub(crate) struct FramebufferKey {
11 pub size: Size<u32>,
12 pub format: ImageFormat,
13 pub mipmap: bool,
14}
15
16#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
17pub(crate) struct Slot(i32);
18
19impl Slot {
20 pub const NONE: Slot = Slot(-1);
21
22 const fn new(index: usize) -> Slot {
23 Slot(index as i32)
24 }
25
26 const fn get(self) -> Option<usize> {
28 if self.0 < 0 {
29 None
30 } else {
31 Some(self.0 as usize)
32 }
33 }
34}
35
36pub struct FramebufferPool<F> {
38 pool: Box<[F]>,
39 slots: Box<[Slot]>,
40
41 last_use: Box<[usize]>,
43}
44
45impl<F> FramebufferPool<F> {
46 pub(crate) fn prepare(&mut self, keys: &[FramebufferKey]) {
48 struct Event {
49 slot: usize,
50 key: FramebufferKey,
51 next_slot: usize,
52 }
53
54 let n = keys.len();
55
56 let mut free: FastHashMap<FramebufferKey, Vec<usize>> = FastHashMap::default();
58
59 let mut freed_at = vec![usize::MAX; n + 1];
60 let mut events: Vec<Event> = Vec::with_capacity(n);
61 let mut slot_count = 0;
62
63 for pass in 0..n {
64 let mut event = freed_at[pass];
65 while event != usize::MAX {
66 let Event {
67 slot,
68 key,
69 next_slot,
70 } = events[event];
71 free.entry(key).or_default().push(slot);
72 event = next_slot;
73 }
74
75 let key = keys[pass];
76 let slot = free.get_mut(&key).and_then(Vec::pop).unwrap_or_else(|| {
77 let slot = slot_count;
78 slot_count += 1;
79 slot
80 });
81
82 self.slots[pass] = Slot::new(slot);
83 let free_at = self.last_use[pass] + 1;
84 events.push(Event {
85 slot,
86 key,
87 next_slot: freed_at[free_at],
88 });
89 freed_at[free_at] = events.len() - 1;
90 }
91 }
92
93 pub fn contains(&self, pass: usize) -> bool {
95 self.slots.get(pass).and_then(|s| s.get()).is_some()
96 }
97}
98
99impl<F> Index<usize> for FramebufferPool<F> {
100 type Output = F;
101
102 fn index(&self, pass: usize) -> &F {
103 &self.pool[self.slots[pass].get().expect("pass has no framebuffer")]
104 }
105}
106
107impl<F> IndexMut<usize> for FramebufferPool<F> {
108 fn index_mut(&mut self, pass: usize) -> &mut F {
109 &mut self.pool[self.slots[pass].get().expect("pass has no framebuffer")]
110 }
111}
112
113pub struct FramebufferInit<'a, F, I, E> {
115 owned_generator: &'a dyn Fn() -> Result<F, E>,
116 input_generator: &'a dyn Fn() -> I,
117 requirements: BindingRequirements,
118 filters_count: usize,
119}
120
121impl<'a, F, I, E> FramebufferInit<'a, F, I, E> {
122 pub fn new(
125 filters: impl Iterator<Item = &'a BindingMeta> + ExactSizeIterator,
126 owned_generator: &'a dyn Fn() -> Result<F, E>,
127 input_generator: &'a dyn Fn() -> I,
128 ) -> Self {
129 let filters_count = filters.len();
130 let requirements = BindingMeta::calculate_requirements(filters);
131
132 Self {
133 owned_generator,
134 input_generator,
135 filters_count,
136 requirements,
137 }
138 }
139
140 pub fn init_history(&self) -> Result<(VecDeque<F>, Box<[I]>), E> {
142 init_history(
143 self.requirements.required_history,
144 self.owned_generator,
145 self.input_generator,
146 )
147 }
148
149 pub fn init_output_framebuffers(&self) -> Result<(FramebufferPool<F>, Box<[I]>), E> {
151 init_output_framebuffers(
152 self.filters_count,
153 &self.requirements.last_use,
154 self.owned_generator,
155 self.input_generator,
156 )
157 }
158
159 pub fn init_feedback_framebuffers(&self) -> Result<(FramebufferPool<F>, Box<[I]>), E> {
162 init_feedback_framebuffers(
163 self.filters_count,
164 &self.requirements.feedback_mask,
165 self.owned_generator,
166 self.input_generator,
167 )
168 }
169
170 pub const fn uses_final_pass_as_feedback(&self) -> bool {
172 self.requirements.uses_final_pass_as_feedback
173 }
174}
175
176fn init_history<'a, F, I, E>(
177 required_images: usize,
178 owned_generator: impl Fn() -> Result<F, E>,
179 input_generator: impl Fn() -> I,
180) -> Result<(VecDeque<F>, Box<[I]>), E> {
181 if required_images < 1 {
185 return Ok((VecDeque::new(), Box::new([])));
186 }
187
188 let mut framebuffers = VecDeque::with_capacity(required_images);
189 framebuffers.resize_with(required_images, owned_generator);
190
191 let framebuffers = framebuffers
192 .into_iter()
193 .collect::<Result<VecDeque<F>, E>>()?;
194
195 let mut history_textures = Vec::new();
196 history_textures.resize_with(required_images, input_generator);
197
198 Ok((framebuffers, history_textures.into_boxed_slice()))
199}
200
201fn init_output_framebuffers<F, I, E>(
202 filters_count: usize,
203 last_use: &[usize],
204 owned_generator: impl Fn() -> Result<F, E>,
205 input_generator: impl Fn() -> I,
206) -> Result<(FramebufferPool<F>, Box<[I]>), E> {
207 let mut pool = Vec::with_capacity(filters_count);
208 pool.resize_with(filters_count, &owned_generator);
209 let pool = pool
210 .into_iter()
211 .collect::<Result<Vec<F>, E>>()?
212 .into_boxed_slice();
213
214 let mut textures = Vec::new();
215 textures.resize_with(filters_count, input_generator);
216
217 Ok((
218 FramebufferPool {
219 pool,
220 last_use: last_use.to_vec().into_boxed_slice(),
221 slots: (0..filters_count).map(Slot::new).collect(),
222 },
223 textures.into_boxed_slice(),
224 ))
225}
226
227fn init_feedback_framebuffers<F, I, E>(
228 filters_count: usize,
229 feedback_mask: &BitSet,
230 owned_generator: impl Fn() -> Result<F, E>,
231 input_generator: impl Fn() -> I,
232) -> Result<(FramebufferPool<F>, Box<[I]>), E> {
233 fn assign_slots(mask: &BitSet, filters_count: usize) -> (usize, Box<[Slot]>) {
235 let mut slot_of_pass = vec![Slot::NONE; filters_count];
236 let mut count = 0;
237 for pass in mask.iter() {
238 if pass < filters_count {
239 slot_of_pass[pass] = Slot::new(count);
240 count += 1;
241 }
242 }
243 (count, slot_of_pass.into_boxed_slice())
244 }
245
246 let (count, slots) = assign_slots(feedback_mask, filters_count);
247
248 let mut pool = Vec::with_capacity(count);
249 pool.resize_with(count, owned_generator);
250 let pool = pool
251 .into_iter()
252 .collect::<Result<Vec<F>, E>>()?
253 .into_boxed_slice();
254
255 let mut textures = Vec::new();
256 textures.resize_with(filters_count, input_generator);
257
258 Ok((
259 FramebufferPool {
260 pool,
261 last_use: Box::new([]),
262 slots,
263 },
264 textures.into_boxed_slice(),
265 ))
266}
267
268#[cfg(test)]
269mod tests {
270 use super::{FramebufferKey, FramebufferPool, Slot};
271 use librashader_common::{ImageFormat, Size};
272 use std::collections::HashSet;
273
274 fn fb(last_use: Vec<usize>) -> FramebufferPool<()> {
275 let n = last_use.len();
276 FramebufferPool {
277 pool: vec![(); n].into_boxed_slice(),
278 last_use: last_use.into_boxed_slice(),
279 slots: vec![Slot::new(0); n].into_boxed_slice(),
280 }
281 }
282
283 fn key(size: Size<u32>) -> FramebufferKey {
284 FramebufferKey {
285 size,
286 format: ImageFormat::R8G8B8A8Unorm,
287 mipmap: false,
288 }
289 }
290
291 fn distinct(slots: &[Slot]) -> usize {
292 slots.iter().copied().collect::<HashSet<_>>().len()
293 }
294
295 #[test]
296 fn liveness_pools_chain() {
297 let size = |w, h| Size::<u32>::new(w, h);
298 let last_use = vec![1, 2, 10, 4, 5, 6, 7, 8, 9, 10, 10];
299 let keys = vec![
300 key(size(1280, 960)), key(size(1280, 960)), key(size(1280, 3360)), key(size(1280, 1680)), key(size(1280, 1680)), key(size(1280, 1680)), key(size(1280, 1680)), key(size(1280, 1680)), key(size(1280, 1680)), key(size(3840, 1680)), key(size(1280, 720)), ];
312
313 let mut output = fb(last_use);
314 output.prepare(&keys);
315
316 assert_eq!(distinct(&output.slots[3..=8]), 2);
319
320 assert_eq!(distinct(&output.slots), 7);
323 let mut seen: std::collections::HashMap<Slot, FramebufferKey> = Default::default();
324 for (pass, &slot) in output.slots.iter().enumerate() {
325 assert_eq!(*seen.entry(slot).or_insert(keys[pass]), keys[pass]);
326 }
327 }
328
329 #[test]
331 fn liveness_pools_uniform_chain() {
332 let keys = vec![key(Size::<u32>::new(1920, 1080)); 8];
333 let mut output = fb(vec![1, 2, 3, 4, 5, 6, 7, 7]);
334 output.prepare(&keys);
335 assert_eq!(distinct(&output.slots), 2);
336 }
337
338 #[test]
342 fn liveness_respects_format_and_mipmap() {
343 let size = Size::<u32>::new(960, 540);
344 let keys = vec![
345 FramebufferKey {
346 size,
347 format: ImageFormat::R8G8B8A8Unorm,
348 mipmap: false,
349 },
350 FramebufferKey {
351 size,
352 format: ImageFormat::R8G8B8A8Unorm,
353 mipmap: true,
354 },
355 FramebufferKey {
356 size,
357 format: ImageFormat::R16G16B16A16Sfloat,
358 mipmap: false,
359 },
360 FramebufferKey {
361 size,
362 format: ImageFormat::R8G8B8A8Unorm,
363 mipmap: false,
364 },
365 ];
366
367 let mut output = fb(vec![1, 2, 3, 3]);
368 output.prepare(&keys);
369
370 assert_eq!(output.slots[3], output.slots[0]);
372 assert_eq!(distinct(&output.slots), 3);
373 }
374}