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 //! An event provides fine-grained synchronization within a single queue, or from the host to a 11 //! queue. 12 //! 13 //! When an event is signaled from a queue using the [`set_event`] command buffer command, 14 //! an event acts similar to a [pipeline barrier], but the synchronization scopes are split: 15 //! the source synchronization scope includes only commands before the `set_event` command, 16 //! while the destination synchronization scope includes only commands after the 17 //! [`wait_events`] command. Commands in between the two are not included. 18 //! 19 //! An event can also be signaled from the host, by calling the [`set`] method directly on the 20 //! [`Event`]. 21 //! 22 //! [`set_event`]: crate::command_buffer::CommandBufferBuilder::set_event 23 //! [pipeline barrier]: crate::command_buffer::CommandBufferBuilder::pipeline_barrier 24 //! [`wait_events`]: crate::command_buffer::CommandBufferBuilder::wait_events 25 //! [`set`]: Event::set 26 27 use crate::{ 28 device::{Device, DeviceOwned}, 29 macros::impl_id_counter, 30 OomError, RequiresOneOf, VulkanError, VulkanObject, 31 }; 32 use std::{ 33 error::Error, 34 fmt::{Display, Error as FmtError, Formatter}, 35 mem::MaybeUninit, 36 num::NonZeroU64, 37 ptr, 38 sync::Arc, 39 }; 40 41 /// Used to block the GPU execution until an event on the CPU occurs. 42 /// 43 /// Note that Vulkan implementations may have limits on how long a command buffer will wait for an 44 /// event to be signaled, in order to avoid interfering with progress of other clients of the GPU. 45 /// If the event isn't signaled within these limits, results are undefined and may include 46 /// device loss. 47 #[derive(Debug)] 48 pub struct Event { 49 handle: ash::vk::Event, 50 device: Arc<Device>, 51 id: NonZeroU64, 52 must_put_in_pool: bool, 53 } 54 55 impl Event { 56 /// Creates a new `Event`. 57 /// 58 /// On [portability subset](crate::instance#portability-subset-devices-and-the-enumerate_portability-flag) 59 /// devices, the 60 /// [`events`](crate::device::Features::events) 61 /// feature must be enabled on the device. 62 #[inline] new(device: Arc<Device>, _create_info: EventCreateInfo) -> Result<Event, EventError>63 pub fn new(device: Arc<Device>, _create_info: EventCreateInfo) -> Result<Event, EventError> { 64 // VUID-vkCreateEvent-events-04468 65 if device.enabled_extensions().khr_portability_subset && !device.enabled_features().events { 66 return Err(EventError::RequirementNotMet { 67 required_for: "this device is a portability subset device, and `Event::new` was \ 68 called", 69 requires_one_of: RequiresOneOf { 70 features: &["events"], 71 ..Default::default() 72 }, 73 }); 74 } 75 76 let create_info = ash::vk::EventCreateInfo { 77 flags: ash::vk::EventCreateFlags::empty(), 78 ..Default::default() 79 }; 80 81 let handle = unsafe { 82 let mut output = MaybeUninit::uninit(); 83 let fns = device.fns(); 84 (fns.v1_0.create_event)( 85 device.handle(), 86 &create_info, 87 ptr::null(), 88 output.as_mut_ptr(), 89 ) 90 .result() 91 .map_err(VulkanError::from)?; 92 output.assume_init() 93 }; 94 95 Ok(Event { 96 handle, 97 device, 98 id: Self::next_id(), 99 must_put_in_pool: false, 100 }) 101 } 102 103 /// Takes an event from the vulkano-provided event pool. 104 /// If the pool is empty, a new event will be allocated. 105 /// Upon `drop`, the event is put back into the pool. 106 /// 107 /// For most applications, using the event pool should be preferred, 108 /// in order to avoid creating new events every frame. 109 #[inline] from_pool(device: Arc<Device>) -> Result<Event, EventError>110 pub fn from_pool(device: Arc<Device>) -> Result<Event, EventError> { 111 let handle = device.event_pool().lock().pop(); 112 let event = match handle { 113 Some(handle) => { 114 unsafe { 115 // Make sure the event isn't signaled 116 let fns = device.fns(); 117 (fns.v1_0.reset_event)(device.handle(), handle) 118 .result() 119 .map_err(VulkanError::from)?; 120 } 121 Event { 122 handle, 123 device, 124 id: Self::next_id(), 125 must_put_in_pool: true, 126 } 127 } 128 None => { 129 // Pool is empty, alloc new event 130 let mut event = Event::new(device, Default::default())?; 131 event.must_put_in_pool = true; 132 event 133 } 134 }; 135 136 Ok(event) 137 } 138 139 /// Creates a new `Event` from a raw object handle. 140 /// 141 /// # Safety 142 /// 143 /// - `handle` must be a valid Vulkan object handle created from `device`. 144 /// - `create_info` must match the info used to create the object. 145 #[inline] from_handle( device: Arc<Device>, handle: ash::vk::Event, _create_info: EventCreateInfo, ) -> Event146 pub unsafe fn from_handle( 147 device: Arc<Device>, 148 handle: ash::vk::Event, 149 _create_info: EventCreateInfo, 150 ) -> Event { 151 Event { 152 handle, 153 device, 154 id: Self::next_id(), 155 must_put_in_pool: false, 156 } 157 } 158 159 /// Returns true if the event is signaled. 160 #[inline] signaled(&self) -> Result<bool, OomError>161 pub fn signaled(&self) -> Result<bool, OomError> { 162 unsafe { 163 let fns = self.device.fns(); 164 let result = (fns.v1_0.get_event_status)(self.device.handle(), self.handle); 165 match result { 166 ash::vk::Result::EVENT_SET => Ok(true), 167 ash::vk::Result::EVENT_RESET => Ok(false), 168 err => Err(VulkanError::from(err).into()), 169 } 170 } 171 } 172 173 /// See the docs of set(). 174 #[inline] set_raw(&mut self) -> Result<(), OomError>175 pub fn set_raw(&mut self) -> Result<(), OomError> { 176 unsafe { 177 let fns = self.device.fns(); 178 (fns.v1_0.set_event)(self.device.handle(), self.handle) 179 .result() 180 .map_err(VulkanError::from)?; 181 Ok(()) 182 } 183 } 184 185 /// Changes the `Event` to the signaled state. 186 /// 187 /// If a command buffer is waiting on this event, it is then unblocked. 188 /// 189 /// # Panics 190 /// 191 /// - Panics if the device or host ran out of memory. 192 #[inline] set(&mut self)193 pub fn set(&mut self) { 194 self.set_raw().unwrap(); 195 } 196 197 /// See the docs of reset(). 198 #[inline] reset_raw(&mut self) -> Result<(), OomError>199 pub fn reset_raw(&mut self) -> Result<(), OomError> { 200 unsafe { 201 let fns = self.device.fns(); 202 (fns.v1_0.reset_event)(self.device.handle(), self.handle) 203 .result() 204 .map_err(VulkanError::from)?; 205 Ok(()) 206 } 207 } 208 209 /// Changes the `Event` to the unsignaled state. 210 /// 211 /// # Panics 212 /// 213 /// - Panics if the device or host ran out of memory. 214 #[inline] reset(&mut self)215 pub fn reset(&mut self) { 216 self.reset_raw().unwrap(); 217 } 218 } 219 220 impl Drop for Event { 221 #[inline] drop(&mut self)222 fn drop(&mut self) { 223 unsafe { 224 if self.must_put_in_pool { 225 let raw_event = self.handle; 226 self.device.event_pool().lock().push(raw_event); 227 } else { 228 let fns = self.device.fns(); 229 (fns.v1_0.destroy_event)(self.device.handle(), self.handle, ptr::null()); 230 } 231 } 232 } 233 } 234 235 unsafe impl VulkanObject for Event { 236 type Handle = ash::vk::Event; 237 238 #[inline] handle(&self) -> Self::Handle239 fn handle(&self) -> Self::Handle { 240 self.handle 241 } 242 } 243 244 unsafe impl DeviceOwned for Event { 245 #[inline] device(&self) -> &Arc<Device>246 fn device(&self) -> &Arc<Device> { 247 &self.device 248 } 249 } 250 251 impl_id_counter!(Event); 252 253 /// Parameters to create a new `Event`. 254 #[derive(Clone, Debug)] 255 pub struct EventCreateInfo { 256 pub _ne: crate::NonExhaustive, 257 } 258 259 impl Default for EventCreateInfo { 260 #[inline] default() -> Self261 fn default() -> Self { 262 Self { 263 _ne: crate::NonExhaustive(()), 264 } 265 } 266 } 267 268 #[derive(Copy, Clone, Debug, PartialEq, Eq)] 269 pub enum EventError { 270 /// Not enough memory available. 271 OomError(OomError), 272 273 RequirementNotMet { 274 required_for: &'static str, 275 requires_one_of: RequiresOneOf, 276 }, 277 } 278 279 impl Error for EventError { source(&self) -> Option<&(dyn Error + 'static)>280 fn source(&self) -> Option<&(dyn Error + 'static)> { 281 match self { 282 Self::OomError(err) => Some(err), 283 _ => None, 284 } 285 } 286 } 287 288 impl Display for EventError { fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>289 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { 290 match self { 291 Self::OomError(_) => write!(f, "not enough memory available"), 292 Self::RequirementNotMet { 293 required_for, 294 requires_one_of, 295 } => write!( 296 f, 297 "a requirement was not met for: {}; requires one of: {}", 298 required_for, requires_one_of, 299 ), 300 } 301 } 302 } 303 304 impl From<VulkanError> for EventError { from(err: VulkanError) -> Self305 fn from(err: VulkanError) -> Self { 306 match err { 307 e @ VulkanError::OutOfHostMemory | e @ VulkanError::OutOfDeviceMemory => { 308 Self::OomError(e.into()) 309 } 310 _ => panic!("unexpected error: {:?}", err), 311 } 312 } 313 } 314 315 #[cfg(test)] 316 mod tests { 317 use crate::{sync::event::Event, VulkanObject}; 318 319 #[test] event_create()320 fn event_create() { 321 let (device, _) = gfx_dev_and_queue!(); 322 let event = Event::new(device, Default::default()).unwrap(); 323 assert!(!event.signaled().unwrap()); 324 } 325 326 #[test] event_set()327 fn event_set() { 328 let (device, _) = gfx_dev_and_queue!(); 329 let mut event = Event::new(device, Default::default()).unwrap(); 330 assert!(!event.signaled().unwrap()); 331 332 event.set(); 333 assert!(event.signaled().unwrap()); 334 } 335 336 #[test] event_reset()337 fn event_reset() { 338 let (device, _) = gfx_dev_and_queue!(); 339 340 let mut event = Event::new(device, Default::default()).unwrap(); 341 event.set(); 342 assert!(event.signaled().unwrap()); 343 344 event.reset(); 345 assert!(!event.signaled().unwrap()); 346 } 347 348 #[test] event_pool()349 fn event_pool() { 350 let (device, _) = gfx_dev_and_queue!(); 351 352 assert_eq!(device.event_pool().lock().len(), 0); 353 let event1_internal_obj = { 354 let event = Event::from_pool(device.clone()).unwrap(); 355 assert_eq!(device.event_pool().lock().len(), 0); 356 event.handle() 357 }; 358 359 assert_eq!(device.event_pool().lock().len(), 1); 360 let event2 = Event::from_pool(device.clone()).unwrap(); 361 assert_eq!(device.event_pool().lock().len(), 0); 362 assert_eq!(event2.handle(), event1_internal_obj); 363 } 364 } 365