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