• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2016 The vulkano developers
2 // Licensed under the Apache License, Version 2.0
3 // <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
6 // at your option. All files in the project carrying such
7 // notice may not be copied, modified, or distributed except
8 // according to those terms.
9 
10 use crate::check_errors;
11 use crate::device::Device;
12 use crate::device::DeviceOwned;
13 use crate::OomError;
14 use crate::Success;
15 use crate::VulkanObject;
16 use std::mem::MaybeUninit;
17 use std::ptr;
18 use std::sync::Arc;
19 
20 /// Used to block the GPU execution until an event on the CPU occurs.
21 ///
22 /// Note that Vulkan implementations may have limits on how long a command buffer will wait for an
23 /// event to be signaled, in order to avoid interfering with progress of other clients of the GPU.
24 /// If the event isn't signaled within these limits, results are undefined and may include
25 /// device loss.
26 #[derive(Debug)]
27 pub struct Event {
28     // The event.
29     event: ash::vk::Event,
30     // The device.
31     device: Arc<Device>,
32     must_put_in_pool: bool,
33 }
34 
35 impl Event {
36     /// Takes an event from the vulkano-provided event pool.
37     /// If the pool is empty, a new event will be allocated.
38     /// Upon `drop`, the event is put back into the pool.
39     ///
40     /// For most applications, using the event pool should be preferred,
41     /// in order to avoid creating new events every frame.
from_pool(device: Arc<Device>) -> Result<Event, OomError>42     pub fn from_pool(device: Arc<Device>) -> Result<Event, OomError> {
43         let maybe_raw_event = device.event_pool().lock().unwrap().pop();
44         match maybe_raw_event {
45             Some(raw_event) => {
46                 unsafe {
47                     // Make sure the event isn't signaled
48                     let fns = device.fns();
49                     check_errors(fns.v1_0.reset_event(device.internal_object(), raw_event))?;
50                 }
51                 Ok(Event {
52                     event: raw_event,
53                     device: device,
54                     must_put_in_pool: true,
55                 })
56             }
57             None => {
58                 // Pool is empty, alloc new event
59                 Event::alloc_impl(device, true)
60             }
61         }
62     }
63 
64     /// Builds a new event.
65     #[inline]
alloc(device: Arc<Device>) -> Result<Event, OomError>66     pub fn alloc(device: Arc<Device>) -> Result<Event, OomError> {
67         Event::alloc_impl(device, false)
68     }
69 
alloc_impl(device: Arc<Device>, must_put_in_pool: bool) -> Result<Event, OomError>70     fn alloc_impl(device: Arc<Device>, must_put_in_pool: bool) -> Result<Event, OomError> {
71         let event = unsafe {
72             let infos = ash::vk::EventCreateInfo {
73                 flags: ash::vk::EventCreateFlags::empty(),
74                 ..Default::default()
75             };
76 
77             let mut output = MaybeUninit::uninit();
78             let fns = device.fns();
79             check_errors(fns.v1_0.create_event(
80                 device.internal_object(),
81                 &infos,
82                 ptr::null(),
83                 output.as_mut_ptr(),
84             ))?;
85             output.assume_init()
86         };
87 
88         Ok(Event {
89             device: device,
90             event: event,
91             must_put_in_pool: must_put_in_pool,
92         })
93     }
94 
95     /// Returns true if the event is signaled.
96     #[inline]
signaled(&self) -> Result<bool, OomError>97     pub fn signaled(&self) -> Result<bool, OomError> {
98         unsafe {
99             let fns = self.device.fns();
100             let result = check_errors(
101                 fns.v1_0
102                     .get_event_status(self.device.internal_object(), self.event),
103             )?;
104             match result {
105                 Success::EventSet => Ok(true),
106                 Success::EventReset => Ok(false),
107                 _ => unreachable!(),
108             }
109         }
110     }
111 
112     /// See the docs of set().
113     #[inline]
set_raw(&mut self) -> Result<(), OomError>114     pub fn set_raw(&mut self) -> Result<(), OomError> {
115         unsafe {
116             let fns = self.device.fns();
117             check_errors(
118                 fns.v1_0
119                     .set_event(self.device.internal_object(), self.event),
120             )?;
121             Ok(())
122         }
123     }
124 
125     /// Changes the `Event` to the signaled state.
126     ///
127     /// If a command buffer is waiting on this event, it is then unblocked.
128     ///
129     /// # Panic
130     ///
131     /// - Panics if the device or host ran out of memory.
132     ///
133     #[inline]
set(&mut self)134     pub fn set(&mut self) {
135         self.set_raw().unwrap();
136     }
137 
138     /// See the docs of reset().
139     #[inline]
reset_raw(&mut self) -> Result<(), OomError>140     pub fn reset_raw(&mut self) -> Result<(), OomError> {
141         unsafe {
142             let fns = self.device.fns();
143             check_errors(
144                 fns.v1_0
145                     .reset_event(self.device.internal_object(), self.event),
146             )?;
147             Ok(())
148         }
149     }
150 
151     /// Changes the `Event` to the unsignaled state.
152     ///
153     /// # Panic
154     ///
155     /// - Panics if the device or host ran out of memory.
156     ///
157     #[inline]
reset(&mut self)158     pub fn reset(&mut self) {
159         self.reset_raw().unwrap();
160     }
161 }
162 
163 unsafe impl DeviceOwned for Event {
164     #[inline]
device(&self) -> &Arc<Device>165     fn device(&self) -> &Arc<Device> {
166         &self.device
167     }
168 }
169 
170 unsafe impl VulkanObject for Event {
171     type Object = ash::vk::Event;
172 
173     #[inline]
internal_object(&self) -> ash::vk::Event174     fn internal_object(&self) -> ash::vk::Event {
175         self.event
176     }
177 }
178 
179 impl Drop for Event {
180     #[inline]
drop(&mut self)181     fn drop(&mut self) {
182         unsafe {
183             if self.must_put_in_pool {
184                 let raw_event = self.event;
185                 self.device.event_pool().lock().unwrap().push(raw_event);
186             } else {
187                 let fns = self.device.fns();
188                 fns.v1_0
189                     .destroy_event(self.device.internal_object(), self.event, ptr::null());
190             }
191         }
192     }
193 }
194 
195 #[cfg(test)]
196 mod tests {
197     use crate::sync::Event;
198     use crate::VulkanObject;
199 
200     #[test]
event_create()201     fn event_create() {
202         let (device, _) = gfx_dev_and_queue!();
203         let event = Event::alloc(device).unwrap();
204         assert!(!event.signaled().unwrap());
205     }
206 
207     #[test]
event_set()208     fn event_set() {
209         let (device, _) = gfx_dev_and_queue!();
210         let mut event = Event::alloc(device).unwrap();
211         assert!(!event.signaled().unwrap());
212 
213         event.set();
214         assert!(event.signaled().unwrap());
215     }
216 
217     #[test]
event_reset()218     fn event_reset() {
219         let (device, _) = gfx_dev_and_queue!();
220 
221         let mut event = Event::alloc(device).unwrap();
222         event.set();
223         assert!(event.signaled().unwrap());
224 
225         event.reset();
226         assert!(!event.signaled().unwrap());
227     }
228 
229     #[test]
event_pool()230     fn event_pool() {
231         let (device, _) = gfx_dev_and_queue!();
232 
233         assert_eq!(device.event_pool().lock().unwrap().len(), 0);
234         let event1_internal_obj = {
235             let event = Event::from_pool(device.clone()).unwrap();
236             assert_eq!(device.event_pool().lock().unwrap().len(), 0);
237             event.internal_object()
238         };
239 
240         assert_eq!(device.event_pool().lock().unwrap().len(), 1);
241         let event2 = Event::from_pool(device.clone()).unwrap();
242         assert_eq!(device.event_pool().lock().unwrap().len(), 0);
243         assert_eq!(event2.internal_object(), event1_internal_obj);
244     }
245 }
246