1use smallvec::SmallVec;
7use std::cell::RefCell;
8use std::ops::Range;
9
10use crate::context::CommandContext;
11use crate::sync::{self, LinearSyncFence};
12
13pub struct Fences {
15 fences: RefCell<SmallVec<[(Range<usize>, LinearSyncFence); 16]>>,
16}
17
18impl Fences {
19 pub fn new() -> Fences {
21 Fences {
22 fences: RefCell::new(SmallVec::new()),
23 }
24 }
25
26 #[inline]
28 pub fn inserter(&self, range: Range<usize>) -> Inserter<'_> {
29 Inserter {
30 fences: self,
31 range,
32 }
33 }
34
35 pub fn wait(&self, ctxt: &mut CommandContext<'_>, range: Range<usize>) {
37 let mut existing_fences = self.fences.borrow_mut();
38 let mut new_fences = SmallVec::new();
39
40 for existing in existing_fences.drain(..) {
41 if (existing.0.start >= range.start && existing.0.start < range.end) ||
42 (existing.0.end > range.start && existing.0.end < range.end)
43 {
44 unsafe { sync::wait_linear_sync_fence_and_drop(existing.1, ctxt) };
45 } else {
46 new_fences.push(existing);
47 }
48 }
49
50 *existing_fences = new_fences;
51 }
52
53 pub fn clean(&mut self, ctxt: &mut CommandContext<'_>) {
55 let mut fences = self.fences.borrow_mut();
56 for (_, sync) in fences.drain(..) {
57 unsafe { sync::destroy_linear_sync_fence(ctxt, sync) };
58 }
59 }
60}
61
62pub struct Inserter<'a> {
64 fences: &'a Fences,
65 range: Range<usize>,
66}
67
68impl<'a> Inserter<'a> {
69 pub fn insert(self, ctxt: &mut CommandContext<'_>) {
71 let mut new_fences = SmallVec::new();
72
73 let mut written = false;
74
75 let mut existing_fences = self.fences.fences.borrow_mut();
76 for existing in existing_fences.drain(..) {
77 if existing.0.start < self.range.start && existing.0.end <= self.range.start {
78 new_fences.push(existing);
79
80 } else if existing.0.start < self.range.start && existing.0.end >= self.range.end {
81 let new_fence = unsafe { sync::new_linear_sync_fence(ctxt).unwrap() };
84 new_fences.push((existing.0.start .. self.range.start, existing.1));
85 new_fences.push((self.range.start .. existing.0.end, new_fence));
86 written = true;
87
88 } else if existing.0.start < self.range.start && existing.0.end >= self.range.start {
89 new_fences.push((existing.0.start .. self.range.start, existing.1));
90 if !written {
91 let new_fence = unsafe { sync::new_linear_sync_fence(ctxt).unwrap() };
92 new_fences.push((self.range.clone(), new_fence));
93 written = true;
94 }
95
96 } else if existing.0.start >= self.range.start && existing.0.end <= self.range.end {
97 unsafe { sync::destroy_linear_sync_fence(ctxt, existing.1) };
98 if !written {
99 let new_fence = unsafe { sync::new_linear_sync_fence(ctxt).unwrap() };
100 new_fences.push((self.range.clone(), new_fence));
101 written = true;
102 }
103
104 } else if existing.0.start >= self.range.end {
105 if !written {
106 let new_fence = unsafe { sync::new_linear_sync_fence(ctxt).unwrap() };
107 new_fences.push((self.range.clone(), new_fence));
108 written = true;
109 }
110
111 new_fences.push(existing);
112
113 } else {
114 if !written {
115 let new_fence = unsafe { sync::new_linear_sync_fence(ctxt).unwrap() };
116 new_fences.push((self.range.clone(), new_fence));
117 written = true;
118 }
119
120 new_fences.push((self.range.end .. existing.0.end, existing.1));
121 }
122 }
123
124 if !written {
125 let new_fence = unsafe { sync::new_linear_sync_fence(ctxt).unwrap() };
126 new_fences.push((self.range, new_fence));
127 }
128
129 *existing_fences = new_fences;
130 }
131}