1use alloc::{sync::Arc, vec::Vec};
2use core::sync::atomic::Ordering;
3use parking_lot::RwLock;
4
5use glow::HasContext;
6
7use crate::AtomicFenceValue;
8
9#[derive(Debug)]
10struct GLFence {
11 sync: Arc<glow::Fence>,
20 value: crate::FenceValue,
21}
22
23#[derive(Debug)]
24pub struct Fence {
25 last_completed: AtomicFenceValue,
26 pending: RwLock<Vec<GLFence>>,
27 fence_behavior: wgt::GlFenceBehavior,
28}
29
30impl crate::DynFence for Fence {}
31
32#[cfg(send_sync)]
33unsafe impl Send for Fence {}
34#[cfg(send_sync)]
35unsafe impl Sync for Fence {}
36
37impl Fence {
38 pub fn new(options: &wgt::GlBackendOptions) -> Self {
39 Self {
40 last_completed: AtomicFenceValue::new(0),
41 pending: RwLock::new(Vec::new()),
42 fence_behavior: options.fence_behavior,
43 }
44 }
45
46 pub fn signal(
47 &self,
48 gl: &glow::Context,
49 value: crate::FenceValue,
50 ) -> Result<(), crate::DeviceError> {
51 if self.fence_behavior.is_auto_finish() {
52 self.last_completed.store(value, Ordering::Release);
53 return Ok(());
54 }
55
56 let sync = unsafe { gl.fence_sync(glow::SYNC_GPU_COMMANDS_COMPLETE, 0) }
57 .map_err(|_| crate::DeviceError::OutOfMemory)?;
58 self.pending.write().push(GLFence {
59 sync: Arc::new(sync),
60 value,
61 });
62
63 Ok(())
64 }
65
66 pub fn satisfied(&self, value: crate::FenceValue) -> bool {
67 self.last_completed.load(Ordering::Acquire) >= value
68 }
69
70 pub fn get_latest(&self, gl: &glow::Context) -> crate::FenceValue {
71 let mut max_value = self.last_completed.load(Ordering::Acquire);
72
73 if self.fence_behavior.is_auto_finish() {
74 return max_value;
75 }
76
77 let pending = self.pending.read();
78
79 for gl_fence in pending.iter() {
80 if gl_fence.value <= max_value {
81 continue;
83 }
84 let status = unsafe { gl.get_sync_status(*gl_fence.sync) };
86 if status == glow::SIGNALED {
87 max_value = gl_fence.value;
88 } else {
89 break;
91 }
92 }
93
94 self.last_completed.fetch_max(max_value, Ordering::AcqRel);
96
97 max_value
98 }
99
100 pub fn maintain(&self, gl: &glow::Context) {
101 if self.fence_behavior.is_auto_finish() {
102 return;
103 }
104
105 let latest = self.get_latest(gl);
106 let mut pending = self.pending.write();
107 pending.retain_mut(|gl_fence| {
108 if gl_fence.value > latest {
109 true
110 } else if let Some(fence) = Arc::get_mut(&mut gl_fence.sync) {
111 unsafe {
112 gl.delete_sync(*fence);
113 }
114 false
115 } else {
116 true
121 }
122 });
123 }
124
125 pub fn wait(
126 &self,
127 gl: &glow::Context,
128 wait_value: crate::FenceValue,
129 timeout_ns: u32,
130 ) -> Result<bool, crate::DeviceError> {
131 let last_completed = self.last_completed.load(Ordering::Acquire);
132
133 if self.fence_behavior.is_auto_finish() {
134 return Ok(last_completed >= wait_value);
135 }
136
137 if last_completed >= wait_value {
139 return Ok(true);
140 }
141
142 let pending = self.pending.read();
143
144 let gl_fence = pending.iter().find(|gl_fence| gl_fence.value >= wait_value);
146
147 let Some(gl_fence) = gl_fence else {
148 log::warn!("Tried to wait for {wait_value} but that value has not been signalled yet");
149 return Ok(false);
150 };
151
152 let sync = gl_fence.sync.clone();
154 let fence_value = gl_fence.value;
155
156 drop(pending);
157
158 let status = unsafe {
159 gl.client_wait_sync(
160 *sync,
161 glow::SYNC_FLUSH_COMMANDS_BIT,
162 timeout_ns.min(i32::MAX as u32) as i32,
163 )
164 };
165
166 drop(sync);
167
168 let signalled = match status {
169 glow::ALREADY_SIGNALED | glow::CONDITION_SATISFIED => true,
170 glow::TIMEOUT_EXPIRED | glow::WAIT_FAILED => false,
171 _ => {
172 log::warn!("Unexpected result from client_wait_sync: {status}");
173 false
174 }
175 };
176
177 if signalled {
178 self.last_completed.fetch_max(fence_value, Ordering::AcqRel);
179 }
180
181 Ok(signalled)
182 }
183
184 pub fn destroy(self, gl: &glow::Context) {
185 if self.fence_behavior.is_auto_finish() {
186 return;
187 }
188
189 for gl_fence in self.pending.into_inner() {
190 unsafe {
191 gl.delete_sync(
192 Arc::into_inner(gl_fence.sync)
193 .expect("A function has failed to drop all its references to this"),
194 );
195 }
196 }
197 }
198}