1 // Copyright (c) 2022 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 super::{CommandBufferBuilder, RenderPassStateType}; 11 use crate::{ 12 command_buffer::allocator::CommandBufferAllocator, 13 device::{DeviceOwned, QueueFlags}, 14 image::{ImageAspects, ImageCreateFlags, ImageLayout, ImageUsage}, 15 sync::{ 16 event::Event, AccessFlags, BufferMemoryBarrier, DependencyFlags, DependencyInfo, 17 ImageMemoryBarrier, MemoryBarrier, PipelineStages, QueueFamilyOwnershipTransfer, Sharing, 18 }, 19 DeviceSize, RequirementNotMet, RequiresOneOf, Version, VulkanObject, 20 }; 21 use smallvec::SmallVec; 22 use std::{ 23 cmp::max, 24 error::Error, 25 fmt::{Display, Error as FmtError, Formatter}, 26 ptr, 27 sync::Arc, 28 }; 29 30 impl<L, A> CommandBufferBuilder<L, A> 31 where 32 A: CommandBufferAllocator, 33 { 34 /// Inserts a memory dependency into the queue. 35 /// 36 /// A pipeline barrier is the primary means of synchronizing work within a single queue. 37 /// Without a pipeline barrier, all commands in a queue could complete out of order, and there 38 /// would be no guarantee about the ordering of memory accesses. When a dependency is inserted, 39 /// a chosen subset of operations after the barrier (the destination synchronization scope) 40 /// depend on, and therefore must wait for the completion of, a chosen subset operations before 41 /// barrier (the source synchronization scope). 42 /// 43 /// When the queue has to wait, it may not be doing useful work, so barriers should be kept to 44 /// the minimum needed to ensure proper functioning. Overly broad barriers, specifying 45 /// a larger class of operations than needed (especially [`ALL_COMMANDS`]), can slow down the 46 /// queue and make it work less efficiently. 47 /// 48 /// In addition to ensuring correct operation, pipeline barriers are also used to transition 49 /// images (or parts of images) from one [image layout] to another. 50 /// 51 /// # Safety 52 /// 53 /// - All images that are accessed by the command must be in the expected image layout. 54 /// - For each element of `dependency_info.image_memory_barriers` that contains an image layout 55 /// transition, which is a write operation, the barrier must be defined appropriately to 56 /// ensure no memory access hazard occurs. 57 /// 58 /// [`ALL_COMMANDS`]: PipelineStages::ALL_COMMANDS 59 /// [image layout]: ImageLayout 60 #[inline] pipeline_barrier( &mut self, dependency_info: DependencyInfo, ) -> Result<&mut Self, SynchronizationError>61 pub unsafe fn pipeline_barrier( 62 &mut self, 63 dependency_info: DependencyInfo, 64 ) -> Result<&mut Self, SynchronizationError> { 65 self.validate_pipeline_barrier(&dependency_info)?; 66 67 unsafe { Ok(self.pipeline_barrier_unchecked(dependency_info)) } 68 } 69 validate_pipeline_barrier( &self, dependency_info: &DependencyInfo, ) -> Result<(), SynchronizationError>70 fn validate_pipeline_barrier( 71 &self, 72 dependency_info: &DependencyInfo, 73 ) -> Result<(), SynchronizationError> { 74 let device = self.device(); 75 let queue_family_properties = self.queue_family_properties(); 76 77 // VUID-vkCmdPipelineBarrier2-commandBuffer-cmdpool 78 if !queue_family_properties.queue_flags.intersects( 79 QueueFlags::TRANSFER 80 | QueueFlags::GRAPHICS 81 | QueueFlags::COMPUTE 82 | QueueFlags::VIDEO_DECODE 83 | QueueFlags::VIDEO_ENCODE, 84 ) { 85 return Err(SynchronizationError::NotSupportedByQueueFamily); 86 } 87 88 let &DependencyInfo { 89 dependency_flags, 90 ref memory_barriers, 91 ref buffer_memory_barriers, 92 ref image_memory_barriers, 93 _ne: _, 94 } = dependency_info; 95 96 // VUID-VkDependencyInfo-dependencyFlags-parameter 97 dependency_flags.validate_device(device)?; 98 99 let check_stages_access = |ty: char, 100 barrier_index: usize, 101 src_stages: PipelineStages, 102 src_access: AccessFlags, 103 dst_stages: PipelineStages, 104 dst_access: AccessFlags| 105 -> Result<(), SynchronizationError> { 106 for (stages, access) in [(src_stages, src_access), (dst_stages, dst_access)] { 107 // VUID-vkCmdPipelineBarrier2-synchronization2-03848 108 if !device.enabled_features().synchronization2 { 109 if stages.is_2() { 110 return Err(SynchronizationError::RequirementNotMet { 111 required_for: "One of `dependency_info.memory_barriers`, \ 112 `dependency_info.buffer_memory_barriers` or \ 113 `dependency_info.image_memory_barriers` has an element where \ 114 `src_stages` or `dst_stages` contains flags from \ 115 `VkPipelineStageFlagBits2`", 116 requires_one_of: RequiresOneOf { 117 features: &["synchronization2"], 118 ..Default::default() 119 }, 120 }); 121 } 122 123 if access.is_2() { 124 return Err(SynchronizationError::RequirementNotMet { 125 required_for: "One of `dependency_info.memory_barriers`, \ 126 `dependency_info.buffer_memory_barriers` or \ 127 `dependency_info.image_memory_barriers` has an element where \ 128 `src_access` or `dst_access` contains flags from \ 129 `VkAccessFlagBits2`", 130 requires_one_of: RequiresOneOf { 131 features: &["synchronization2"], 132 ..Default::default() 133 }, 134 }); 135 } 136 } 137 138 // VUID-VkMemoryBarrier2-srcStageMask-parameter 139 // VUID-VkMemoryBarrier2-dstStageMask-parameter 140 // VUID-VkBufferMemoryBarrier2-srcStageMask-parameter 141 // VUID-VkBufferMemoryBarrier2-dstStageMask-parameter 142 // VUID-VkImageMemoryBarrier2-srcStageMask-parameter 143 // VUID-VkImageMemoryBarrier2-dstStageMask-parameter 144 stages.validate_device(device)?; 145 146 // VUID-VkMemoryBarrier2-srcAccessMask-parameter 147 // VUID-VkMemoryBarrier2-dstAccessMask-parameter 148 // VUID-VkBufferMemoryBarrier2-srcAccessMask-parameter 149 // VUID-VkBufferMemoryBarrier2-dstAccessMask-parameter 150 // VUID-VkImageMemoryBarrier2-srcAccessMask-parameter 151 // VUID-VkImageMemoryBarrier2-dstAccessMask-parameter 152 access.validate_device(device)?; 153 154 // VUID-vkCmdPipelineBarrier2-srcStageMask-03849 155 // VUID-vkCmdPipelineBarrier2-dstStageMask-03850 156 if !PipelineStages::from(queue_family_properties.queue_flags).contains(stages) { 157 match ty { 158 'm' => { 159 return Err(SynchronizationError::MemoryBarrierStageNotSupported { 160 barrier_index, 161 }) 162 } 163 'b' => { 164 return Err( 165 SynchronizationError::BufferMemoryBarrierStageNotSupported { 166 barrier_index, 167 }, 168 ) 169 } 170 'i' => { 171 return Err(SynchronizationError::ImageMemoryBarrierStageNotSupported { 172 barrier_index, 173 }) 174 } 175 _ => unreachable!(), 176 } 177 } 178 179 // VUID-VkMemoryBarrier2-srcStageMask-03929 180 // VUID-VkMemoryBarrier2-dstStageMask-03929 181 // VUID-VkBufferMemoryBarrier2-srcStageMask-03929 182 // VUID-VkBufferMemoryBarrier2-dstStageMask-03929 183 // VUID-VkImageMemoryBarrier2-srcStageMask-03930 184 // VUID-VkImageMemoryBarrier2-dstStageMask-03930 185 if stages.intersects(PipelineStages::GEOMETRY_SHADER) 186 && !device.enabled_features().geometry_shader 187 { 188 return Err(SynchronizationError::RequirementNotMet { 189 required_for: "One of `dependency_info.memory_barriers`, \ 190 `dependency_info.buffer_memory_barriers` or \ 191 `dependency_info.image_memory_barriers` has an element where `stages` \ 192 contains `PipelineStages::GEOMETRY_SHADER`", 193 requires_one_of: RequiresOneOf { 194 features: &["geometry_shader"], 195 ..Default::default() 196 }, 197 }); 198 } 199 200 // VUID-VkMemoryBarrier2-srcStageMask-03930 201 // VUID-VkMemoryBarrier2-dstStageMask-03930 202 // VUID-VkBufferMemoryBarrier2-srcStageMask-03930 203 // VUID-VkBufferMemoryBarrier2-dstStageMask-03930 204 // VUID-VkImageMemoryBarrier2-srcStageMask-03930 205 // VUID-VkImageMemoryBarrier2-dstStageMask-03930 206 if stages.intersects( 207 PipelineStages::TESSELLATION_CONTROL_SHADER 208 | PipelineStages::TESSELLATION_EVALUATION_SHADER, 209 ) && !device.enabled_features().tessellation_shader 210 { 211 return Err(SynchronizationError::RequirementNotMet { 212 required_for: "One of `dependency_info.memory_barriers`, \ 213 `dependency_info.buffer_memory_barriers` or \ 214 `dependency_info.image_memory_barriers` has an element where `stages` \ 215 contains `PipelineStages::TESSELLATION_CONTROL_SHADER` or \ 216 `PipelineStages::TESSELLATION_EVALUATION_SHADER`", 217 requires_one_of: RequiresOneOf { 218 features: &["tessellation_shader"], 219 ..Default::default() 220 }, 221 }); 222 } 223 224 // VUID-VkMemoryBarrier2-srcStageMask-03931 225 // VUID-VkMemoryBarrier2-dstStageMask-03931 226 // VUID-VkBufferMemoryBarrier2-srcStageMask-03931 227 // VUID-VkBufferMemoryBarrier2-dstStageMask-03931 228 // VUID-VImagekMemoryBarrier2-srcStageMask-03931 229 // VUID-VkImageMemoryBarrier2-dstStageMask-03931 230 if stages.intersects(PipelineStages::CONDITIONAL_RENDERING) 231 && !device.enabled_features().conditional_rendering 232 { 233 return Err(SynchronizationError::RequirementNotMet { 234 required_for: "One of `dependency_info.memory_barriers`, \ 235 `dependency_info.buffer_memory_barriers` or \ 236 `dependency_info.image_memory_barriers` has an element where `stages` \ 237 contains `PipelineStages::CONDITIONAL_RENDERING`", 238 requires_one_of: RequiresOneOf { 239 features: &["conditional_rendering"], 240 ..Default::default() 241 }, 242 }); 243 } 244 245 // VUID-VkMemoryBarrier2-srcStageMask-03932 246 // VUID-VkMemoryBarrier2-dstStageMask-03932 247 // VUID-VkBufferMemoryBarrier2-srcStageMask-03932 248 // VUID-VkBufferMemoryBarrier2-dstStageMask-03932 249 // VUID-VkImageMemoryBarrier2-srcStageMask-03932 250 // VUID-VkImageMemoryBarrier2-dstStageMask-03932 251 if stages.intersects(PipelineStages::FRAGMENT_DENSITY_PROCESS) 252 && !device.enabled_features().fragment_density_map 253 { 254 return Err(SynchronizationError::RequirementNotMet { 255 required_for: "One of `dependency_info.memory_barriers`, \ 256 `dependency_info.buffer_memory_barriers` or \ 257 `dependency_info.image_memory_barriers` has an element where `stages` \ 258 contains `PipelineStages::FRAGMENT_DENSITY_PROCESS`", 259 requires_one_of: RequiresOneOf { 260 features: &["fragment_density_map"], 261 ..Default::default() 262 }, 263 }); 264 } 265 266 // VUID-VkMemoryBarrier2-srcStageMask-03933 267 // VUID-VkMemoryBarrier2-dstStageMask-03933 268 // VUID-VkBufferMemoryBarrier2-srcStageMask-03933 269 // VUID-VkBufferMemoryBarrier2-dstStageMask-03933 270 // VUID-VkImageMemoryBarrier2-srcStageMask-03933 271 // VUID-VkImageMemoryBarrier2-dstStageMask-03933 272 if stages.intersects(PipelineStages::TRANSFORM_FEEDBACK) 273 && !device.enabled_features().transform_feedback 274 { 275 return Err(SynchronizationError::RequirementNotMet { 276 required_for: "One of `dependency_info.memory_barriers`, \ 277 `dependency_info.buffer_memory_barriers` or \ 278 `dependency_info.image_memory_barriers` has an element where `stages` \ 279 contains `PipelineStages::TRANSFORM_FEEDBACK`", 280 requires_one_of: RequiresOneOf { 281 features: &["transform_feedback"], 282 ..Default::default() 283 }, 284 }); 285 } 286 287 // VUID-VkMemoryBarrier2-srcStageMask-03934 288 // VUID-VkMemoryBarrier2-dstStageMask-03934 289 // VUID-VkBufferMemoryBarrier2-srcStageMask-03934 290 // VUID-VkBufferMemoryBarrier2-dstStageMask-03934 291 // VUID-VkImageMemoryBarrier2-srcStageMask-03934 292 // VUID-VkImageMemoryBarrier2-dstStageMask-03934 293 if stages.intersects(PipelineStages::MESH_SHADER) 294 && !device.enabled_features().mesh_shader 295 { 296 return Err(SynchronizationError::RequirementNotMet { 297 required_for: "One of `dependency_info.memory_barriers`, \ 298 `dependency_info.buffer_memory_barriers` or \ 299 `dependency_info.image_memory_barriers` has an element where `stages` \ 300 contains `PipelineStages::MESH_SHADER`", 301 requires_one_of: RequiresOneOf { 302 features: &["mesh_shader"], 303 ..Default::default() 304 }, 305 }); 306 } 307 308 // VUID-VkMemoryBarrier2-srcStageMask-03935 309 // VUID-VkMemoryBarrier2-dstStageMask-03935 310 // VUID-VkBufferMemoryBarrier2-srcStageMask-03935 311 // VUID-VkBufferMemoryBarrier2-dstStageMask-03935 312 // VUID-VkImageMemoryBarrier2-srcStageMask-03935 313 // VUID-VkImageMemoryBarrier2-dstStageMask-03935 314 if stages.intersects(PipelineStages::TASK_SHADER) 315 && !device.enabled_features().task_shader 316 { 317 return Err(SynchronizationError::RequirementNotMet { 318 required_for: "One of `dependency_info.memory_barriers`, \ 319 `dependency_info.buffer_memory_barriers` or \ 320 `dependency_info.image_memory_barriers` has an element where `stages` \ 321 contains `PipelineStages::TASK_SHADER`", 322 requires_one_of: RequiresOneOf { 323 features: &["task_shader"], 324 ..Default::default() 325 }, 326 }); 327 } 328 329 // VUID-VkMemoryBarrier2-shadingRateImage-07316 330 // VUID-VkMemoryBarrier2-shadingRateImage-07316 331 // VUID-VkBufferMemoryBarrier2-shadingRateImage-07316 332 // VUID-VkBufferMemoryBarrier2-shadingRateImage-07316 333 // VUID-VkImageMemoryBarrier2-shadingRateImage-07316 334 // VUID-VkImageMemoryBarrier2-shadingRateImage-07316 335 if stages.intersects(PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT) 336 && !(device.enabled_features().attachment_fragment_shading_rate 337 || device.enabled_features().shading_rate_image) 338 { 339 return Err(SynchronizationError::RequirementNotMet { 340 required_for: "One of `dependency_info.memory_barriers`, \ 341 `dependency_info.buffer_memory_barriers` or \ 342 `dependency_info.image_memory_barriers` has an element where `stages` \ 343 contains `PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT`", 344 requires_one_of: RequiresOneOf { 345 features: &["attachment_fragment_shading_rate", "shading_rate_image"], 346 ..Default::default() 347 }, 348 }); 349 } 350 351 // VUID-VkMemoryBarrier2-srcStageMask-04957 352 // VUID-VkMemoryBarrier2-dstStageMask-04957 353 // VUID-VkBufferMemoryBarrier2-srcStageMask-04957 354 // VUID-VkBufferMemoryBarrier2-dstStageMask-04957 355 // VUID-VkImageMemoryBarrier2-srcStageMask-04957 356 // VUID-VkImageMemoryBarrier2-dstStageMask-04957 357 if stages.intersects(PipelineStages::SUBPASS_SHADING) 358 && !device.enabled_features().subpass_shading 359 { 360 return Err(SynchronizationError::RequirementNotMet { 361 required_for: "One of `dependency_info.memory_barriers`, \ 362 `dependency_info.buffer_memory_barriers` or \ 363 `dependency_info.image_memory_barriers` has an element where `stages` \ 364 contains `PipelineStages::SUBPASS_SHADING`", 365 requires_one_of: RequiresOneOf { 366 features: &["subpass_shading"], 367 ..Default::default() 368 }, 369 }); 370 } 371 372 // VUID-VkMemoryBarrier2-srcStageMask-04995 373 // VUID-VkMemoryBarrier2-dstStageMask-04995 374 // VUID-VkBufferMemoryBarrier2-srcStageMask-04995 375 // VUID-VkBufferMemoryBarrier2-dstStageMask-04995 376 // VUID-VkImageMemoryBarrier2-srcStageMask-04995 377 // VUID-VkImageMemoryBarrier2-dstStageMask-04995 378 if stages.intersects(PipelineStages::INVOCATION_MASK) 379 && !device.enabled_features().invocation_mask 380 { 381 return Err(SynchronizationError::RequirementNotMet { 382 required_for: "One of `dependency_info.memory_barriers`, \ 383 `dependency_info.buffer_memory_barriers` or \ 384 `dependency_info.image_memory_barriers` has an element where `stages` \ 385 contains `PipelineStages::INVOCATION_MASK`", 386 requires_one_of: RequiresOneOf { 387 features: &["invocation_mask"], 388 ..Default::default() 389 }, 390 }); 391 } 392 393 // VUID-vkCmdPipelineBarrier-srcStageMask-03937 394 // VUID-vkCmdPipelineBarrier-dstStageMask-03937 395 if stages.is_empty() && !device.enabled_features().synchronization2 { 396 return Err(SynchronizationError::RequirementNotMet { 397 required_for: "One of `dependency_info.memory_barriers`, \ 398 `dependency_info.buffer_memory_barriers` or \ 399 `dependency_info.image_memory_barriers` has an element where `stages` \ 400 is empty", 401 requires_one_of: RequiresOneOf { 402 features: &["synchronization2"], 403 ..Default::default() 404 }, 405 }); 406 } 407 408 // A bit of a ridiculous number of VUIDs... 409 410 // VUID-VkMemoryBarrier2-srcAccessMask-03900 411 // .. 412 // VUID-VkMemoryBarrier2-srcAccessMask-07458 413 414 // VUID-VkMemoryBarrier2-dstAccessMask-03900 415 // .. 416 // VUID-VkMemoryBarrier2-dstAccessMask-07458 417 418 // VUID-VkBufferMemoryBarrier2-srcAccessMask-03900 419 // .. 420 // VUID-VkBufferMemoryBarrier2-srcAccessMask-07458 421 422 // VUID-VkBufferMemoryBarrier2-dstAccessMask-03900 423 // .. 424 // VUID-VkBufferMemoryBarrier2-dstAccessMask-07458 425 426 // VUID-VkImageMemoryBarrier2-srcAccessMask-03900 427 // .. 428 // VUID-VkImageMemoryBarrier2-srcAccessMask-07458 429 430 // VUID-VkImageMemoryBarrier2-dstAccessMask-03900 431 // .. 432 // VUID-VkImageMemoryBarrier2-dstAccessMask-07458 433 434 if !AccessFlags::from(stages).contains(access) { 435 match ty { 436 'm' => { 437 return Err( 438 SynchronizationError::MemoryBarrierAccessNotSupportedByStages { 439 barrier_index, 440 }, 441 ) 442 } 443 'b' => return Err( 444 SynchronizationError::BufferMemoryBarrierAccessNotSupportedByStages { 445 barrier_index, 446 }, 447 ), 448 'i' => return Err( 449 SynchronizationError::ImageMemoryBarrierAccessNotSupportedByStages { 450 barrier_index, 451 }, 452 ), 453 _ => unreachable!(), 454 } 455 } 456 } 457 458 // VUID-VkMemoryBarrier2-srcAccessMask-06256 459 // VUID-VkBufferMemoryBarrier2-srcAccessMask-06256 460 // VUID-VkImageMemoryBarrier2-srcAccessMask-06256 461 if !device.enabled_features().ray_query 462 && src_access.intersects(AccessFlags::ACCELERATION_STRUCTURE_READ) 463 && src_stages.intersects( 464 PipelineStages::VERTEX_SHADER 465 | PipelineStages::TESSELLATION_CONTROL_SHADER 466 | PipelineStages::TESSELLATION_EVALUATION_SHADER 467 | PipelineStages::GEOMETRY_SHADER 468 | PipelineStages::FRAGMENT_SHADER 469 | PipelineStages::COMPUTE_SHADER 470 | PipelineStages::PRE_RASTERIZATION_SHADERS 471 | PipelineStages::TASK_SHADER 472 | PipelineStages::MESH_SHADER, 473 ) 474 { 475 return Err(SynchronizationError::RequirementNotMet { 476 required_for: "One of `dependency_info.memory_barriers`, \ 477 `dependency_info.buffer_memory_barriers` or \ 478 `dependency_info.image_memory_barriers` has an element where \ 479 `src_access` contains `ACCELERATION_STRUCTURE_READ`, and \ 480 `src_stages` contains a shader stage other than `RAY_TRACING_SHADER`", 481 requires_one_of: RequiresOneOf { 482 features: &["ray_query"], 483 ..Default::default() 484 }, 485 }); 486 } 487 488 Ok(()) 489 }; 490 491 let check_queue_family_ownership_transfer = |ty: char, 492 barrier_index: usize, 493 src_stages: PipelineStages, 494 dst_stages: PipelineStages, 495 queue_family_ownership_transfer: Option< 496 QueueFamilyOwnershipTransfer, 497 >, 498 sharing: &Sharing<_>| 499 -> Result<(), SynchronizationError> { 500 if let Some(transfer) = queue_family_ownership_transfer { 501 // VUID? 502 transfer.validate_device(device)?; 503 504 // VUID-VkBufferMemoryBarrier2-srcQueueFamilyIndex-04087 505 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-04070 506 // Ensured by the definition of `QueueFamilyOwnershipTransfer`. 507 508 // VUID-VkBufferMemoryBarrier2-buffer-04088 509 // VUID-VkImageMemoryBarrier2-image-04071 510 // Ensured by the definition of `QueueFamilyOwnershipTransfer`. 511 512 let queue_family_count = 513 device.physical_device().queue_family_properties().len() as u32; 514 515 let provided_queue_family_index = match (sharing, transfer) { 516 ( 517 Sharing::Exclusive, 518 QueueFamilyOwnershipTransfer::ExclusiveBetweenLocal { 519 src_index, 520 dst_index, 521 }, 522 ) => Some(max(src_index, dst_index)), 523 ( 524 Sharing::Exclusive, 525 QueueFamilyOwnershipTransfer::ExclusiveToExternal { src_index } 526 | QueueFamilyOwnershipTransfer::ExclusiveToForeign { src_index }, 527 ) => Some(src_index), 528 ( 529 Sharing::Exclusive, 530 QueueFamilyOwnershipTransfer::ExclusiveFromExternal { dst_index } 531 | QueueFamilyOwnershipTransfer::ExclusiveFromForeign { dst_index }, 532 ) => Some(dst_index), 533 ( 534 Sharing::Concurrent(_), 535 QueueFamilyOwnershipTransfer::ConcurrentToExternal 536 | QueueFamilyOwnershipTransfer::ConcurrentFromExternal 537 | QueueFamilyOwnershipTransfer::ConcurrentToForeign 538 | QueueFamilyOwnershipTransfer::ConcurrentFromForeign, 539 ) => None, 540 _ => match ty { 541 'b' => return Err(SynchronizationError::BufferMemoryBarrierOwnershipTransferSharingMismatch { 542 barrier_index, 543 }), 544 'i' => return Err(SynchronizationError::ImageMemoryBarrierOwnershipTransferSharingMismatch { 545 barrier_index, 546 }), 547 _ => unreachable!(), 548 }, 549 }.filter(|&index| index >= queue_family_count); 550 551 // VUID-VkBufferMemoryBarrier2-buffer-04089 552 // VUID-VkImageMemoryBarrier2-image-04072 553 554 if let Some(provided_queue_family_index) = provided_queue_family_index { 555 match ty { 556 'b' => return Err(SynchronizationError::BufferMemoryBarrierOwnershipTransferIndexOutOfRange { 557 barrier_index, 558 provided_queue_family_index, 559 queue_family_count, 560 }), 561 'i' => return Err(SynchronizationError::ImageMemoryBarrierOwnershipTransferIndexOutOfRange { 562 barrier_index, 563 provided_queue_family_index, 564 queue_family_count, 565 }), 566 _ => unreachable!(), 567 } 568 } 569 570 // VUID-VkBufferMemoryBarrier2-srcStageMask-03851 571 // VUID-VkImageMemoryBarrier2-srcStageMask-03854 572 if src_stages.intersects(PipelineStages::HOST) 573 || dst_stages.intersects(PipelineStages::HOST) 574 { 575 match ty { 576 'b' => return Err(SynchronizationError::BufferMemoryBarrierOwnershipTransferHostNotAllowed { 577 barrier_index, 578 }), 579 'i' => return Err(SynchronizationError::ImageMemoryBarrierOwnershipTransferHostForbidden { 580 barrier_index, 581 }), 582 _ => unreachable!(), 583 } 584 } 585 } 586 587 Ok(()) 588 }; 589 590 for (barrier_index, barrier) in memory_barriers.iter().enumerate() { 591 let &MemoryBarrier { 592 src_stages, 593 src_access, 594 dst_stages, 595 dst_access, 596 _ne: _, 597 } = barrier; 598 599 /* 600 Check stages and access 601 */ 602 603 check_stages_access( 604 'm', 605 barrier_index, 606 src_stages, 607 src_access, 608 dst_stages, 609 dst_access, 610 )?; 611 } 612 613 for (barrier_index, barrier) in buffer_memory_barriers.iter().enumerate() { 614 let &BufferMemoryBarrier { 615 src_stages, 616 src_access, 617 dst_stages, 618 dst_access, 619 queue_family_ownership_transfer, 620 ref buffer, 621 ref range, 622 _ne: _, 623 } = barrier; 624 625 // VUID-VkBufferMemoryBarrier2-buffer-01931 626 // Ensured by Buffer type construction. 627 628 /* 629 Check stages and access 630 */ 631 632 check_stages_access( 633 'b', 634 barrier_index, 635 src_stages, 636 src_access, 637 dst_stages, 638 dst_access, 639 )?; 640 641 /* 642 Check queue family transfer 643 */ 644 645 check_queue_family_ownership_transfer( 646 'b', 647 barrier_index, 648 src_stages, 649 dst_stages, 650 queue_family_ownership_transfer, 651 buffer.sharing(), 652 )?; 653 654 /* 655 Check range 656 */ 657 658 // VUID-VkBufferMemoryBarrier2-size-01188 659 assert!(!range.is_empty()); 660 661 // VUID-VkBufferMemoryBarrier2-offset-01187 662 // VUID-VkBufferMemoryBarrier2-size-01189 663 if range.end > buffer.size() { 664 return Err(SynchronizationError::BufferMemoryBarrierOutOfRange { 665 barrier_index, 666 range_end: range.end, 667 buffer_size: buffer.size(), 668 }); 669 } 670 } 671 672 for (barrier_index, barrier) in image_memory_barriers.iter().enumerate() { 673 let &ImageMemoryBarrier { 674 src_stages, 675 src_access, 676 dst_stages, 677 dst_access, 678 old_layout, 679 new_layout, 680 queue_family_ownership_transfer, 681 ref image, 682 ref subresource_range, 683 _ne: _, 684 } = barrier; 685 686 // VUID-VkImageMemoryBarrier2-image-01932 687 // Ensured by Image type construction. 688 689 /* 690 Check stages and access 691 */ 692 693 check_stages_access( 694 'i', 695 barrier_index, 696 src_stages, 697 src_access, 698 dst_stages, 699 dst_access, 700 )?; 701 702 /* 703 Check layouts 704 */ 705 706 // VUID-VkImageMemoryBarrier2-oldLayout-parameter 707 old_layout.validate_device(device)?; 708 709 // VUID-VkImageMemoryBarrier2-newLayout-parameter 710 new_layout.validate_device(device)?; 711 712 // VUID-VkImageMemoryBarrier2-srcStageMask-03855 713 if src_stages.intersects(PipelineStages::HOST) 714 && !matches!( 715 old_layout, 716 ImageLayout::Preinitialized | ImageLayout::Undefined | ImageLayout::General 717 ) 718 { 719 return Err( 720 SynchronizationError::ImageMemoryBarrierOldLayoutFromHostInvalid { 721 barrier_index, 722 old_layout, 723 }, 724 ); 725 } 726 727 // VUID-VkImageMemoryBarrier2-oldLayout-01197 728 // Not checked yet, therefore unsafe. 729 730 // VUID-VkImageMemoryBarrier2-newLayout-01198 731 if matches!( 732 new_layout, 733 ImageLayout::Undefined | ImageLayout::Preinitialized 734 ) { 735 return Err(SynchronizationError::ImageMemoryBarrierNewLayoutInvalid { 736 barrier_index, 737 }); 738 } 739 740 // VUID-VkImageMemoryBarrier2-attachmentFeedbackLoopLayout-07313 741 /*if !device.enabled_features().attachment_feedback_loop_layout 742 && matches!(new_layout, ImageLayout::AttachmentFeedbackLoopOptimal) 743 { 744 return Err(SynchronizationError::RequirementNotMet { 745 required_for: "`dependency_info.image_memory_barriers` has an element where \ 746 `new_layout` is `AttachmentFeedbackLoopOptimal`", 747 requires_one_of: RequiresOneOf { 748 features: &["attachment_feedback_loop_layout"], 749 ..Default::default() 750 }, 751 }); 752 }*/ 753 754 for layout in [old_layout, new_layout] { 755 // VUID-VkImageMemoryBarrier2-synchronization2-06911 756 /*if !device.enabled_features().synchronization2 757 && matches!( 758 layout, 759 ImageLayout::AttachmentOptimal | ImageLayout::ReadOnlyOptimal 760 ) 761 { 762 return Err(SynchronizationError::RequirementNotMet { 763 required_for: "`dependency_info.image_memory_barriers` has an element \ 764 where `old_layout` or `new_layout` is `AttachmentOptimal` or \ 765 `ReadOnlyOptimal`", 766 requires_one_of: RequiresOneOf { 767 features: &["synchronization2"], 768 ..Default::default() 769 }, 770 }); 771 }*/ 772 773 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07006 774 /*if layout == ImageLayout::AttachmentFeedbackLoopOptimal { 775 if !image.usage().intersects( 776 ImageUsage::COLOR_ATTACHMENT | ImageUsage::DEPTH_STENCIL_ATTACHMENT, 777 ) { 778 return Err( 779 SynchronizationError::ImageMemoryBarrierImageMissingUsageForLayout { 780 barrier_index, 781 layout, 782 requires_one_of_usage: ImageUsage::COLOR_ATTACHMENT 783 | ImageUsage::DEPTH_STENCIL_ATTACHMENT, 784 }, 785 ); 786 } 787 788 if !image 789 .usage() 790 .intersects(ImageUsage::INPUT_ATTACHMENT | ImageUsage::SAMPLED) 791 { 792 return Err( 793 SynchronizationError::ImageMemoryBarrierImageMissingUsageForLayout { 794 barrier_index, 795 layout, 796 requires_one_of_usage: ImageUsage::INPUT_ATTACHMENT 797 | ImageUsage::SAMPLED, 798 }, 799 ); 800 } 801 802 if !image 803 .usage() 804 .intersects(ImageUsage::ATTACHMENT_FEEDBACK_LOOP) 805 { 806 return Err( 807 SynchronizationError::ImageMemoryBarrierImageMissingUsageForLayout { 808 barrier_index, 809 layout, 810 requires_one_of_usage: ImageUsage::ATTACHMENT_FEEDBACK_LOOP, 811 }, 812 ); 813 } 814 }*/ 815 816 let requires_one_of_usage = match layout { 817 // VUID-VkImageMemoryBarrier2-oldLayout-01208 818 ImageLayout::ColorAttachmentOptimal => ImageUsage::COLOR_ATTACHMENT, 819 820 // VUID-VkImageMemoryBarrier2-oldLayout-01209 821 ImageLayout::DepthStencilAttachmentOptimal => { 822 ImageUsage::DEPTH_STENCIL_ATTACHMENT 823 } 824 825 // VUID-VkImageMemoryBarrier2-oldLayout-01210 826 ImageLayout::DepthStencilReadOnlyOptimal => { 827 ImageUsage::DEPTH_STENCIL_ATTACHMENT 828 } 829 830 // VUID-VkImageMemoryBarrier2-oldLayout-01211 831 ImageLayout::ShaderReadOnlyOptimal => { 832 ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT 833 } 834 835 // VUID-VkImageMemoryBarrier2-oldLayout-01212 836 ImageLayout::TransferSrcOptimal => ImageUsage::TRANSFER_SRC, 837 838 // VUID-VkImageMemoryBarrier2-oldLayout-01213 839 ImageLayout::TransferDstOptimal => ImageUsage::TRANSFER_DST, 840 841 // VUID-VkImageMemoryBarrier2-oldLayout-01658 842 ImageLayout::DepthReadOnlyStencilAttachmentOptimal => { 843 ImageUsage::DEPTH_STENCIL_ATTACHMENT 844 } 845 846 // VUID-VkImageMemoryBarrier2-oldLayout-01659 847 ImageLayout::DepthAttachmentStencilReadOnlyOptimal => { 848 ImageUsage::DEPTH_STENCIL_ATTACHMENT 849 } 850 851 /* 852 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-04065 853 ImageLayout::DepthReadOnlyOptimal => { 854 ImageUsage::DEPTH_STENCIL_ATTACHMENT 855 | ImageUsage::SAMPLED 856 | ImageUsage::INPUT_ATTACHMENT 857 } 858 859 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-04066 860 ImageLayout::DepthAttachmentOptimal => ImageUsage::DEPTH_STENCIL_ATTACHMENT, 861 862 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-04067 863 ImageLayout::StencilReadOnlyOptimal => { 864 ImageUsage::DEPTH_STENCIL_ATTACHMENT 865 | ImageUsage::SAMPLED 866 | ImageUsage::INPUT_ATTACHMENT 867 } 868 869 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-04068 870 ImageLayout::StencilAttachmentOptimal => ImageUsage::DEPTH_STENCIL_ATTACHMENT, 871 872 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-03938 873 ImageLayout::AttachmentOptimal => { 874 ImageUsage::COLOR_ATTACHMENT | ImageUsage::DEPTH_STENCIL_ATTACHMENT 875 } 876 877 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-03939 878 ImageLayout::ReadOnlyOptimal => { 879 ImageUsage::DEPTH_STENCIL_ATTACHMENT 880 | ImageUsage::SAMPLED 881 | ImageUsage::INPUT_ATTACHMENT 882 } 883 884 // VUID-VkImageMemoryBarrier2-oldLayout-02088 885 ImageLayout::FragmentShadingRateAttachmentOptimal => { 886 ImageUsage::FRAGMENT_SHADING_RATE_ATTACHMENT 887 } 888 */ 889 _ => continue, 890 }; 891 892 if !image.usage().intersects(requires_one_of_usage) { 893 return Err( 894 SynchronizationError::ImageMemoryBarrierImageMissingUsageForLayout { 895 barrier_index, 896 layout, 897 requires_one_of_usage, 898 }, 899 ); 900 } 901 } 902 903 /* 904 Check queue family tansfer 905 */ 906 907 check_queue_family_ownership_transfer( 908 'i', 909 barrier_index, 910 src_stages, 911 dst_stages, 912 queue_family_ownership_transfer, 913 image.sharing(), 914 )?; 915 916 /* 917 Check subresource range 918 */ 919 920 // VUID-VkImageSubresourceRange-aspectMask-requiredbitmask 921 assert!(!subresource_range.aspects.is_empty()); 922 923 // VUID-VkImageSubresourceRange-aspectMask-parameter 924 subresource_range.aspects.validate_device(device)?; 925 926 let image_aspects = image.format().unwrap().aspects(); 927 928 // VUID-VkImageMemoryBarrier2-image-01673 929 // VUID-VkImageMemoryBarrier2-image-03319 930 if image_aspects.contains(subresource_range.aspects) { 931 return Err(SynchronizationError::ImageMemoryBarrierAspectsNotAllowed { 932 barrier_index, 933 aspects: subresource_range.aspects - image_aspects, 934 }); 935 } 936 937 if image_aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL) { 938 // VUID-VkImageMemoryBarrier2-image-03320 939 if !device.enabled_features().separate_depth_stencil_layouts 940 && image_aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL) 941 && !subresource_range 942 .aspects 943 .contains(ImageAspects::DEPTH | ImageAspects::STENCIL) 944 { 945 return Err(SynchronizationError::RequirementNotMet { 946 required_for: "`dependency_info.image_memory_barriers` has an element \ 947 where `image` has both a depth and a stencil aspect, and \ 948 `subresource_range.aspects` does not contain both aspects", 949 requires_one_of: RequiresOneOf { 950 features: &["separate_depth_stencil_layouts"], 951 ..Default::default() 952 }, 953 }); 954 } 955 } else { 956 // VUID-VkImageMemoryBarrier2-image-01671 957 if !image.flags().intersects(ImageCreateFlags::DISJOINT) 958 && subresource_range.aspects != ImageAspects::COLOR 959 { 960 return Err(SynchronizationError::ImageMemoryBarrierAspectsNotAllowed { 961 barrier_index, 962 aspects: subresource_range.aspects - ImageAspects::COLOR, 963 }); 964 } 965 } 966 967 // VUID-VkImageSubresourceRange-levelCount-01720 968 assert!(!subresource_range.mip_levels.is_empty()); 969 970 // VUID-VkImageMemoryBarrier2-subresourceRange-01486 971 // VUID-VkImageMemoryBarrier2-subresourceRange-01724 972 if subresource_range.mip_levels.end > image.mip_levels() { 973 return Err( 974 SynchronizationError::ImageMemoryBarrierMipLevelsOutOfRange { 975 barrier_index, 976 mip_levels_range_end: subresource_range.mip_levels.end, 977 image_mip_levels: image.mip_levels(), 978 }, 979 ); 980 } 981 982 // VUID-VkImageSubresourceRange-layerCount-01721 983 assert!(!subresource_range.array_layers.is_empty()); 984 985 // VUID-VkImageMemoryBarrier2-subresourceRange-01488 986 // VUID-VkImageMemoryBarrier2-subresourceRange-01725 987 if subresource_range.array_layers.end > image.dimensions().array_layers() { 988 return Err( 989 SynchronizationError::ImageMemoryBarrierArrayLayersOutOfRange { 990 barrier_index, 991 array_layers_range_end: subresource_range.array_layers.end, 992 image_array_layers: image.dimensions().array_layers(), 993 }, 994 ); 995 } 996 } 997 998 /* 999 Checks for current render pass 1000 */ 1001 1002 if let Some(render_pass_state) = self.builder_state.render_pass.as_ref() { 1003 // VUID-vkCmdPipelineBarrier2-None-06191 1004 let begin_render_pass_state = match &render_pass_state.render_pass { 1005 RenderPassStateType::BeginRenderPass(x) => x, 1006 RenderPassStateType::BeginRendering(_) => { 1007 return Err(SynchronizationError::ForbiddenWithBeginRendering) 1008 } 1009 }; 1010 let subpass_index = begin_render_pass_state.subpass.index(); 1011 let subpass_desc = begin_render_pass_state.subpass.subpass_desc(); 1012 let dependencies = begin_render_pass_state.subpass.render_pass().dependencies(); 1013 1014 // VUID-vkCmdPipelineBarrier2-pDependencies-02285 1015 // TODO: see https://github.com/KhronosGroup/Vulkan-Docs/issues/1982 1016 if !dependencies.iter().any(|dependency| { 1017 dependency.src_subpass == Some(subpass_index) 1018 && dependency.dst_subpass == Some(subpass_index) 1019 }) { 1020 return Err(SynchronizationError::MemoryBarrierNoMatchingSubpassSelfDependency); 1021 } 1022 1023 // VUID-vkCmdPipelineBarrier2-bufferMemoryBarrierCount-01178 1024 if !buffer_memory_barriers.is_empty() { 1025 return Err(SynchronizationError::BufferMemoryBarrierForbiddenInsideRenderPass); 1026 } 1027 1028 for (barrier_index, barrier) in image_memory_barriers.iter().enumerate() { 1029 // VUID-vkCmdPipelineBarrier2-image-04073 1030 // TODO: How are you supposed to verify this in secondary command buffers, 1031 // when there is no inherited framebuffer? 1032 // The image is not known until you execute it in a primary command buffer. 1033 if let Some(framebuffer) = &begin_render_pass_state.framebuffer { 1034 let attachment_index = (framebuffer.attachments().iter()) 1035 .position(|attachment| attachment.image().inner().image == &barrier.image) 1036 .ok_or(SynchronizationError::ImageMemoryBarrierNotInputAttachment { 1037 barrier_index, 1038 })? as u32; 1039 1040 if !(subpass_desc.input_attachments.iter().flatten()) 1041 .any(|atch_ref| atch_ref.attachment == attachment_index) 1042 { 1043 return Err(SynchronizationError::ImageMemoryBarrierNotInputAttachment { 1044 barrier_index, 1045 }); 1046 } 1047 1048 if !(subpass_desc.color_attachments.iter().flatten()) 1049 .chain(subpass_desc.depth_stencil_attachment.as_ref()) 1050 .any(|atch_ref| atch_ref.attachment == attachment_index) 1051 { 1052 return Err(SynchronizationError::ImageMemoryBarrierNotColorDepthStencilAttachment { 1053 barrier_index, 1054 }); 1055 } 1056 } 1057 1058 // VUID-vkCmdPipelineBarrier2-oldLayout-01181 1059 if barrier.old_layout != barrier.new_layout { 1060 return Err(SynchronizationError::ImageMemoryBarrierLayoutTransitionForbiddenInsideRenderPass { 1061 barrier_index, 1062 }); 1063 } 1064 1065 // VUID-vkCmdPipelineBarrier2-srcQueueFamilyIndex-01182 1066 if barrier.queue_family_ownership_transfer.is_some() { 1067 return Err(SynchronizationError::ImageMemoryBarrierOwnershipTransferForbiddenInsideRenderPass { 1068 barrier_index, 1069 }); 1070 } 1071 } 1072 } else { 1073 // VUID-vkCmdPipelineBarrier2-dependencyFlags-01186 1074 if dependency_flags.intersects(DependencyFlags::VIEW_LOCAL) { 1075 return Err(SynchronizationError::DependencyFlagsViewLocalNotAllowed); 1076 } 1077 } 1078 1079 Ok(()) 1080 } 1081 1082 #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] pipeline_barrier_unchecked( &mut self, dependency_info: DependencyInfo, ) -> &mut Self1083 pub unsafe fn pipeline_barrier_unchecked( 1084 &mut self, 1085 dependency_info: DependencyInfo, 1086 ) -> &mut Self { 1087 if dependency_info.is_empty() { 1088 return self; 1089 } 1090 1091 let &DependencyInfo { 1092 dependency_flags, 1093 ref memory_barriers, 1094 ref buffer_memory_barriers, 1095 ref image_memory_barriers, 1096 _ne: _, 1097 } = &dependency_info; 1098 1099 if self.device().enabled_features().synchronization2 { 1100 let memory_barriers_vk: SmallVec<[_; 2]> = memory_barriers 1101 .iter() 1102 .map(|barrier| { 1103 let &MemoryBarrier { 1104 src_stages, 1105 src_access, 1106 dst_stages, 1107 dst_access, 1108 _ne: _, 1109 } = barrier; 1110 1111 ash::vk::MemoryBarrier2 { 1112 src_stage_mask: src_stages.into(), 1113 src_access_mask: src_access.into(), 1114 dst_stage_mask: dst_stages.into(), 1115 dst_access_mask: dst_access.into(), 1116 ..Default::default() 1117 } 1118 }) 1119 .collect(); 1120 1121 let buffer_memory_barriers_vk: SmallVec<[_; 8]> = buffer_memory_barriers 1122 .iter() 1123 .map(|barrier| { 1124 let &BufferMemoryBarrier { 1125 src_stages, 1126 src_access, 1127 dst_stages, 1128 dst_access, 1129 queue_family_ownership_transfer, 1130 ref buffer, 1131 ref range, 1132 _ne: _, 1133 } = barrier; 1134 1135 let (src_queue_family_index, dst_queue_family_index) = 1136 queue_family_ownership_transfer.map_or( 1137 (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), 1138 Into::into, 1139 ); 1140 1141 ash::vk::BufferMemoryBarrier2 { 1142 src_stage_mask: src_stages.into(), 1143 src_access_mask: src_access.into(), 1144 dst_stage_mask: dst_stages.into(), 1145 dst_access_mask: dst_access.into(), 1146 src_queue_family_index, 1147 dst_queue_family_index, 1148 buffer: buffer.handle(), 1149 offset: range.start, 1150 size: range.end - range.start, 1151 ..Default::default() 1152 } 1153 }) 1154 .collect(); 1155 1156 let image_memory_barriers_vk: SmallVec<[_; 8]> = image_memory_barriers 1157 .iter() 1158 .map(|barrier| { 1159 let &ImageMemoryBarrier { 1160 src_stages, 1161 src_access, 1162 dst_stages, 1163 dst_access, 1164 old_layout, 1165 new_layout, 1166 queue_family_ownership_transfer, 1167 ref image, 1168 ref subresource_range, 1169 _ne: _, 1170 } = barrier; 1171 1172 let (src_queue_family_index, dst_queue_family_index) = 1173 queue_family_ownership_transfer.map_or( 1174 (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), 1175 Into::into, 1176 ); 1177 1178 ash::vk::ImageMemoryBarrier2 { 1179 src_stage_mask: src_stages.into(), 1180 src_access_mask: src_access.into(), 1181 dst_stage_mask: dst_stages.into(), 1182 dst_access_mask: dst_access.into(), 1183 old_layout: old_layout.into(), 1184 new_layout: new_layout.into(), 1185 src_queue_family_index, 1186 dst_queue_family_index, 1187 image: image.handle(), 1188 subresource_range: subresource_range.clone().into(), 1189 ..Default::default() 1190 } 1191 }) 1192 .collect(); 1193 1194 let dependency_info_vk = ash::vk::DependencyInfo { 1195 dependency_flags: dependency_flags.into(), 1196 memory_barrier_count: memory_barriers_vk.len() as u32, 1197 p_memory_barriers: memory_barriers_vk.as_ptr(), 1198 buffer_memory_barrier_count: buffer_memory_barriers_vk.len() as u32, 1199 p_buffer_memory_barriers: buffer_memory_barriers_vk.as_ptr(), 1200 image_memory_barrier_count: image_memory_barriers_vk.len() as u32, 1201 p_image_memory_barriers: image_memory_barriers_vk.as_ptr(), 1202 ..Default::default() 1203 }; 1204 1205 let fns = self.device().fns(); 1206 1207 if self.device().api_version() >= Version::V1_3 { 1208 (fns.v1_3.cmd_pipeline_barrier2)(self.handle(), &dependency_info_vk); 1209 } else { 1210 debug_assert!(self.device().enabled_extensions().khr_synchronization2); 1211 (fns.khr_synchronization2.cmd_pipeline_barrier2_khr)( 1212 self.handle(), 1213 &dependency_info_vk, 1214 ); 1215 } 1216 } else { 1217 let mut src_stage_mask = ash::vk::PipelineStageFlags::empty(); 1218 let mut dst_stage_mask = ash::vk::PipelineStageFlags::empty(); 1219 1220 let memory_barriers_vk: SmallVec<[_; 2]> = memory_barriers 1221 .iter() 1222 .map(|barrier| { 1223 let &MemoryBarrier { 1224 src_stages, 1225 src_access, 1226 dst_stages, 1227 dst_access, 1228 _ne: _, 1229 } = barrier; 1230 1231 src_stage_mask |= src_stages.into(); 1232 dst_stage_mask |= dst_stages.into(); 1233 1234 ash::vk::MemoryBarrier { 1235 src_access_mask: src_access.into(), 1236 dst_access_mask: dst_access.into(), 1237 ..Default::default() 1238 } 1239 }) 1240 .collect(); 1241 1242 let buffer_memory_barriers_vk: SmallVec<[_; 8]> = buffer_memory_barriers 1243 .iter() 1244 .map(|barrier| { 1245 let &BufferMemoryBarrier { 1246 src_stages, 1247 src_access, 1248 dst_stages, 1249 dst_access, 1250 queue_family_ownership_transfer, 1251 ref buffer, 1252 ref range, 1253 _ne: _, 1254 } = barrier; 1255 1256 src_stage_mask |= src_stages.into(); 1257 dst_stage_mask |= dst_stages.into(); 1258 1259 let (src_queue_family_index, dst_queue_family_index) = 1260 queue_family_ownership_transfer.map_or( 1261 (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), 1262 Into::into, 1263 ); 1264 1265 ash::vk::BufferMemoryBarrier { 1266 src_access_mask: src_access.into(), 1267 dst_access_mask: dst_access.into(), 1268 src_queue_family_index, 1269 dst_queue_family_index, 1270 buffer: buffer.handle(), 1271 offset: range.start, 1272 size: range.end - range.start, 1273 ..Default::default() 1274 } 1275 }) 1276 .collect(); 1277 1278 let image_memory_barriers_vk: SmallVec<[_; 8]> = image_memory_barriers 1279 .iter() 1280 .map(|barrier| { 1281 let &ImageMemoryBarrier { 1282 src_stages, 1283 src_access, 1284 dst_stages, 1285 dst_access, 1286 old_layout, 1287 new_layout, 1288 queue_family_ownership_transfer, 1289 ref image, 1290 ref subresource_range, 1291 _ne: _, 1292 } = barrier; 1293 1294 src_stage_mask |= src_stages.into(); 1295 dst_stage_mask |= dst_stages.into(); 1296 1297 let (src_queue_family_index, dst_queue_family_index) = 1298 queue_family_ownership_transfer.map_or( 1299 (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), 1300 Into::into, 1301 ); 1302 1303 ash::vk::ImageMemoryBarrier { 1304 src_access_mask: src_access.into(), 1305 dst_access_mask: dst_access.into(), 1306 old_layout: old_layout.into(), 1307 new_layout: new_layout.into(), 1308 src_queue_family_index, 1309 dst_queue_family_index, 1310 image: image.handle(), 1311 subresource_range: subresource_range.clone().into(), 1312 ..Default::default() 1313 } 1314 }) 1315 .collect(); 1316 1317 if src_stage_mask.is_empty() { 1318 // "VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT is [...] equivalent to 1319 // VK_PIPELINE_STAGE_2_NONE in the first scope." 1320 src_stage_mask |= ash::vk::PipelineStageFlags::TOP_OF_PIPE; 1321 } 1322 1323 if dst_stage_mask.is_empty() { 1324 // "VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT is [...] equivalent to 1325 // VK_PIPELINE_STAGE_2_NONE in the second scope." 1326 dst_stage_mask |= ash::vk::PipelineStageFlags::BOTTOM_OF_PIPE; 1327 } 1328 1329 let fns = self.device().fns(); 1330 (fns.v1_0.cmd_pipeline_barrier)( 1331 self.handle(), 1332 src_stage_mask, 1333 dst_stage_mask, 1334 dependency_flags.into(), 1335 memory_barriers_vk.len() as u32, 1336 memory_barriers_vk.as_ptr(), 1337 buffer_memory_barriers_vk.len() as u32, 1338 buffer_memory_barriers_vk.as_ptr(), 1339 image_memory_barriers_vk.len() as u32, 1340 image_memory_barriers_vk.as_ptr(), 1341 ); 1342 } 1343 1344 let command_index = self.next_command_index; 1345 let command_name = "pipeline_barrier"; 1346 self.resources_usage_state.record_pipeline_barrier( 1347 command_index, 1348 command_name, 1349 &dependency_info, 1350 self.queue_family_properties().queue_flags, 1351 ); 1352 1353 self.resources 1354 .reserve(buffer_memory_barriers.len() + image_memory_barriers.len()); 1355 1356 for barrier in dependency_info.buffer_memory_barriers { 1357 self.resources.push(Box::new(barrier.buffer)); 1358 } 1359 1360 for barrier in dependency_info.image_memory_barriers { 1361 self.resources.push(Box::new(barrier.image)); 1362 } 1363 1364 self.next_command_index += 1; 1365 self 1366 } 1367 1368 /// Signals an [`Event`] from the device. 1369 /// 1370 /// # Safety 1371 /// 1372 /// - All images that are accessed by the command must be in the expected image layout. 1373 /// - For each element of `dependency_info.image_memory_barriers` that contains an image layout 1374 /// transition, which is a write operation, the barrier must be defined appropriately to 1375 /// ensure no memory access hazard occurs. 1376 #[inline] set_event( &mut self, event: Arc<Event>, dependency_info: DependencyInfo, ) -> Result<&mut Self, SynchronizationError>1377 pub unsafe fn set_event( 1378 &mut self, 1379 event: Arc<Event>, 1380 dependency_info: DependencyInfo, 1381 ) -> Result<&mut Self, SynchronizationError> { 1382 self.validate_set_event(&event, &dependency_info)?; 1383 1384 unsafe { Ok(self.set_event_unchecked(event, dependency_info)) } 1385 } 1386 validate_set_event( &self, event: &Event, dependency_info: &DependencyInfo, ) -> Result<(), SynchronizationError>1387 fn validate_set_event( 1388 &self, 1389 event: &Event, 1390 dependency_info: &DependencyInfo, 1391 ) -> Result<(), SynchronizationError> { 1392 // VUID-vkCmdSetEvent2-renderpass 1393 if self.builder_state.render_pass.is_some() { 1394 return Err(SynchronizationError::ForbiddenInsideRenderPass); 1395 } 1396 1397 // VUID-vkCmdSetEvent2-commandBuffer-03826 1398 // TODO: 1399 1400 let device = self.device(); 1401 let queue_family_properties = self.queue_family_properties(); 1402 1403 // VUID-vkCmdSetEvent2-commandBuffer-cmdpool 1404 if !queue_family_properties.queue_flags.intersects( 1405 QueueFlags::GRAPHICS 1406 | QueueFlags::COMPUTE 1407 | QueueFlags::VIDEO_DECODE 1408 | QueueFlags::VIDEO_ENCODE, 1409 ) { 1410 return Err(SynchronizationError::NotSupportedByQueueFamily); 1411 } 1412 1413 // VUID-vkCmdSetEvent2-commonparent 1414 assert_eq!(device, event.device()); 1415 1416 let &DependencyInfo { 1417 dependency_flags, 1418 ref memory_barriers, 1419 ref buffer_memory_barriers, 1420 ref image_memory_barriers, 1421 _ne: _, 1422 } = dependency_info; 1423 1424 // VUID-VkDependencyInfo-dependencyFlags-parameter 1425 dependency_flags.validate_device(device)?; 1426 1427 // VUID-vkCmdSetEvent2-dependencyFlags-03825 1428 assert!(dependency_flags.is_empty()); 1429 1430 let check_stages_access = |ty: char, 1431 barrier_index: usize, 1432 src_stages: PipelineStages, 1433 src_access: AccessFlags, 1434 dst_stages: PipelineStages, 1435 dst_access: AccessFlags| 1436 -> Result<(), SynchronizationError> { 1437 for (stages, access) in [(src_stages, src_access), (dst_stages, dst_access)] { 1438 // VUID-vkCmdSetEvent2-synchronization2-03824 1439 if !device.enabled_features().synchronization2 { 1440 if stages.is_2() { 1441 return Err(SynchronizationError::RequirementNotMet { 1442 required_for: "One of `dependency_info.memory_barriers`, \ 1443 `dependency_info.buffer_memory_barriers` or \ 1444 `dependency_info.image_memory_barriers` has an element where \ 1445 `src_stages` or `dst_stages` contains flags from \ 1446 `VkPipelineStageFlagBits2`", 1447 requires_one_of: RequiresOneOf { 1448 features: &["synchronization2"], 1449 ..Default::default() 1450 }, 1451 }); 1452 } 1453 1454 if access.is_2() { 1455 return Err(SynchronizationError::RequirementNotMet { 1456 required_for: "One of `dependency_info.memory_barriers`, \ 1457 `dependency_info.buffer_memory_barriers` or \ 1458 `dependency_info.image_memory_barriers` has an element where \ 1459 `src_access` or `dst_access` contains flags from \ 1460 `VkAccessFlagBits2`", 1461 requires_one_of: RequiresOneOf { 1462 features: &["synchronization2"], 1463 ..Default::default() 1464 }, 1465 }); 1466 } 1467 } 1468 1469 // VUID-VkMemoryBarrier2-srcStageMask-parameter 1470 // VUID-VkMemoryBarrier2-dstStageMask-parameter 1471 // VUID-VkBufferMemoryBarrier2-srcStageMask-parameter 1472 // VUID-VkBufferMemoryBarrier2-dstStageMask-parameter 1473 // VUID-VkImageMemoryBarrier2-srcStageMask-parameter 1474 // VUID-VkImageMemoryBarrier2-dstStageMask-parameter 1475 stages.validate_device(device)?; 1476 1477 // VUID-VkMemoryBarrier2-srcAccessMask-parameter 1478 // VUID-VkMemoryBarrier2-dstAccessMask-parameter 1479 // VUID-VkBufferMemoryBarrier2-srcAccessMask-parameter 1480 // VUID-VkBufferMemoryBarrier2-dstAccessMask-parameter 1481 // VUID-VkImageMemoryBarrier2-srcAccessMask-parameter 1482 // VUID-VkImageMemoryBarrier2-dstAccessMask-parameter 1483 access.validate_device(device)?; 1484 1485 // VUID-vkCmdSetEvent2-srcStageMask-03827 1486 // VUID-vkCmdSetEvent2-dstStageMask-03828 1487 if !PipelineStages::from(queue_family_properties.queue_flags).contains(stages) { 1488 match ty { 1489 'm' => { 1490 return Err(SynchronizationError::MemoryBarrierStageNotSupported { 1491 barrier_index, 1492 }) 1493 } 1494 'b' => { 1495 return Err( 1496 SynchronizationError::BufferMemoryBarrierStageNotSupported { 1497 barrier_index, 1498 }, 1499 ) 1500 } 1501 'i' => { 1502 return Err(SynchronizationError::ImageMemoryBarrierStageNotSupported { 1503 barrier_index, 1504 }) 1505 } 1506 _ => unreachable!(), 1507 } 1508 } 1509 1510 // VUID-VkMemoryBarrier2-srcStageMask-03929 1511 // VUID-VkMemoryBarrier2-dstStageMask-03929 1512 // VUID-VkBufferMemoryBarrier2-srcStageMask-03929 1513 // VUID-VkBufferMemoryBarrier2-dstStageMask-03929 1514 // VUID-VkImageMemoryBarrier2-srcStageMask-03930 1515 // VUID-VkImageMemoryBarrier2-dstStageMask-03930 1516 if stages.intersects(PipelineStages::GEOMETRY_SHADER) 1517 && !device.enabled_features().geometry_shader 1518 { 1519 return Err(SynchronizationError::RequirementNotMet { 1520 required_for: "One of `dependency_info.memory_barriers`, \ 1521 `dependency_info.buffer_memory_barriers` or \ 1522 `dependency_info.image_memory_barriers` has an element where `stages` \ 1523 contains `PipelineStages::GEOMETRY_SHADER`", 1524 requires_one_of: RequiresOneOf { 1525 features: &["geometry_shader"], 1526 ..Default::default() 1527 }, 1528 }); 1529 } 1530 1531 // VUID-VkMemoryBarrier2-srcStageMask-03930 1532 // VUID-VkMemoryBarrier2-dstStageMask-03930 1533 // VUID-VkBufferMemoryBarrier2-srcStageMask-03930 1534 // VUID-VkBufferMemoryBarrier2-dstStageMask-03930 1535 // VUID-VkImageMemoryBarrier2-srcStageMask-03930 1536 // VUID-VkImageMemoryBarrier2-dstStageMask-03930 1537 if stages.intersects( 1538 PipelineStages::TESSELLATION_CONTROL_SHADER 1539 | PipelineStages::TESSELLATION_EVALUATION_SHADER, 1540 ) && !device.enabled_features().tessellation_shader 1541 { 1542 return Err(SynchronizationError::RequirementNotMet { 1543 required_for: "One of `dependency_info.memory_barriers`, \ 1544 `dependency_info.buffer_memory_barriers` or \ 1545 `dependency_info.image_memory_barriers` has an element where `stages` \ 1546 contains `PipelineStages::TESSELLATION_CONTROL_SHADER` or \ 1547 `PipelineStages::TESSELLATION_EVALUATION_SHADER`", 1548 requires_one_of: RequiresOneOf { 1549 features: &["tessellation_shader"], 1550 ..Default::default() 1551 }, 1552 }); 1553 } 1554 1555 // VUID-VkMemoryBarrier2-srcStageMask-03931 1556 // VUID-VkMemoryBarrier2-dstStageMask-03931 1557 // VUID-VkBufferMemoryBarrier2-srcStageMask-03931 1558 // VUID-VkBufferMemoryBarrier2-dstStageMask-03931 1559 // VUID-VImagekMemoryBarrier2-srcStageMask-03931 1560 // VUID-VkImageMemoryBarrier2-dstStageMask-03931 1561 if stages.intersects(PipelineStages::CONDITIONAL_RENDERING) 1562 && !device.enabled_features().conditional_rendering 1563 { 1564 return Err(SynchronizationError::RequirementNotMet { 1565 required_for: "One of `dependency_info.memory_barriers`, \ 1566 `dependency_info.buffer_memory_barriers` or \ 1567 `dependency_info.image_memory_barriers` has an element where `stages` \ 1568 contains `PipelineStages::CONDITIONAL_RENDERING`", 1569 requires_one_of: RequiresOneOf { 1570 features: &["conditional_rendering"], 1571 ..Default::default() 1572 }, 1573 }); 1574 } 1575 1576 // VUID-VkMemoryBarrier2-srcStageMask-03932 1577 // VUID-VkMemoryBarrier2-dstStageMask-03932 1578 // VUID-VkBufferMemoryBarrier2-srcStageMask-03932 1579 // VUID-VkBufferMemoryBarrier2-dstStageMask-03932 1580 // VUID-VkImageMemoryBarrier2-srcStageMask-03932 1581 // VUID-VkImageMemoryBarrier2-dstStageMask-03932 1582 if stages.intersects(PipelineStages::FRAGMENT_DENSITY_PROCESS) 1583 && !device.enabled_features().fragment_density_map 1584 { 1585 return Err(SynchronizationError::RequirementNotMet { 1586 required_for: "One of `dependency_info.memory_barriers`, \ 1587 `dependency_info.buffer_memory_barriers` or \ 1588 `dependency_info.image_memory_barriers` has an element where `stages` \ 1589 contains `PipelineStages::FRAGMENT_DENSITY_PROCESS`", 1590 requires_one_of: RequiresOneOf { 1591 features: &["fragment_density_map"], 1592 ..Default::default() 1593 }, 1594 }); 1595 } 1596 1597 // VUID-VkMemoryBarrier2-srcStageMask-03933 1598 // VUID-VkMemoryBarrier2-dstStageMask-03933 1599 // VUID-VkBufferMemoryBarrier2-srcStageMask-03933 1600 // VUID-VkBufferMemoryBarrier2-dstStageMask-03933 1601 // VUID-VkImageMemoryBarrier2-srcStageMask-03933 1602 // VUID-VkImageMemoryBarrier2-dstStageMask-03933 1603 if stages.intersects(PipelineStages::TRANSFORM_FEEDBACK) 1604 && !device.enabled_features().transform_feedback 1605 { 1606 return Err(SynchronizationError::RequirementNotMet { 1607 required_for: "One of `dependency_info.memory_barriers`, \ 1608 `dependency_info.buffer_memory_barriers` or \ 1609 `dependency_info.image_memory_barriers` has an element where `stages` \ 1610 contains `PipelineStages::TRANSFORM_FEEDBACK`", 1611 requires_one_of: RequiresOneOf { 1612 features: &["transform_feedback"], 1613 ..Default::default() 1614 }, 1615 }); 1616 } 1617 1618 // VUID-VkMemoryBarrier2-srcStageMask-03934 1619 // VUID-VkMemoryBarrier2-dstStageMask-03934 1620 // VUID-VkBufferMemoryBarrier2-srcStageMask-03934 1621 // VUID-VkBufferMemoryBarrier2-dstStageMask-03934 1622 // VUID-VkImageMemoryBarrier2-srcStageMask-03934 1623 // VUID-VkImageMemoryBarrier2-dstStageMask-03934 1624 if stages.intersects(PipelineStages::MESH_SHADER) 1625 && !device.enabled_features().mesh_shader 1626 { 1627 return Err(SynchronizationError::RequirementNotMet { 1628 required_for: "One of `dependency_info.memory_barriers`, \ 1629 `dependency_info.buffer_memory_barriers` or \ 1630 `dependency_info.image_memory_barriers` has an element where `stages` \ 1631 contains `PipelineStages::MESH_SHADER`", 1632 requires_one_of: RequiresOneOf { 1633 features: &["mesh_shader"], 1634 ..Default::default() 1635 }, 1636 }); 1637 } 1638 1639 // VUID-VkMemoryBarrier2-srcStageMask-03935 1640 // VUID-VkMemoryBarrier2-dstStageMask-03935 1641 // VUID-VkBufferMemoryBarrier2-srcStageMask-03935 1642 // VUID-VkBufferMemoryBarrier2-dstStageMask-03935 1643 // VUID-VkImageMemoryBarrier2-srcStageMask-03935 1644 // VUID-VkImageMemoryBarrier2-dstStageMask-03935 1645 if stages.intersects(PipelineStages::TASK_SHADER) 1646 && !device.enabled_features().task_shader 1647 { 1648 return Err(SynchronizationError::RequirementNotMet { 1649 required_for: "One of `dependency_info.memory_barriers`, \ 1650 `dependency_info.buffer_memory_barriers` or \ 1651 `dependency_info.image_memory_barriers` has an element where `stages` \ 1652 contains `PipelineStages::TASK_SHADER`", 1653 requires_one_of: RequiresOneOf { 1654 features: &["task_shader"], 1655 ..Default::default() 1656 }, 1657 }); 1658 } 1659 1660 // VUID-VkMemoryBarrier2-shadingRateImage-07316 1661 // VUID-VkMemoryBarrier2-shadingRateImage-07316 1662 // VUID-VkBufferMemoryBarrier2-shadingRateImage-07316 1663 // VUID-VkBufferMemoryBarrier2-shadingRateImage-07316 1664 // VUID-VkImageMemoryBarrier2-shadingRateImage-07316 1665 // VUID-VkImageMemoryBarrier2-shadingRateImage-07316 1666 if stages.intersects(PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT) 1667 && !(device.enabled_features().attachment_fragment_shading_rate 1668 || device.enabled_features().shading_rate_image) 1669 { 1670 return Err(SynchronizationError::RequirementNotMet { 1671 required_for: "One of `dependency_info.memory_barriers`, \ 1672 `dependency_info.buffer_memory_barriers` or \ 1673 `dependency_info.image_memory_barriers` has an element where `stages` \ 1674 contains `PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT`", 1675 requires_one_of: RequiresOneOf { 1676 features: &["attachment_fragment_shading_rate", "shading_rate_image"], 1677 ..Default::default() 1678 }, 1679 }); 1680 } 1681 1682 // VUID-VkMemoryBarrier2-srcStageMask-04957 1683 // VUID-VkMemoryBarrier2-dstStageMask-04957 1684 // VUID-VkBufferMemoryBarrier2-srcStageMask-04957 1685 // VUID-VkBufferMemoryBarrier2-dstStageMask-04957 1686 // VUID-VkImageMemoryBarrier2-srcStageMask-04957 1687 // VUID-VkImageMemoryBarrier2-dstStageMask-04957 1688 if stages.intersects(PipelineStages::SUBPASS_SHADING) 1689 && !device.enabled_features().subpass_shading 1690 { 1691 return Err(SynchronizationError::RequirementNotMet { 1692 required_for: "One of `dependency_info.memory_barriers`, \ 1693 `dependency_info.buffer_memory_barriers` or \ 1694 `dependency_info.image_memory_barriers` has an element where `stages` \ 1695 contains `PipelineStages::SUBPASS_SHADING`", 1696 requires_one_of: RequiresOneOf { 1697 features: &["subpass_shading"], 1698 ..Default::default() 1699 }, 1700 }); 1701 } 1702 1703 // VUID-VkMemoryBarrier2-srcStageMask-04995 1704 // VUID-VkMemoryBarrier2-dstStageMask-04995 1705 // VUID-VkBufferMemoryBarrier2-srcStageMask-04995 1706 // VUID-VkBufferMemoryBarrier2-dstStageMask-04995 1707 // VUID-VkImageMemoryBarrier2-srcStageMask-04995 1708 // VUID-VkImageMemoryBarrier2-dstStageMask-04995 1709 if stages.intersects(PipelineStages::INVOCATION_MASK) 1710 && !device.enabled_features().invocation_mask 1711 { 1712 return Err(SynchronizationError::RequirementNotMet { 1713 required_for: "One of `dependency_info.memory_barriers`, \ 1714 `dependency_info.buffer_memory_barriers` or \ 1715 `dependency_info.image_memory_barriers` has an element where `stages` \ 1716 contains `PipelineStages::INVOCATION_MASK`", 1717 requires_one_of: RequiresOneOf { 1718 features: &["invocation_mask"], 1719 ..Default::default() 1720 }, 1721 }); 1722 } 1723 1724 // VUID-vkCmdSetEvent-stageMask-03937 1725 if stages.is_empty() && !device.enabled_features().synchronization2 { 1726 return Err(SynchronizationError::RequirementNotMet { 1727 required_for: "One of `dependency_info.memory_barriers`, \ 1728 `dependency_info.buffer_memory_barriers` or \ 1729 `dependency_info.image_memory_barriers` has an element where `stages` \ 1730 is empty", 1731 requires_one_of: RequiresOneOf { 1732 features: &["synchronization2"], 1733 ..Default::default() 1734 }, 1735 }); 1736 } 1737 1738 // A bit of a ridiculous number of VUIDs... 1739 1740 // VUID-VkMemoryBarrier2-srcAccessMask-03900 1741 // .. 1742 // VUID-VkMemoryBarrier2-srcAccessMask-07458 1743 1744 // VUID-VkMemoryBarrier2-dstAccessMask-03900 1745 // .. 1746 // VUID-VkMemoryBarrier2-dstAccessMask-07458 1747 1748 // VUID-VkBufferMemoryBarrier2-srcAccessMask-03900 1749 // .. 1750 // VUID-VkBufferMemoryBarrier2-srcAccessMask-07458 1751 1752 // VUID-VkBufferMemoryBarrier2-dstAccessMask-03900 1753 // .. 1754 // VUID-VkBufferMemoryBarrier2-dstAccessMask-07458 1755 1756 // VUID-VkImageMemoryBarrier2-srcAccessMask-03900 1757 // .. 1758 // VUID-VkImageMemoryBarrier2-srcAccessMask-07458 1759 1760 // VUID-VkImageMemoryBarrier2-dstAccessMask-03900 1761 // .. 1762 // VUID-VkImageMemoryBarrier2-dstAccessMask-07458 1763 1764 if !AccessFlags::from(stages).contains(access) { 1765 match ty { 1766 'm' => { 1767 return Err( 1768 SynchronizationError::MemoryBarrierAccessNotSupportedByStages { 1769 barrier_index, 1770 }, 1771 ) 1772 } 1773 'b' => return Err( 1774 SynchronizationError::BufferMemoryBarrierAccessNotSupportedByStages { 1775 barrier_index, 1776 }, 1777 ), 1778 'i' => return Err( 1779 SynchronizationError::ImageMemoryBarrierAccessNotSupportedByStages { 1780 barrier_index, 1781 }, 1782 ), 1783 _ => unreachable!(), 1784 } 1785 } 1786 } 1787 1788 // VUID-VkMemoryBarrier2-srcAccessMask-06256 1789 // VUID-VkBufferMemoryBarrier2-srcAccessMask-06256 1790 // VUID-VkImageMemoryBarrier2-srcAccessMask-06256 1791 if !device.enabled_features().ray_query 1792 && src_access.intersects(AccessFlags::ACCELERATION_STRUCTURE_READ) 1793 && src_stages.intersects( 1794 PipelineStages::VERTEX_SHADER 1795 | PipelineStages::TESSELLATION_CONTROL_SHADER 1796 | PipelineStages::TESSELLATION_EVALUATION_SHADER 1797 | PipelineStages::GEOMETRY_SHADER 1798 | PipelineStages::FRAGMENT_SHADER 1799 | PipelineStages::COMPUTE_SHADER 1800 | PipelineStages::PRE_RASTERIZATION_SHADERS 1801 | PipelineStages::TASK_SHADER 1802 | PipelineStages::MESH_SHADER, 1803 ) 1804 { 1805 return Err(SynchronizationError::RequirementNotMet { 1806 required_for: "One of `dependency_info.memory_barriers`, \ 1807 `dependency_info.buffer_memory_barriers` or \ 1808 `dependency_info.image_memory_barriers` has an element where \ 1809 `src_access` contains `ACCELERATION_STRUCTURE_READ`, and \ 1810 `src_stages` contains a shader stage other than `RAY_TRACING_SHADER`", 1811 requires_one_of: RequiresOneOf { 1812 features: &["ray_query"], 1813 ..Default::default() 1814 }, 1815 }); 1816 } 1817 1818 Ok(()) 1819 }; 1820 1821 let check_queue_family_ownership_transfer = |ty: char, 1822 barrier_index: usize, 1823 src_stages: PipelineStages, 1824 dst_stages: PipelineStages, 1825 queue_family_ownership_transfer: Option< 1826 QueueFamilyOwnershipTransfer, 1827 >, 1828 sharing: &Sharing<_>| 1829 -> Result<(), SynchronizationError> { 1830 if let Some(transfer) = queue_family_ownership_transfer { 1831 // VUID? 1832 transfer.validate_device(device)?; 1833 1834 // VUID-VkBufferMemoryBarrier2-srcQueueFamilyIndex-04087 1835 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-04070 1836 // Ensured by the definition of `QueueFamilyOwnershipTransfer`. 1837 1838 // VUID-VkBufferMemoryBarrier2-buffer-04088 1839 // VUID-VkImageMemoryBarrier2-image-04071 1840 // Ensured by the definition of `QueueFamilyOwnershipTransfer`. 1841 1842 let queue_family_count = 1843 device.physical_device().queue_family_properties().len() as u32; 1844 1845 let provided_queue_family_index = match (sharing, transfer) { 1846 ( 1847 Sharing::Exclusive, 1848 QueueFamilyOwnershipTransfer::ExclusiveBetweenLocal { 1849 src_index, 1850 dst_index, 1851 }, 1852 ) => Some(max(src_index, dst_index)), 1853 ( 1854 Sharing::Exclusive, 1855 QueueFamilyOwnershipTransfer::ExclusiveToExternal { src_index } 1856 | QueueFamilyOwnershipTransfer::ExclusiveToForeign { src_index }, 1857 ) => Some(src_index), 1858 ( 1859 Sharing::Exclusive, 1860 QueueFamilyOwnershipTransfer::ExclusiveFromExternal { dst_index } 1861 | QueueFamilyOwnershipTransfer::ExclusiveFromForeign { dst_index }, 1862 ) => Some(dst_index), 1863 ( 1864 Sharing::Concurrent(_), 1865 QueueFamilyOwnershipTransfer::ConcurrentToExternal 1866 | QueueFamilyOwnershipTransfer::ConcurrentFromExternal 1867 | QueueFamilyOwnershipTransfer::ConcurrentToForeign 1868 | QueueFamilyOwnershipTransfer::ConcurrentFromForeign, 1869 ) => None, 1870 _ => match ty { 1871 'b' => return Err(SynchronizationError::BufferMemoryBarrierOwnershipTransferSharingMismatch { 1872 barrier_index, 1873 }), 1874 'i' => return Err(SynchronizationError::ImageMemoryBarrierOwnershipTransferSharingMismatch { 1875 barrier_index, 1876 }), 1877 _ => unreachable!(), 1878 }, 1879 }.filter(|&index| index >= queue_family_count); 1880 1881 // VUID-VkBufferMemoryBarrier2-buffer-04089 1882 // VUID-VkImageMemoryBarrier2-image-04072 1883 1884 if let Some(provided_queue_family_index) = provided_queue_family_index { 1885 match ty { 1886 'b' => return Err(SynchronizationError::BufferMemoryBarrierOwnershipTransferIndexOutOfRange { 1887 barrier_index, 1888 provided_queue_family_index, 1889 queue_family_count, 1890 }), 1891 'i' => return Err(SynchronizationError::ImageMemoryBarrierOwnershipTransferIndexOutOfRange { 1892 barrier_index, 1893 provided_queue_family_index, 1894 queue_family_count, 1895 }), 1896 _ => unreachable!(), 1897 } 1898 } 1899 1900 // VUID-VkBufferMemoryBarrier2-srcStageMask-03851 1901 // VUID-VkImageMemoryBarrier2-srcStageMask-03854 1902 if src_stages.intersects(PipelineStages::HOST) 1903 || dst_stages.intersects(PipelineStages::HOST) 1904 { 1905 match ty { 1906 'b' => return Err(SynchronizationError::BufferMemoryBarrierOwnershipTransferHostNotAllowed { 1907 barrier_index, 1908 }), 1909 'i' => return Err(SynchronizationError::ImageMemoryBarrierOwnershipTransferHostForbidden { 1910 barrier_index, 1911 }), 1912 _ => unreachable!(), 1913 } 1914 } 1915 } 1916 1917 Ok(()) 1918 }; 1919 1920 for (barrier_index, barrier) in memory_barriers.iter().enumerate() { 1921 let &MemoryBarrier { 1922 src_stages, 1923 src_access, 1924 dst_stages, 1925 dst_access, 1926 _ne: _, 1927 } = barrier; 1928 1929 /* 1930 Check stages and access 1931 */ 1932 1933 check_stages_access( 1934 'm', 1935 barrier_index, 1936 src_stages, 1937 src_access, 1938 dst_stages, 1939 dst_access, 1940 )?; 1941 } 1942 1943 for (barrier_index, barrier) in buffer_memory_barriers.iter().enumerate() { 1944 let &BufferMemoryBarrier { 1945 src_stages, 1946 src_access, 1947 dst_stages, 1948 dst_access, 1949 queue_family_ownership_transfer, 1950 ref buffer, 1951 ref range, 1952 _ne: _, 1953 } = barrier; 1954 1955 // VUID-VkBufferMemoryBarrier2-buffer-01931 1956 // Ensured by Buffer type construction. 1957 1958 /* 1959 Check stages and access 1960 */ 1961 1962 check_stages_access( 1963 'b', 1964 barrier_index, 1965 src_stages, 1966 src_access, 1967 dst_stages, 1968 dst_access, 1969 )?; 1970 1971 /* 1972 Check queue family transfer 1973 */ 1974 1975 check_queue_family_ownership_transfer( 1976 'b', 1977 barrier_index, 1978 src_stages, 1979 dst_stages, 1980 queue_family_ownership_transfer, 1981 buffer.sharing(), 1982 )?; 1983 1984 /* 1985 Check range 1986 */ 1987 1988 // VUID-VkBufferMemoryBarrier2-size-01188 1989 assert!(!range.is_empty()); 1990 1991 // VUID-VkBufferMemoryBarrier2-offset-01187 1992 // VUID-VkBufferMemoryBarrier2-size-01189 1993 if range.end > buffer.size() { 1994 return Err(SynchronizationError::BufferMemoryBarrierOutOfRange { 1995 barrier_index, 1996 range_end: range.end, 1997 buffer_size: buffer.size(), 1998 }); 1999 } 2000 } 2001 2002 for (barrier_index, barrier) in image_memory_barriers.iter().enumerate() { 2003 let &ImageMemoryBarrier { 2004 src_stages, 2005 src_access, 2006 dst_stages, 2007 dst_access, 2008 old_layout, 2009 new_layout, 2010 queue_family_ownership_transfer, 2011 ref image, 2012 ref subresource_range, 2013 _ne: _, 2014 } = barrier; 2015 2016 // VUID-VkImageMemoryBarrier2-image-01932 2017 // Ensured by Image type construction. 2018 2019 /* 2020 Check stages and access 2021 */ 2022 2023 check_stages_access( 2024 'i', 2025 barrier_index, 2026 src_stages, 2027 src_access, 2028 dst_stages, 2029 dst_access, 2030 )?; 2031 2032 /* 2033 Check layouts 2034 */ 2035 2036 // VUID-VkImageMemoryBarrier2-oldLayout-parameter 2037 old_layout.validate_device(device)?; 2038 2039 // VUID-VkImageMemoryBarrier2-newLayout-parameter 2040 new_layout.validate_device(device)?; 2041 2042 // VUID-VkImageMemoryBarrier2-srcStageMask-03855 2043 if src_stages.intersects(PipelineStages::HOST) 2044 && !matches!( 2045 old_layout, 2046 ImageLayout::Preinitialized | ImageLayout::Undefined | ImageLayout::General 2047 ) 2048 { 2049 return Err( 2050 SynchronizationError::ImageMemoryBarrierOldLayoutFromHostInvalid { 2051 barrier_index, 2052 old_layout, 2053 }, 2054 ); 2055 } 2056 2057 // VUID-VkImageMemoryBarrier2-oldLayout-01197 2058 // Not checked yet, therefore unsafe. 2059 2060 // VUID-VkImageMemoryBarrier2-newLayout-01198 2061 if matches!( 2062 new_layout, 2063 ImageLayout::Undefined | ImageLayout::Preinitialized 2064 ) { 2065 return Err(SynchronizationError::ImageMemoryBarrierNewLayoutInvalid { 2066 barrier_index, 2067 }); 2068 } 2069 2070 // VUID-VkImageMemoryBarrier2-attachmentFeedbackLoopLayout-07313 2071 /*if !device.enabled_features().attachment_feedback_loop_layout 2072 && matches!(new_layout, ImageLayout::AttachmentFeedbackLoopOptimal) 2073 { 2074 return Err(SynchronizationError::RequirementNotMet { 2075 required_for: "`dependency_info.image_memory_barriers` has an element where \ 2076 `new_layout` is `AttachmentFeedbackLoopOptimal`", 2077 requires_one_of: RequiresOneOf { 2078 features: &["attachment_feedback_loop_layout"], 2079 ..Default::default() 2080 }, 2081 }); 2082 }*/ 2083 2084 for layout in [old_layout, new_layout] { 2085 // VUID-VkImageMemoryBarrier2-synchronization2-06911 2086 /*if !device.enabled_features().synchronization2 2087 && matches!( 2088 layout, 2089 ImageLayout::AttachmentOptimal | ImageLayout::ReadOnlyOptimal 2090 ) 2091 { 2092 return Err(SynchronizationError::RequirementNotMet { 2093 required_for: "`dependency_info.image_memory_barriers` has an element \ 2094 where `old_layout` or `new_layout` is `AttachmentOptimal` or \ 2095 `ReadOnlyOptimal`", 2096 requires_one_of: RequiresOneOf { 2097 features: &["synchronization2"], 2098 ..Default::default() 2099 }, 2100 }); 2101 }*/ 2102 2103 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07006 2104 /*if layout == ImageLayout::AttachmentFeedbackLoopOptimal { 2105 if !image.usage().intersects( 2106 ImageUsage::COLOR_ATTACHMENT | ImageUsage::DEPTH_STENCIL_ATTACHMENT, 2107 ) { 2108 return Err( 2109 SynchronizationError::ImageMemoryBarrierImageMissingUsageForLayout { 2110 barrier_index, 2111 layout, 2112 requires_one_of_usage: ImageUsage::COLOR_ATTACHMENT 2113 | ImageUsage::DEPTH_STENCIL_ATTACHMENT, 2114 }, 2115 ); 2116 } 2117 2118 if !image 2119 .usage() 2120 .intersects(ImageUsage::INPUT_ATTACHMENT | ImageUsage::SAMPLED) 2121 { 2122 return Err( 2123 SynchronizationError::ImageMemoryBarrierImageMissingUsageForLayout { 2124 barrier_index, 2125 layout, 2126 requires_one_of_usage: ImageUsage::INPUT_ATTACHMENT 2127 | ImageUsage::SAMPLED, 2128 }, 2129 ); 2130 } 2131 2132 if !image 2133 .usage() 2134 .intersects(ImageUsage::ATTACHMENT_FEEDBACK_LOOP) 2135 { 2136 return Err( 2137 SynchronizationError::ImageMemoryBarrierImageMissingUsageForLayout { 2138 barrier_index, 2139 layout, 2140 requires_one_of_usage: ImageUsage::ATTACHMENT_FEEDBACK_LOOP, 2141 }, 2142 ); 2143 } 2144 }*/ 2145 2146 let requires_one_of_usage = match layout { 2147 // VUID-VkImageMemoryBarrier2-oldLayout-01208 2148 ImageLayout::ColorAttachmentOptimal => ImageUsage::COLOR_ATTACHMENT, 2149 2150 // VUID-VkImageMemoryBarrier2-oldLayout-01209 2151 ImageLayout::DepthStencilAttachmentOptimal => { 2152 ImageUsage::DEPTH_STENCIL_ATTACHMENT 2153 } 2154 2155 // VUID-VkImageMemoryBarrier2-oldLayout-01210 2156 ImageLayout::DepthStencilReadOnlyOptimal => { 2157 ImageUsage::DEPTH_STENCIL_ATTACHMENT 2158 } 2159 2160 // VUID-VkImageMemoryBarrier2-oldLayout-01211 2161 ImageLayout::ShaderReadOnlyOptimal => { 2162 ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT 2163 } 2164 2165 // VUID-VkImageMemoryBarrier2-oldLayout-01212 2166 ImageLayout::TransferSrcOptimal => ImageUsage::TRANSFER_SRC, 2167 2168 // VUID-VkImageMemoryBarrier2-oldLayout-01213 2169 ImageLayout::TransferDstOptimal => ImageUsage::TRANSFER_DST, 2170 2171 // VUID-VkImageMemoryBarrier2-oldLayout-01658 2172 ImageLayout::DepthReadOnlyStencilAttachmentOptimal => { 2173 ImageUsage::DEPTH_STENCIL_ATTACHMENT 2174 } 2175 2176 // VUID-VkImageMemoryBarrier2-oldLayout-01659 2177 ImageLayout::DepthAttachmentStencilReadOnlyOptimal => { 2178 ImageUsage::DEPTH_STENCIL_ATTACHMENT 2179 } 2180 2181 /* 2182 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-04065 2183 ImageLayout::DepthReadOnlyOptimal => { 2184 ImageUsage::DEPTH_STENCIL_ATTACHMENT 2185 | ImageUsage::SAMPLED 2186 | ImageUsage::INPUT_ATTACHMENT 2187 } 2188 2189 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-04066 2190 ImageLayout::DepthAttachmentOptimal => ImageUsage::DEPTH_STENCIL_ATTACHMENT, 2191 2192 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-04067 2193 ImageLayout::StencilReadOnlyOptimal => { 2194 ImageUsage::DEPTH_STENCIL_ATTACHMENT 2195 | ImageUsage::SAMPLED 2196 | ImageUsage::INPUT_ATTACHMENT 2197 } 2198 2199 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-04068 2200 ImageLayout::StencilAttachmentOptimal => ImageUsage::DEPTH_STENCIL_ATTACHMENT, 2201 2202 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-03938 2203 ImageLayout::AttachmentOptimal => { 2204 ImageUsage::COLOR_ATTACHMENT | ImageUsage::DEPTH_STENCIL_ATTACHMENT 2205 } 2206 2207 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-03939 2208 ImageLayout::ReadOnlyOptimal => { 2209 ImageUsage::DEPTH_STENCIL_ATTACHMENT 2210 | ImageUsage::SAMPLED 2211 | ImageUsage::INPUT_ATTACHMENT 2212 } 2213 2214 // VUID-VkImageMemoryBarrier2-oldLayout-02088 2215 ImageLayout::FragmentShadingRateAttachmentOptimal => { 2216 ImageUsage::FRAGMENT_SHADING_RATE_ATTACHMENT 2217 } 2218 */ 2219 _ => continue, 2220 }; 2221 2222 if !image.usage().intersects(requires_one_of_usage) { 2223 return Err( 2224 SynchronizationError::ImageMemoryBarrierImageMissingUsageForLayout { 2225 barrier_index, 2226 layout, 2227 requires_one_of_usage, 2228 }, 2229 ); 2230 } 2231 } 2232 2233 /* 2234 Check queue family tansfer 2235 */ 2236 2237 check_queue_family_ownership_transfer( 2238 'i', 2239 barrier_index, 2240 src_stages, 2241 dst_stages, 2242 queue_family_ownership_transfer, 2243 image.sharing(), 2244 )?; 2245 2246 /* 2247 Check subresource range 2248 */ 2249 2250 // VUID-VkImageSubresourceRange-aspectMask-requiredbitmask 2251 assert!(!subresource_range.aspects.is_empty()); 2252 2253 // VUID-VkImageSubresourceRange-aspectMask-parameter 2254 subresource_range.aspects.validate_device(device)?; 2255 2256 let image_aspects = image.format().unwrap().aspects(); 2257 2258 // VUID-VkImageMemoryBarrier2-image-01673 2259 // VUID-VkImageMemoryBarrier2-image-03319 2260 if image_aspects.contains(subresource_range.aspects) { 2261 return Err(SynchronizationError::ImageMemoryBarrierAspectsNotAllowed { 2262 barrier_index, 2263 aspects: subresource_range.aspects - image_aspects, 2264 }); 2265 } 2266 2267 if image_aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL) { 2268 // VUID-VkImageMemoryBarrier2-image-03320 2269 if !device.enabled_features().separate_depth_stencil_layouts 2270 && image_aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL) 2271 && !subresource_range 2272 .aspects 2273 .contains(ImageAspects::DEPTH | ImageAspects::STENCIL) 2274 { 2275 return Err(SynchronizationError::RequirementNotMet { 2276 required_for: "`dependency_info.image_memory_barriers` has an element \ 2277 where `image` has both a depth and a stencil aspect, and \ 2278 `subresource_range.aspects` does not contain both aspects", 2279 requires_one_of: RequiresOneOf { 2280 features: &["separate_depth_stencil_layouts"], 2281 ..Default::default() 2282 }, 2283 }); 2284 } 2285 } else { 2286 // VUID-VkImageMemoryBarrier2-image-01671 2287 if !image.flags().intersects(ImageCreateFlags::DISJOINT) 2288 && subresource_range.aspects != ImageAspects::COLOR 2289 { 2290 return Err(SynchronizationError::ImageMemoryBarrierAspectsNotAllowed { 2291 barrier_index, 2292 aspects: subresource_range.aspects - ImageAspects::COLOR, 2293 }); 2294 } 2295 } 2296 2297 // VUID-VkImageSubresourceRange-levelCount-01720 2298 assert!(!subresource_range.mip_levels.is_empty()); 2299 2300 // VUID-VkImageMemoryBarrier2-subresourceRange-01486 2301 // VUID-VkImageMemoryBarrier2-subresourceRange-01724 2302 if subresource_range.mip_levels.end > image.mip_levels() { 2303 return Err( 2304 SynchronizationError::ImageMemoryBarrierMipLevelsOutOfRange { 2305 barrier_index, 2306 mip_levels_range_end: subresource_range.mip_levels.end, 2307 image_mip_levels: image.mip_levels(), 2308 }, 2309 ); 2310 } 2311 2312 // VUID-VkImageSubresourceRange-layerCount-01721 2313 assert!(!subresource_range.array_layers.is_empty()); 2314 2315 // VUID-VkImageMemoryBarrier2-subresourceRange-01488 2316 // VUID-VkImageMemoryBarrier2-subresourceRange-01725 2317 if subresource_range.array_layers.end > image.dimensions().array_layers() { 2318 return Err( 2319 SynchronizationError::ImageMemoryBarrierArrayLayersOutOfRange { 2320 barrier_index, 2321 array_layers_range_end: subresource_range.array_layers.end, 2322 image_array_layers: image.dimensions().array_layers(), 2323 }, 2324 ); 2325 } 2326 } 2327 2328 Ok(()) 2329 } 2330 2331 #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] set_event_unchecked( &mut self, event: Arc<Event>, dependency_info: DependencyInfo, ) -> &mut Self2332 pub unsafe fn set_event_unchecked( 2333 &mut self, 2334 event: Arc<Event>, 2335 dependency_info: DependencyInfo, 2336 ) -> &mut Self { 2337 let DependencyInfo { 2338 dependency_flags, 2339 memory_barriers, 2340 buffer_memory_barriers, 2341 image_memory_barriers, 2342 _ne: _, 2343 } = dependency_info; 2344 2345 let fns = self.device().fns(); 2346 2347 if self.device().enabled_features().synchronization2 { 2348 let memory_barriers_vk: SmallVec<[_; 2]> = memory_barriers 2349 .iter() 2350 .map(|barrier| { 2351 let &MemoryBarrier { 2352 src_stages, 2353 src_access, 2354 dst_stages, 2355 dst_access, 2356 _ne: _, 2357 } = barrier; 2358 2359 ash::vk::MemoryBarrier2 { 2360 src_stage_mask: src_stages.into(), 2361 src_access_mask: src_access.into(), 2362 dst_stage_mask: dst_stages.into(), 2363 dst_access_mask: dst_access.into(), 2364 ..Default::default() 2365 } 2366 }) 2367 .collect(); 2368 2369 let buffer_memory_barriers_vk: SmallVec<[_; 8]> = buffer_memory_barriers 2370 .iter() 2371 .map(|barrier| { 2372 let &BufferMemoryBarrier { 2373 src_stages, 2374 src_access, 2375 dst_stages, 2376 dst_access, 2377 queue_family_ownership_transfer, 2378 ref buffer, 2379 ref range, 2380 _ne: _, 2381 } = barrier; 2382 2383 let (src_queue_family_index, dst_queue_family_index) = 2384 queue_family_ownership_transfer.map_or( 2385 (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), 2386 Into::into, 2387 ); 2388 2389 ash::vk::BufferMemoryBarrier2 { 2390 src_stage_mask: src_stages.into(), 2391 src_access_mask: src_access.into(), 2392 dst_stage_mask: dst_stages.into(), 2393 dst_access_mask: dst_access.into(), 2394 src_queue_family_index, 2395 dst_queue_family_index, 2396 buffer: buffer.handle(), 2397 offset: range.start, 2398 size: range.end - range.start, 2399 ..Default::default() 2400 } 2401 }) 2402 .collect(); 2403 2404 let image_memory_barriers_vk: SmallVec<[_; 8]> = image_memory_barriers 2405 .iter() 2406 .map(|barrier| { 2407 let &ImageMemoryBarrier { 2408 src_stages, 2409 src_access, 2410 dst_stages, 2411 dst_access, 2412 old_layout, 2413 new_layout, 2414 queue_family_ownership_transfer, 2415 ref image, 2416 ref subresource_range, 2417 _ne: _, 2418 } = barrier; 2419 2420 let (src_queue_family_index, dst_queue_family_index) = 2421 queue_family_ownership_transfer.map_or( 2422 (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), 2423 Into::into, 2424 ); 2425 2426 ash::vk::ImageMemoryBarrier2 { 2427 src_stage_mask: src_stages.into(), 2428 src_access_mask: src_access.into(), 2429 dst_stage_mask: dst_stages.into(), 2430 dst_access_mask: dst_access.into(), 2431 old_layout: old_layout.into(), 2432 new_layout: new_layout.into(), 2433 src_queue_family_index, 2434 dst_queue_family_index, 2435 image: image.handle(), 2436 subresource_range: subresource_range.clone().into(), 2437 ..Default::default() 2438 } 2439 }) 2440 .collect(); 2441 2442 let dependency_info_vk = ash::vk::DependencyInfo { 2443 dependency_flags: dependency_flags.into(), 2444 memory_barrier_count: memory_barriers_vk.len() as u32, 2445 p_memory_barriers: memory_barriers_vk.as_ptr(), 2446 buffer_memory_barrier_count: buffer_memory_barriers_vk.len() as u32, 2447 p_buffer_memory_barriers: buffer_memory_barriers_vk.as_ptr(), 2448 image_memory_barrier_count: image_memory_barriers_vk.len() as u32, 2449 p_image_memory_barriers: image_memory_barriers_vk.as_ptr(), 2450 ..Default::default() 2451 }; 2452 2453 if self.device().api_version() >= Version::V1_3 { 2454 (fns.v1_3.cmd_set_event2)(self.handle(), event.handle(), &dependency_info_vk); 2455 } else { 2456 debug_assert!(self.device().enabled_extensions().khr_synchronization2); 2457 (fns.khr_synchronization2.cmd_set_event2_khr)( 2458 self.handle(), 2459 event.handle(), 2460 &dependency_info_vk, 2461 ); 2462 } 2463 } else { 2464 // The original function only takes a source stage mask; the rest of the info is 2465 // provided with `wait_events` instead. Therefore, we condense the source stages 2466 // here and ignore the rest. 2467 2468 let mut stage_mask = ash::vk::PipelineStageFlags::empty(); 2469 2470 for barrier in memory_barriers { 2471 stage_mask |= barrier.src_stages.into(); 2472 } 2473 2474 for barrier in buffer_memory_barriers { 2475 stage_mask |= barrier.src_stages.into(); 2476 } 2477 2478 for barrier in image_memory_barriers { 2479 stage_mask |= barrier.src_stages.into(); 2480 } 2481 2482 if stage_mask.is_empty() { 2483 // "VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT is [...] equivalent to 2484 // VK_PIPELINE_STAGE_2_NONE in the first scope." 2485 stage_mask |= ash::vk::PipelineStageFlags::TOP_OF_PIPE; 2486 } 2487 2488 (fns.v1_0.cmd_set_event)(self.handle(), event.handle(), stage_mask); 2489 } 2490 2491 self.resources.push(Box::new(event)); 2492 2493 // TODO: sync state update 2494 2495 self.next_command_index += 1; 2496 self 2497 } 2498 2499 /// Waits for one or more [`Event`]s to be signaled. 2500 /// 2501 /// # Safety 2502 /// 2503 /// - For each element in `events`, if the event is signaled by [`set_event`], that command 2504 /// must have already been recorded or previously submitted to the queue, and the 2505 /// `DependencyInfo` provided here must be equal to the `DependencyInfo` used in that 2506 /// command. 2507 /// - For each element in `events`, if the event is signaled by [`Event::set`], that function 2508 /// must have already been called before submitting this command to a queue. 2509 /// 2510 /// [`set_event`]: Self::set_event 2511 /// [`Event::set`]: Event::set 2512 #[inline] wait_events( &mut self, events: impl IntoIterator<Item = (Arc<Event>, DependencyInfo)>, ) -> Result<&mut Self, SynchronizationError>2513 pub unsafe fn wait_events( 2514 &mut self, 2515 events: impl IntoIterator<Item = (Arc<Event>, DependencyInfo)>, 2516 ) -> Result<&mut Self, SynchronizationError> { 2517 let events: SmallVec<[(Arc<Event>, DependencyInfo); 4]> = events.into_iter().collect(); 2518 self.validate_wait_events(&events)?; 2519 2520 unsafe { Ok(self.wait_events_unchecked(events)) } 2521 } 2522 validate_wait_events( &self, events: &[(Arc<Event>, DependencyInfo)], ) -> Result<(), SynchronizationError>2523 fn validate_wait_events( 2524 &self, 2525 events: &[(Arc<Event>, DependencyInfo)], 2526 ) -> Result<(), SynchronizationError> { 2527 // VUID-vkCmdWaitEvents2-commandBuffer-03846 2528 // TODO: 2529 2530 let device = self.device(); 2531 let queue_family_properties = self.queue_family_properties(); 2532 2533 // VUID-vkCmdWaitEvents2-commandBuffer-cmdpool 2534 if !queue_family_properties.queue_flags.intersects( 2535 QueueFlags::GRAPHICS 2536 | QueueFlags::COMPUTE 2537 | QueueFlags::VIDEO_DECODE 2538 | QueueFlags::VIDEO_ENCODE, 2539 ) { 2540 return Err(SynchronizationError::NotSupportedByQueueFamily); 2541 } 2542 2543 if events.is_empty() { 2544 return Ok(()); 2545 } 2546 2547 for (event, dependency_info) in events { 2548 // VUID-vkCmdWaitEvents2-commonparent 2549 assert_eq!(device, event.device()); 2550 2551 // VUID-vkCmdWaitEvents2-pEvents-03838 2552 // TODO: 2553 2554 // VUID-vkCmdWaitEvents2-pEvents-03839 2555 // TODO: 2556 2557 // VUID-vkCmdWaitEvents2-pEvents-03840 2558 // TODO: 2559 2560 // VUID-vkCmdWaitEvents2-pEvents-03841 2561 // TODO: 2562 2563 let &DependencyInfo { 2564 dependency_flags, 2565 ref memory_barriers, 2566 ref buffer_memory_barriers, 2567 ref image_memory_barriers, 2568 _ne: _, 2569 } = dependency_info; 2570 2571 // VUID-VkDependencyInfo-dependencyFlags-parameter 2572 dependency_flags.validate_device(device)?; 2573 2574 let check_stages_access = |ty: char, 2575 barrier_index: usize, 2576 src_stages: PipelineStages, 2577 src_access: AccessFlags, 2578 dst_stages: PipelineStages, 2579 dst_access: AccessFlags| 2580 -> Result<(), SynchronizationError> { 2581 for (stages, access) in [(src_stages, src_access), (dst_stages, dst_access)] { 2582 // VUID-vkCmdWaitEvents2-synchronization2-03836 2583 if !device.enabled_features().synchronization2 { 2584 if stages.is_2() { 2585 return Err(SynchronizationError::RequirementNotMet { 2586 required_for: "One of `dependency_info.memory_barriers`, \ 2587 `dependency_info.buffer_memory_barriers` or \ 2588 `dependency_info.image_memory_barriers` has an element where \ 2589 `src_stages` or `dst_stages` contains flags from \ 2590 `VkPipelineStageFlagBits2`", 2591 requires_one_of: RequiresOneOf { 2592 features: &["synchronization2"], 2593 ..Default::default() 2594 }, 2595 }); 2596 } 2597 2598 if access.is_2() { 2599 return Err(SynchronizationError::RequirementNotMet { 2600 required_for: "One of `dependency_info.memory_barriers`, \ 2601 `dependency_info.buffer_memory_barriers` or \ 2602 `dependency_info.image_memory_barriers` has an element where \ 2603 `src_access` or `dst_access` contains flags from \ 2604 `VkAccessFlagBits2`", 2605 requires_one_of: RequiresOneOf { 2606 features: &["synchronization2"], 2607 ..Default::default() 2608 }, 2609 }); 2610 } 2611 } 2612 2613 // VUID-VkMemoryBarrier2-srcStageMask-parameter 2614 // VUID-VkMemoryBarrier2-dstStageMask-parameter 2615 // VUID-VkBufferMemoryBarrier2-srcStageMask-parameter 2616 // VUID-VkBufferMemoryBarrier2-dstStageMask-parameter 2617 // VUID-VkImageMemoryBarrier2-srcStageMask-parameter 2618 // VUID-VkImageMemoryBarrier2-dstStageMask-parameter 2619 stages.validate_device(device)?; 2620 2621 // VUID-VkMemoryBarrier2-srcAccessMask-parameter 2622 // VUID-VkMemoryBarrier2-dstAccessMask-parameter 2623 // VUID-VkBufferMemoryBarrier2-srcAccessMask-parameter 2624 // VUID-VkBufferMemoryBarrier2-dstAccessMask-parameter 2625 // VUID-VkImageMemoryBarrier2-srcAccessMask-parameter 2626 // VUID-VkImageMemoryBarrier2-dstAccessMask-parameter 2627 access.validate_device(device)?; 2628 2629 // VUID-vkCmdWaitEvents2-srcStageMask-03842 2630 // VUID-vkCmdWaitEvents2-dstStageMask-03843 2631 if !PipelineStages::from(queue_family_properties.queue_flags).contains(stages) { 2632 match ty { 2633 'm' => { 2634 return Err(SynchronizationError::MemoryBarrierStageNotSupported { 2635 barrier_index, 2636 }) 2637 } 2638 'b' => { 2639 return Err( 2640 SynchronizationError::BufferMemoryBarrierStageNotSupported { 2641 barrier_index, 2642 }, 2643 ) 2644 } 2645 'i' => { 2646 return Err( 2647 SynchronizationError::ImageMemoryBarrierStageNotSupported { 2648 barrier_index, 2649 }, 2650 ) 2651 } 2652 _ => unreachable!(), 2653 } 2654 } 2655 2656 // VUID-VkMemoryBarrier2-srcStageMask-03929 2657 // VUID-VkMemoryBarrier2-dstStageMask-03929 2658 // VUID-VkBufferMemoryBarrier2-srcStageMask-03929 2659 // VUID-VkBufferMemoryBarrier2-dstStageMask-03929 2660 // VUID-VkImageMemoryBarrier2-srcStageMask-03930 2661 // VUID-VkImageMemoryBarrier2-dstStageMask-03930 2662 if stages.intersects(PipelineStages::GEOMETRY_SHADER) 2663 && !device.enabled_features().geometry_shader 2664 { 2665 return Err(SynchronizationError::RequirementNotMet { 2666 required_for: "One of `dependency_info.memory_barriers`, \ 2667 `dependency_info.buffer_memory_barriers` or \ 2668 `dependency_info.image_memory_barriers` has an element where `stages` \ 2669 contains `PipelineStages::GEOMETRY_SHADER`", 2670 requires_one_of: RequiresOneOf { 2671 features: &["geometry_shader"], 2672 ..Default::default() 2673 }, 2674 }); 2675 } 2676 2677 // VUID-VkMemoryBarrier2-srcStageMask-03930 2678 // VUID-VkMemoryBarrier2-dstStageMask-03930 2679 // VUID-VkBufferMemoryBarrier2-srcStageMask-03930 2680 // VUID-VkBufferMemoryBarrier2-dstStageMask-03930 2681 // VUID-VkImageMemoryBarrier2-srcStageMask-03930 2682 // VUID-VkImageMemoryBarrier2-dstStageMask-03930 2683 if stages.intersects( 2684 PipelineStages::TESSELLATION_CONTROL_SHADER 2685 | PipelineStages::TESSELLATION_EVALUATION_SHADER, 2686 ) && !device.enabled_features().tessellation_shader 2687 { 2688 return Err(SynchronizationError::RequirementNotMet { 2689 required_for: "One of `dependency_info.memory_barriers`, \ 2690 `dependency_info.buffer_memory_barriers` or \ 2691 `dependency_info.image_memory_barriers` has an element where `stages` \ 2692 contains `PipelineStages::TESSELLATION_CONTROL_SHADER` or \ 2693 `PipelineStages::TESSELLATION_EVALUATION_SHADER`", 2694 requires_one_of: RequiresOneOf { 2695 features: &["tessellation_shader"], 2696 ..Default::default() 2697 }, 2698 }); 2699 } 2700 2701 // VUID-VkMemoryBarrier2-srcStageMask-03931 2702 // VUID-VkMemoryBarrier2-dstStageMask-03931 2703 // VUID-VkBufferMemoryBarrier2-srcStageMask-03931 2704 // VUID-VkBufferMemoryBarrier2-dstStageMask-03931 2705 // VUID-VImagekMemoryBarrier2-srcStageMask-03931 2706 // VUID-VkImageMemoryBarrier2-dstStageMask-03931 2707 if stages.intersects(PipelineStages::CONDITIONAL_RENDERING) 2708 && !device.enabled_features().conditional_rendering 2709 { 2710 return Err(SynchronizationError::RequirementNotMet { 2711 required_for: "One of `dependency_info.memory_barriers`, \ 2712 `dependency_info.buffer_memory_barriers` or \ 2713 `dependency_info.image_memory_barriers` has an element where `stages` \ 2714 contains `PipelineStages::CONDITIONAL_RENDERING`", 2715 requires_one_of: RequiresOneOf { 2716 features: &["conditional_rendering"], 2717 ..Default::default() 2718 }, 2719 }); 2720 } 2721 2722 // VUID-VkMemoryBarrier2-srcStageMask-03932 2723 // VUID-VkMemoryBarrier2-dstStageMask-03932 2724 // VUID-VkBufferMemoryBarrier2-srcStageMask-03932 2725 // VUID-VkBufferMemoryBarrier2-dstStageMask-03932 2726 // VUID-VkImageMemoryBarrier2-srcStageMask-03932 2727 // VUID-VkImageMemoryBarrier2-dstStageMask-03932 2728 if stages.intersects(PipelineStages::FRAGMENT_DENSITY_PROCESS) 2729 && !device.enabled_features().fragment_density_map 2730 { 2731 return Err(SynchronizationError::RequirementNotMet { 2732 required_for: "One of `dependency_info.memory_barriers`, \ 2733 `dependency_info.buffer_memory_barriers` or \ 2734 `dependency_info.image_memory_barriers` has an element where `stages` \ 2735 contains `PipelineStages::FRAGMENT_DENSITY_PROCESS`", 2736 requires_one_of: RequiresOneOf { 2737 features: &["fragment_density_map"], 2738 ..Default::default() 2739 }, 2740 }); 2741 } 2742 2743 // VUID-VkMemoryBarrier2-srcStageMask-03933 2744 // VUID-VkMemoryBarrier2-dstStageMask-03933 2745 // VUID-VkBufferMemoryBarrier2-srcStageMask-03933 2746 // VUID-VkBufferMemoryBarrier2-dstStageMask-03933 2747 // VUID-VkImageMemoryBarrier2-srcStageMask-03933 2748 // VUID-VkImageMemoryBarrier2-dstStageMask-03933 2749 if stages.intersects(PipelineStages::TRANSFORM_FEEDBACK) 2750 && !device.enabled_features().transform_feedback 2751 { 2752 return Err(SynchronizationError::RequirementNotMet { 2753 required_for: "One of `dependency_info.memory_barriers`, \ 2754 `dependency_info.buffer_memory_barriers` or \ 2755 `dependency_info.image_memory_barriers` has an element where `stages` \ 2756 contains `PipelineStages::TRANSFORM_FEEDBACK`", 2757 requires_one_of: RequiresOneOf { 2758 features: &["transform_feedback"], 2759 ..Default::default() 2760 }, 2761 }); 2762 } 2763 2764 // VUID-VkMemoryBarrier2-srcStageMask-03934 2765 // VUID-VkMemoryBarrier2-dstStageMask-03934 2766 // VUID-VkBufferMemoryBarrier2-srcStageMask-03934 2767 // VUID-VkBufferMemoryBarrier2-dstStageMask-03934 2768 // VUID-VkImageMemoryBarrier2-srcStageMask-03934 2769 // VUID-VkImageMemoryBarrier2-dstStageMask-03934 2770 if stages.intersects(PipelineStages::MESH_SHADER) 2771 && !device.enabled_features().mesh_shader 2772 { 2773 return Err(SynchronizationError::RequirementNotMet { 2774 required_for: "One of `dependency_info.memory_barriers`, \ 2775 `dependency_info.buffer_memory_barriers` or \ 2776 `dependency_info.image_memory_barriers` has an element where `stages` \ 2777 contains `PipelineStages::MESH_SHADER`", 2778 requires_one_of: RequiresOneOf { 2779 features: &["mesh_shader"], 2780 ..Default::default() 2781 }, 2782 }); 2783 } 2784 2785 // VUID-VkMemoryBarrier2-srcStageMask-03935 2786 // VUID-VkMemoryBarrier2-dstStageMask-03935 2787 // VUID-VkBufferMemoryBarrier2-srcStageMask-03935 2788 // VUID-VkBufferMemoryBarrier2-dstStageMask-03935 2789 // VUID-VkImageMemoryBarrier2-srcStageMask-03935 2790 // VUID-VkImageMemoryBarrier2-dstStageMask-03935 2791 if stages.intersects(PipelineStages::TASK_SHADER) 2792 && !device.enabled_features().task_shader 2793 { 2794 return Err(SynchronizationError::RequirementNotMet { 2795 required_for: "One of `dependency_info.memory_barriers`, \ 2796 `dependency_info.buffer_memory_barriers` or \ 2797 `dependency_info.image_memory_barriers` has an element where `stages` \ 2798 contains `PipelineStages::TASK_SHADER`", 2799 requires_one_of: RequiresOneOf { 2800 features: &["task_shader"], 2801 ..Default::default() 2802 }, 2803 }); 2804 } 2805 2806 // VUID-VkMemoryBarrier2-shadingRateImage-07316 2807 // VUID-VkMemoryBarrier2-shadingRateImage-07316 2808 // VUID-VkBufferMemoryBarrier2-shadingRateImage-07316 2809 // VUID-VkBufferMemoryBarrier2-shadingRateImage-07316 2810 // VUID-VkImageMemoryBarrier2-shadingRateImage-07316 2811 // VUID-VkImageMemoryBarrier2-shadingRateImage-07316 2812 if stages.intersects(PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT) 2813 && !(device.enabled_features().attachment_fragment_shading_rate 2814 || device.enabled_features().shading_rate_image) 2815 { 2816 return Err(SynchronizationError::RequirementNotMet { 2817 required_for: "One of `dependency_info.memory_barriers`, \ 2818 `dependency_info.buffer_memory_barriers` or \ 2819 `dependency_info.image_memory_barriers` has an element where `stages` \ 2820 contains `PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT`", 2821 requires_one_of: RequiresOneOf { 2822 features: &[ 2823 "attachment_fragment_shading_rate", 2824 "shading_rate_image", 2825 ], 2826 ..Default::default() 2827 }, 2828 }); 2829 } 2830 2831 // VUID-VkMemoryBarrier2-srcStageMask-04957 2832 // VUID-VkMemoryBarrier2-dstStageMask-04957 2833 // VUID-VkBufferMemoryBarrier2-srcStageMask-04957 2834 // VUID-VkBufferMemoryBarrier2-dstStageMask-04957 2835 // VUID-VkImageMemoryBarrier2-srcStageMask-04957 2836 // VUID-VkImageMemoryBarrier2-dstStageMask-04957 2837 if stages.intersects(PipelineStages::SUBPASS_SHADING) 2838 && !device.enabled_features().subpass_shading 2839 { 2840 return Err(SynchronizationError::RequirementNotMet { 2841 required_for: "One of `dependency_info.memory_barriers`, \ 2842 `dependency_info.buffer_memory_barriers` or \ 2843 `dependency_info.image_memory_barriers` has an element where `stages` \ 2844 contains `PipelineStages::SUBPASS_SHADING`", 2845 requires_one_of: RequiresOneOf { 2846 features: &["subpass_shading"], 2847 ..Default::default() 2848 }, 2849 }); 2850 } 2851 2852 // VUID-VkMemoryBarrier2-srcStageMask-04995 2853 // VUID-VkMemoryBarrier2-dstStageMask-04995 2854 // VUID-VkBufferMemoryBarrier2-srcStageMask-04995 2855 // VUID-VkBufferMemoryBarrier2-dstStageMask-04995 2856 // VUID-VkImageMemoryBarrier2-srcStageMask-04995 2857 // VUID-VkImageMemoryBarrier2-dstStageMask-04995 2858 if stages.intersects(PipelineStages::INVOCATION_MASK) 2859 && !device.enabled_features().invocation_mask 2860 { 2861 return Err(SynchronizationError::RequirementNotMet { 2862 required_for: "One of `dependency_info.memory_barriers`, \ 2863 `dependency_info.buffer_memory_barriers` or \ 2864 `dependency_info.image_memory_barriers` has an element where `stages` \ 2865 contains `PipelineStages::INVOCATION_MASK`", 2866 requires_one_of: RequiresOneOf { 2867 features: &["invocation_mask"], 2868 ..Default::default() 2869 }, 2870 }); 2871 } 2872 2873 // VUID-vkCmdWaitEvents-srcStageMask-03937 2874 // VUID-vkCmdWaitEvents-dstStageMask-03937 2875 if stages.is_empty() && !device.enabled_features().synchronization2 { 2876 return Err(SynchronizationError::RequirementNotMet { 2877 required_for: "One of `dependency_info.memory_barriers`, \ 2878 `dependency_info.buffer_memory_barriers` or \ 2879 `dependency_info.image_memory_barriers` has an element where `stages` \ 2880 is empty", 2881 requires_one_of: RequiresOneOf { 2882 features: &["synchronization2"], 2883 ..Default::default() 2884 }, 2885 }); 2886 } 2887 2888 // A bit of a ridiculous number of VUIDs... 2889 2890 // VUID-VkMemoryBarrier2-srcAccessMask-03900 2891 // .. 2892 // VUID-VkMemoryBarrier2-srcAccessMask-07458 2893 2894 // VUID-VkMemoryBarrier2-dstAccessMask-03900 2895 // .. 2896 // VUID-VkMemoryBarrier2-dstAccessMask-07458 2897 2898 // VUID-VkBufferMemoryBarrier2-srcAccessMask-03900 2899 // .. 2900 // VUID-VkBufferMemoryBarrier2-srcAccessMask-07458 2901 2902 // VUID-VkBufferMemoryBarrier2-dstAccessMask-03900 2903 // .. 2904 // VUID-VkBufferMemoryBarrier2-dstAccessMask-07458 2905 2906 // VUID-VkImageMemoryBarrier2-srcAccessMask-03900 2907 // .. 2908 // VUID-VkImageMemoryBarrier2-srcAccessMask-07458 2909 2910 // VUID-VkImageMemoryBarrier2-dstAccessMask-03900 2911 // .. 2912 // VUID-VkImageMemoryBarrier2-dstAccessMask-07458 2913 2914 if !AccessFlags::from(stages).contains(access) { 2915 match ty { 2916 'm' => { 2917 return Err( 2918 SynchronizationError::MemoryBarrierAccessNotSupportedByStages { 2919 barrier_index, 2920 }, 2921 ) 2922 } 2923 'b' => return Err( 2924 SynchronizationError::BufferMemoryBarrierAccessNotSupportedByStages { 2925 barrier_index, 2926 }, 2927 ), 2928 'i' => return Err( 2929 SynchronizationError::ImageMemoryBarrierAccessNotSupportedByStages { 2930 barrier_index, 2931 }, 2932 ), 2933 _ => unreachable!(), 2934 } 2935 } 2936 } 2937 2938 // VUID-VkMemoryBarrier2-srcAccessMask-06256 2939 // VUID-VkBufferMemoryBarrier2-srcAccessMask-06256 2940 // VUID-VkImageMemoryBarrier2-srcAccessMask-06256 2941 if !device.enabled_features().ray_query 2942 && src_access.intersects(AccessFlags::ACCELERATION_STRUCTURE_READ) 2943 && src_stages.intersects( 2944 PipelineStages::VERTEX_SHADER 2945 | PipelineStages::TESSELLATION_CONTROL_SHADER 2946 | PipelineStages::TESSELLATION_EVALUATION_SHADER 2947 | PipelineStages::GEOMETRY_SHADER 2948 | PipelineStages::FRAGMENT_SHADER 2949 | PipelineStages::COMPUTE_SHADER 2950 | PipelineStages::PRE_RASTERIZATION_SHADERS 2951 | PipelineStages::TASK_SHADER 2952 | PipelineStages::MESH_SHADER, 2953 ) 2954 { 2955 return Err(SynchronizationError::RequirementNotMet { 2956 required_for: "One of `dependency_info.memory_barriers`, \ 2957 `dependency_info.buffer_memory_barriers` or \ 2958 `dependency_info.image_memory_barriers` has an element where \ 2959 `src_access` contains `ACCELERATION_STRUCTURE_READ`, and \ 2960 `src_stages` contains a shader stage other than `RAY_TRACING_SHADER`", 2961 requires_one_of: RequiresOneOf { 2962 features: &["ray_query"], 2963 ..Default::default() 2964 }, 2965 }); 2966 } 2967 2968 // VUID-vkCmdWaitEvents2-dependencyFlags-03844 2969 if self.builder_state.render_pass.is_some() 2970 && src_stages.intersects(PipelineStages::HOST) 2971 { 2972 todo!() 2973 } 2974 2975 Ok(()) 2976 }; 2977 2978 let check_queue_family_ownership_transfer = 2979 |ty: char, 2980 barrier_index: usize, 2981 src_stages: PipelineStages, 2982 dst_stages: PipelineStages, 2983 queue_family_ownership_transfer: Option<QueueFamilyOwnershipTransfer>, 2984 sharing: &Sharing<_>| 2985 -> Result<(), SynchronizationError> { 2986 if let Some(transfer) = queue_family_ownership_transfer { 2987 // VUID? 2988 transfer.validate_device(device)?; 2989 2990 // VUID-VkBufferMemoryBarrier2-srcQueueFamilyIndex-04087 2991 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-04070 2992 // Ensured by the definition of `QueueFamilyOwnershipTransfer`. 2993 2994 // VUID-VkBufferMemoryBarrier2-buffer-04088 2995 // VUID-VkImageMemoryBarrier2-image-04071 2996 // Ensured by the definition of `QueueFamilyOwnershipTransfer`. 2997 2998 let queue_family_count = 2999 device.physical_device().queue_family_properties().len() as u32; 3000 3001 let provided_queue_family_index = match (sharing, transfer) { 3002 ( 3003 Sharing::Exclusive, 3004 QueueFamilyOwnershipTransfer::ExclusiveBetweenLocal { 3005 src_index, 3006 dst_index, 3007 }, 3008 ) => Some(max(src_index, dst_index)), 3009 ( 3010 Sharing::Exclusive, 3011 QueueFamilyOwnershipTransfer::ExclusiveToExternal { src_index } 3012 | QueueFamilyOwnershipTransfer::ExclusiveToForeign { src_index }, 3013 ) => Some(src_index), 3014 ( 3015 Sharing::Exclusive, 3016 QueueFamilyOwnershipTransfer::ExclusiveFromExternal { dst_index } 3017 | QueueFamilyOwnershipTransfer::ExclusiveFromForeign { dst_index }, 3018 ) => Some(dst_index), 3019 ( 3020 Sharing::Concurrent(_), 3021 QueueFamilyOwnershipTransfer::ConcurrentToExternal 3022 | QueueFamilyOwnershipTransfer::ConcurrentFromExternal 3023 | QueueFamilyOwnershipTransfer::ConcurrentToForeign 3024 | QueueFamilyOwnershipTransfer::ConcurrentFromForeign, 3025 ) => None, 3026 _ => match ty { 3027 'b' => return Err(SynchronizationError::BufferMemoryBarrierOwnershipTransferSharingMismatch { 3028 barrier_index, 3029 }), 3030 'i' => return Err(SynchronizationError::ImageMemoryBarrierOwnershipTransferSharingMismatch { 3031 barrier_index, 3032 }), 3033 _ => unreachable!(), 3034 }, 3035 }.filter(|&index| index >= queue_family_count); 3036 3037 // VUID-VkBufferMemoryBarrier2-buffer-04089 3038 // VUID-VkImageMemoryBarrier2-image-04072 3039 3040 if let Some(provided_queue_family_index) = provided_queue_family_index { 3041 match ty { 3042 'b' => return Err(SynchronizationError::BufferMemoryBarrierOwnershipTransferIndexOutOfRange { 3043 barrier_index, 3044 provided_queue_family_index, 3045 queue_family_count, 3046 }), 3047 'i' => return Err(SynchronizationError::ImageMemoryBarrierOwnershipTransferIndexOutOfRange { 3048 barrier_index, 3049 provided_queue_family_index, 3050 queue_family_count, 3051 }), 3052 _ => unreachable!(), 3053 } 3054 } 3055 3056 // VUID-VkBufferMemoryBarrier2-srcStageMask-03851 3057 // VUID-VkImageMemoryBarrier2-srcStageMask-03854 3058 if src_stages.intersects(PipelineStages::HOST) 3059 || dst_stages.intersects(PipelineStages::HOST) 3060 { 3061 match ty { 3062 'b' => return Err(SynchronizationError::BufferMemoryBarrierOwnershipTransferHostNotAllowed { 3063 barrier_index, 3064 }), 3065 'i' => return Err(SynchronizationError::ImageMemoryBarrierOwnershipTransferHostForbidden { 3066 barrier_index, 3067 }), 3068 _ => unreachable!(), 3069 } 3070 } 3071 } 3072 3073 Ok(()) 3074 }; 3075 3076 for (barrier_index, barrier) in memory_barriers.iter().enumerate() { 3077 let &MemoryBarrier { 3078 src_stages, 3079 src_access, 3080 dst_stages, 3081 dst_access, 3082 _ne: _, 3083 } = barrier; 3084 3085 /* 3086 Check stages and access 3087 */ 3088 3089 check_stages_access( 3090 'm', 3091 barrier_index, 3092 src_stages, 3093 src_access, 3094 dst_stages, 3095 dst_access, 3096 )?; 3097 } 3098 3099 for (barrier_index, barrier) in buffer_memory_barriers.iter().enumerate() { 3100 let &BufferMemoryBarrier { 3101 src_stages, 3102 src_access, 3103 dst_stages, 3104 dst_access, 3105 queue_family_ownership_transfer, 3106 ref buffer, 3107 ref range, 3108 _ne: _, 3109 } = barrier; 3110 3111 // VUID-VkBufferMemoryBarrier2-buffer-01931 3112 // Ensured by Buffer type construction. 3113 3114 /* 3115 Check stages and access 3116 */ 3117 3118 check_stages_access( 3119 'b', 3120 barrier_index, 3121 src_stages, 3122 src_access, 3123 dst_stages, 3124 dst_access, 3125 )?; 3126 3127 /* 3128 Check queue family transfer 3129 */ 3130 3131 check_queue_family_ownership_transfer( 3132 'b', 3133 barrier_index, 3134 src_stages, 3135 dst_stages, 3136 queue_family_ownership_transfer, 3137 buffer.sharing(), 3138 )?; 3139 3140 /* 3141 Check range 3142 */ 3143 3144 // VUID-VkBufferMemoryBarrier2-size-01188 3145 assert!(!range.is_empty()); 3146 3147 // VUID-VkBufferMemoryBarrier2-offset-01187 3148 // VUID-VkBufferMemoryBarrier2-size-01189 3149 if range.end > buffer.size() { 3150 return Err(SynchronizationError::BufferMemoryBarrierOutOfRange { 3151 barrier_index, 3152 range_end: range.end, 3153 buffer_size: buffer.size(), 3154 }); 3155 } 3156 } 3157 3158 for (barrier_index, barrier) in image_memory_barriers.iter().enumerate() { 3159 let &ImageMemoryBarrier { 3160 src_stages, 3161 src_access, 3162 dst_stages, 3163 dst_access, 3164 old_layout, 3165 new_layout, 3166 queue_family_ownership_transfer, 3167 ref image, 3168 ref subresource_range, 3169 _ne: _, 3170 } = barrier; 3171 3172 // VUID-VkImageMemoryBarrier2-image-01932 3173 // Ensured by Image type construction. 3174 3175 /* 3176 Check stages and access 3177 */ 3178 3179 check_stages_access( 3180 'i', 3181 barrier_index, 3182 src_stages, 3183 src_access, 3184 dst_stages, 3185 dst_access, 3186 )?; 3187 3188 /* 3189 Check layouts 3190 */ 3191 3192 // VUID-VkImageMemoryBarrier2-oldLayout-parameter 3193 old_layout.validate_device(device)?; 3194 3195 // VUID-VkImageMemoryBarrier2-newLayout-parameter 3196 new_layout.validate_device(device)?; 3197 3198 // VUID-VkImageMemoryBarrier2-srcStageMask-03855 3199 if src_stages.intersects(PipelineStages::HOST) 3200 && !matches!( 3201 old_layout, 3202 ImageLayout::Preinitialized | ImageLayout::Undefined | ImageLayout::General 3203 ) 3204 { 3205 return Err( 3206 SynchronizationError::ImageMemoryBarrierOldLayoutFromHostInvalid { 3207 barrier_index, 3208 old_layout, 3209 }, 3210 ); 3211 } 3212 3213 // VUID-VkImageMemoryBarrier2-oldLayout-01197 3214 // Not checked yet, therefore unsafe. 3215 3216 // VUID-VkImageMemoryBarrier2-newLayout-01198 3217 if matches!( 3218 new_layout, 3219 ImageLayout::Undefined | ImageLayout::Preinitialized 3220 ) { 3221 return Err(SynchronizationError::ImageMemoryBarrierNewLayoutInvalid { 3222 barrier_index, 3223 }); 3224 } 3225 3226 // VUID-VkImageMemoryBarrier2-attachmentFeedbackLoopLayout-07313 3227 /*if !device.enabled_features().attachment_feedback_loop_layout 3228 && matches!(new_layout, ImageLayout::AttachmentFeedbackLoopOptimal) 3229 { 3230 return Err(SynchronizationError::RequirementNotMet { 3231 required_for: "`dependency_info.image_memory_barriers` has an element where \ 3232 `new_layout` is `AttachmentFeedbackLoopOptimal`", 3233 requires_one_of: RequiresOneOf { 3234 features: &["attachment_feedback_loop_layout"], 3235 ..Default::default() 3236 }, 3237 }); 3238 }*/ 3239 3240 for layout in [old_layout, new_layout] { 3241 // VUID-VkImageMemoryBarrier2-synchronization2-06911 3242 /*if !device.enabled_features().synchronization2 3243 && matches!( 3244 layout, 3245 ImageLayout::AttachmentOptimal | ImageLayout::ReadOnlyOptimal 3246 ) 3247 { 3248 return Err(SynchronizationError::RequirementNotMet { 3249 required_for: "`dependency_info.image_memory_barriers` has an element \ 3250 where `old_layout` or `new_layout` is `AttachmentOptimal` or \ 3251 `ReadOnlyOptimal`", 3252 requires_one_of: RequiresOneOf { 3253 features: &["synchronization2"], 3254 ..Default::default() 3255 }, 3256 }); 3257 }*/ 3258 3259 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-07006 3260 /*if layout == ImageLayout::AttachmentFeedbackLoopOptimal { 3261 if !image.usage().intersects( 3262 ImageUsage::COLOR_ATTACHMENT | ImageUsage::DEPTH_STENCIL_ATTACHMENT, 3263 ) { 3264 return Err( 3265 SynchronizationError::ImageMemoryBarrierImageMissingUsageForLayout { 3266 barrier_index, 3267 layout, 3268 requires_one_of_usage: ImageUsage::COLOR_ATTACHMENT 3269 | ImageUsage::DEPTH_STENCIL_ATTACHMENT, 3270 }, 3271 ); 3272 } 3273 3274 if !image 3275 .usage() 3276 .intersects(ImageUsage::INPUT_ATTACHMENT | ImageUsage::SAMPLED) 3277 { 3278 return Err( 3279 SynchronizationError::ImageMemoryBarrierImageMissingUsageForLayout { 3280 barrier_index, 3281 layout, 3282 requires_one_of_usage: ImageUsage::INPUT_ATTACHMENT 3283 | ImageUsage::SAMPLED, 3284 }, 3285 ); 3286 } 3287 3288 if !image 3289 .usage() 3290 .intersects(ImageUsage::ATTACHMENT_FEEDBACK_LOOP) 3291 { 3292 return Err( 3293 SynchronizationError::ImageMemoryBarrierImageMissingUsageForLayout { 3294 barrier_index, 3295 layout, 3296 requires_one_of_usage: ImageUsage::ATTACHMENT_FEEDBACK_LOOP, 3297 }, 3298 ); 3299 } 3300 }*/ 3301 3302 let requires_one_of_usage = match layout { 3303 // VUID-VkImageMemoryBarrier2-oldLayout-01208 3304 ImageLayout::ColorAttachmentOptimal => ImageUsage::COLOR_ATTACHMENT, 3305 3306 // VUID-VkImageMemoryBarrier2-oldLayout-01209 3307 ImageLayout::DepthStencilAttachmentOptimal => { 3308 ImageUsage::DEPTH_STENCIL_ATTACHMENT 3309 } 3310 3311 // VUID-VkImageMemoryBarrier2-oldLayout-01210 3312 ImageLayout::DepthStencilReadOnlyOptimal => { 3313 ImageUsage::DEPTH_STENCIL_ATTACHMENT 3314 } 3315 3316 // VUID-VkImageMemoryBarrier2-oldLayout-01211 3317 ImageLayout::ShaderReadOnlyOptimal => { 3318 ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT 3319 } 3320 3321 // VUID-VkImageMemoryBarrier2-oldLayout-01212 3322 ImageLayout::TransferSrcOptimal => ImageUsage::TRANSFER_SRC, 3323 3324 // VUID-VkImageMemoryBarrier2-oldLayout-01213 3325 ImageLayout::TransferDstOptimal => ImageUsage::TRANSFER_DST, 3326 3327 // VUID-VkImageMemoryBarrier2-oldLayout-01658 3328 ImageLayout::DepthReadOnlyStencilAttachmentOptimal => { 3329 ImageUsage::DEPTH_STENCIL_ATTACHMENT 3330 } 3331 3332 // VUID-VkImageMemoryBarrier2-oldLayout-01659 3333 ImageLayout::DepthAttachmentStencilReadOnlyOptimal => { 3334 ImageUsage::DEPTH_STENCIL_ATTACHMENT 3335 } 3336 3337 /* 3338 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-04065 3339 ImageLayout::DepthReadOnlyOptimal => { 3340 ImageUsage::DEPTH_STENCIL_ATTACHMENT 3341 | ImageUsage::SAMPLED 3342 | ImageUsage::INPUT_ATTACHMENT 3343 } 3344 3345 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-04066 3346 ImageLayout::DepthAttachmentOptimal => ImageUsage::DEPTH_STENCIL_ATTACHMENT, 3347 3348 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-04067 3349 ImageLayout::StencilReadOnlyOptimal => { 3350 ImageUsage::DEPTH_STENCIL_ATTACHMENT 3351 | ImageUsage::SAMPLED 3352 | ImageUsage::INPUT_ATTACHMENT 3353 } 3354 3355 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-04068 3356 ImageLayout::StencilAttachmentOptimal => ImageUsage::DEPTH_STENCIL_ATTACHMENT, 3357 3358 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-03938 3359 ImageLayout::AttachmentOptimal => { 3360 ImageUsage::COLOR_ATTACHMENT | ImageUsage::DEPTH_STENCIL_ATTACHMENT 3361 } 3362 3363 // VUID-VkImageMemoryBarrier2-srcQueueFamilyIndex-03939 3364 ImageLayout::ReadOnlyOptimal => { 3365 ImageUsage::DEPTH_STENCIL_ATTACHMENT 3366 | ImageUsage::SAMPLED 3367 | ImageUsage::INPUT_ATTACHMENT 3368 } 3369 3370 // VUID-VkImageMemoryBarrier2-oldLayout-02088 3371 ImageLayout::FragmentShadingRateAttachmentOptimal => { 3372 ImageUsage::FRAGMENT_SHADING_RATE_ATTACHMENT 3373 } 3374 */ 3375 _ => continue, 3376 }; 3377 3378 if !image.usage().intersects(requires_one_of_usage) { 3379 return Err( 3380 SynchronizationError::ImageMemoryBarrierImageMissingUsageForLayout { 3381 barrier_index, 3382 layout, 3383 requires_one_of_usage, 3384 }, 3385 ); 3386 } 3387 } 3388 3389 /* 3390 Check queue family tansfer 3391 */ 3392 3393 check_queue_family_ownership_transfer( 3394 'i', 3395 barrier_index, 3396 src_stages, 3397 dst_stages, 3398 queue_family_ownership_transfer, 3399 image.sharing(), 3400 )?; 3401 3402 /* 3403 Check subresource range 3404 */ 3405 3406 // VUID-VkImageSubresourceRange-aspectMask-requiredbitmask 3407 assert!(!subresource_range.aspects.is_empty()); 3408 3409 // VUID-VkImageSubresourceRange-aspectMask-parameter 3410 subresource_range.aspects.validate_device(device)?; 3411 3412 let image_aspects = image.format().unwrap().aspects(); 3413 3414 // VUID-VkImageMemoryBarrier2-image-01673 3415 // VUID-VkImageMemoryBarrier2-image-03319 3416 if image_aspects.contains(subresource_range.aspects) { 3417 return Err(SynchronizationError::ImageMemoryBarrierAspectsNotAllowed { 3418 barrier_index, 3419 aspects: subresource_range.aspects - image_aspects, 3420 }); 3421 } 3422 3423 if image_aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL) { 3424 // VUID-VkImageMemoryBarrier2-image-03320 3425 if !device.enabled_features().separate_depth_stencil_layouts 3426 && image_aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL) 3427 && !subresource_range 3428 .aspects 3429 .contains(ImageAspects::DEPTH | ImageAspects::STENCIL) 3430 { 3431 return Err(SynchronizationError::RequirementNotMet { 3432 required_for: "`dependency_info.image_memory_barriers` has an element \ 3433 where `image` has both a depth and a stencil aspect, and \ 3434 `subresource_range.aspects` does not contain both aspects", 3435 requires_one_of: RequiresOneOf { 3436 features: &["separate_depth_stencil_layouts"], 3437 ..Default::default() 3438 }, 3439 }); 3440 } 3441 } else { 3442 // VUID-VkImageMemoryBarrier2-image-01671 3443 if !image.flags().intersects(ImageCreateFlags::DISJOINT) 3444 && subresource_range.aspects != ImageAspects::COLOR 3445 { 3446 return Err(SynchronizationError::ImageMemoryBarrierAspectsNotAllowed { 3447 barrier_index, 3448 aspects: subresource_range.aspects - ImageAspects::COLOR, 3449 }); 3450 } 3451 } 3452 3453 // VUID-VkImageSubresourceRange-levelCount-01720 3454 assert!(!subresource_range.mip_levels.is_empty()); 3455 3456 // VUID-VkImageMemoryBarrier2-subresourceRange-01486 3457 // VUID-VkImageMemoryBarrier2-subresourceRange-01724 3458 if subresource_range.mip_levels.end > image.mip_levels() { 3459 return Err( 3460 SynchronizationError::ImageMemoryBarrierMipLevelsOutOfRange { 3461 barrier_index, 3462 mip_levels_range_end: subresource_range.mip_levels.end, 3463 image_mip_levels: image.mip_levels(), 3464 }, 3465 ); 3466 } 3467 3468 // VUID-VkImageSubresourceRange-layerCount-01721 3469 assert!(!subresource_range.array_layers.is_empty()); 3470 3471 // VUID-VkImageMemoryBarrier2-subresourceRange-01488 3472 // VUID-VkImageMemoryBarrier2-subresourceRange-01725 3473 if subresource_range.array_layers.end > image.dimensions().array_layers() { 3474 return Err( 3475 SynchronizationError::ImageMemoryBarrierArrayLayersOutOfRange { 3476 barrier_index, 3477 array_layers_range_end: subresource_range.array_layers.end, 3478 image_array_layers: image.dimensions().array_layers(), 3479 }, 3480 ); 3481 } 3482 } 3483 } 3484 3485 Ok(()) 3486 } 3487 3488 #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] wait_events_unchecked( &mut self, events: impl IntoIterator<Item = (Arc<Event>, DependencyInfo)>, ) -> &mut Self3489 pub unsafe fn wait_events_unchecked( 3490 &mut self, 3491 events: impl IntoIterator<Item = (Arc<Event>, DependencyInfo)>, 3492 ) -> &mut Self { 3493 let events: SmallVec<[(Arc<Event>, DependencyInfo); 4]> = events.into_iter().collect(); 3494 let fns = self.device().fns(); 3495 3496 // VUID-vkCmdWaitEvents2-pEvents-03837 3497 // Ensured by using `vkCmdSetEvent2` and `vkCmdWaitEvents2` under the exact same 3498 // conditions, i.e. when `synchronization2` is enabled. 3499 3500 if self.device().enabled_features().synchronization2 { 3501 struct PerDependencyInfo { 3502 memory_barriers_vk: SmallVec<[ash::vk::MemoryBarrier2; 2]>, 3503 buffer_memory_barriers_vk: SmallVec<[ash::vk::BufferMemoryBarrier2; 8]>, 3504 image_memory_barriers_vk: SmallVec<[ash::vk::ImageMemoryBarrier2; 8]>, 3505 } 3506 3507 let mut events_vk: SmallVec<[_; 4]> = SmallVec::new(); 3508 let mut dependency_infos_vk: SmallVec<[_; 4]> = SmallVec::new(); 3509 let mut per_dependency_info_vk: SmallVec<[_; 4]> = SmallVec::new(); 3510 3511 for (event, dependency_info) in &events { 3512 let &DependencyInfo { 3513 dependency_flags, 3514 ref memory_barriers, 3515 ref buffer_memory_barriers, 3516 ref image_memory_barriers, 3517 _ne: _, 3518 } = dependency_info; 3519 3520 let memory_barriers_vk: SmallVec<[_; 2]> = memory_barriers 3521 .iter() 3522 .map(|barrier| { 3523 let &MemoryBarrier { 3524 src_stages, 3525 src_access, 3526 dst_stages, 3527 dst_access, 3528 _ne: _, 3529 } = barrier; 3530 3531 ash::vk::MemoryBarrier2 { 3532 src_stage_mask: src_stages.into(), 3533 src_access_mask: src_access.into(), 3534 dst_stage_mask: dst_stages.into(), 3535 dst_access_mask: dst_access.into(), 3536 ..Default::default() 3537 } 3538 }) 3539 .collect(); 3540 3541 let buffer_memory_barriers_vk: SmallVec<[_; 8]> = buffer_memory_barriers 3542 .iter() 3543 .map(|barrier| { 3544 let &BufferMemoryBarrier { 3545 src_stages, 3546 src_access, 3547 dst_stages, 3548 dst_access, 3549 queue_family_ownership_transfer, 3550 ref buffer, 3551 ref range, 3552 _ne: _, 3553 } = barrier; 3554 3555 let (src_queue_family_index, dst_queue_family_index) = 3556 queue_family_ownership_transfer.map_or( 3557 (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), 3558 Into::into, 3559 ); 3560 3561 ash::vk::BufferMemoryBarrier2 { 3562 src_stage_mask: src_stages.into(), 3563 src_access_mask: src_access.into(), 3564 dst_stage_mask: dst_stages.into(), 3565 dst_access_mask: dst_access.into(), 3566 src_queue_family_index, 3567 dst_queue_family_index, 3568 buffer: buffer.handle(), 3569 offset: range.start, 3570 size: range.end - range.start, 3571 ..Default::default() 3572 } 3573 }) 3574 .collect(); 3575 3576 let image_memory_barriers_vk: SmallVec<[_; 8]> = image_memory_barriers 3577 .iter() 3578 .map(|barrier| { 3579 let &ImageMemoryBarrier { 3580 src_stages, 3581 src_access, 3582 dst_stages, 3583 dst_access, 3584 old_layout, 3585 new_layout, 3586 queue_family_ownership_transfer, 3587 ref image, 3588 ref subresource_range, 3589 _ne: _, 3590 } = barrier; 3591 3592 let (src_queue_family_index, dst_queue_family_index) = 3593 queue_family_ownership_transfer.map_or( 3594 (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), 3595 Into::into, 3596 ); 3597 3598 ash::vk::ImageMemoryBarrier2 { 3599 src_stage_mask: src_stages.into(), 3600 src_access_mask: src_access.into(), 3601 dst_stage_mask: dst_stages.into(), 3602 dst_access_mask: dst_access.into(), 3603 old_layout: old_layout.into(), 3604 new_layout: new_layout.into(), 3605 src_queue_family_index, 3606 dst_queue_family_index, 3607 image: image.handle(), 3608 subresource_range: subresource_range.clone().into(), 3609 ..Default::default() 3610 } 3611 }) 3612 .collect(); 3613 3614 events_vk.push(event.handle()); 3615 dependency_infos_vk.push(ash::vk::DependencyInfo { 3616 dependency_flags: dependency_flags.into(), 3617 memory_barrier_count: 0, 3618 p_memory_barriers: ptr::null(), 3619 buffer_memory_barrier_count: 0, 3620 p_buffer_memory_barriers: ptr::null(), 3621 image_memory_barrier_count: 0, 3622 p_image_memory_barriers: ptr::null(), 3623 ..Default::default() 3624 }); 3625 per_dependency_info_vk.push(PerDependencyInfo { 3626 memory_barriers_vk, 3627 buffer_memory_barriers_vk, 3628 image_memory_barriers_vk, 3629 }); 3630 } 3631 3632 for ( 3633 dependency_info_vk, 3634 PerDependencyInfo { 3635 memory_barriers_vk, 3636 buffer_memory_barriers_vk, 3637 image_memory_barriers_vk, 3638 }, 3639 ) in (dependency_infos_vk.iter_mut()).zip(per_dependency_info_vk.iter_mut()) 3640 { 3641 *dependency_info_vk = ash::vk::DependencyInfo { 3642 memory_barrier_count: memory_barriers_vk.len() as u32, 3643 p_memory_barriers: memory_barriers_vk.as_ptr(), 3644 buffer_memory_barrier_count: buffer_memory_barriers_vk.len() as u32, 3645 p_buffer_memory_barriers: buffer_memory_barriers_vk.as_ptr(), 3646 image_memory_barrier_count: image_memory_barriers_vk.len() as u32, 3647 p_image_memory_barriers: image_memory_barriers_vk.as_ptr(), 3648 ..*dependency_info_vk 3649 } 3650 } 3651 3652 if self.device().api_version() >= Version::V1_3 { 3653 (fns.v1_3.cmd_wait_events2)( 3654 self.handle(), 3655 events_vk.len() as u32, 3656 events_vk.as_ptr(), 3657 dependency_infos_vk.as_ptr(), 3658 ); 3659 } else { 3660 debug_assert!(self.device().enabled_extensions().khr_synchronization2); 3661 (fns.khr_synchronization2.cmd_wait_events2_khr)( 3662 self.handle(), 3663 events_vk.len() as u32, 3664 events_vk.as_ptr(), 3665 dependency_infos_vk.as_ptr(), 3666 ); 3667 } 3668 } else { 3669 // With the original function, you can only specify a single dependency info for all 3670 // events at once, rather than separately for each event. Therefore, to achieve the 3671 // same behaviour as the "2" function, we split it up into multiple Vulkan API calls, 3672 // one per event. 3673 3674 for (event, dependency_info) in &events { 3675 let events_vk = [event.handle()]; 3676 3677 let DependencyInfo { 3678 dependency_flags: _, 3679 memory_barriers, 3680 buffer_memory_barriers, 3681 image_memory_barriers, 3682 _ne: _, 3683 } = dependency_info; 3684 3685 let mut src_stage_mask = ash::vk::PipelineStageFlags::empty(); 3686 let mut dst_stage_mask = ash::vk::PipelineStageFlags::empty(); 3687 3688 let memory_barriers_vk: SmallVec<[_; 2]> = memory_barriers 3689 .iter() 3690 .map(|barrier| { 3691 let &MemoryBarrier { 3692 src_stages, 3693 src_access, 3694 dst_stages, 3695 dst_access, 3696 _ne: _, 3697 } = barrier; 3698 3699 src_stage_mask |= src_stages.into(); 3700 dst_stage_mask |= dst_stages.into(); 3701 3702 ash::vk::MemoryBarrier { 3703 src_access_mask: src_access.into(), 3704 dst_access_mask: dst_access.into(), 3705 ..Default::default() 3706 } 3707 }) 3708 .collect(); 3709 3710 let buffer_memory_barriers_vk: SmallVec<[_; 8]> = buffer_memory_barriers 3711 .iter() 3712 .map(|barrier| { 3713 let &BufferMemoryBarrier { 3714 src_stages, 3715 src_access, 3716 dst_stages, 3717 dst_access, 3718 queue_family_ownership_transfer, 3719 ref buffer, 3720 ref range, 3721 _ne: _, 3722 } = barrier; 3723 3724 src_stage_mask |= src_stages.into(); 3725 dst_stage_mask |= dst_stages.into(); 3726 3727 let (src_queue_family_index, dst_queue_family_index) = 3728 queue_family_ownership_transfer.map_or( 3729 (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), 3730 Into::into, 3731 ); 3732 3733 ash::vk::BufferMemoryBarrier { 3734 src_access_mask: src_access.into(), 3735 dst_access_mask: dst_access.into(), 3736 src_queue_family_index, 3737 dst_queue_family_index, 3738 buffer: buffer.handle(), 3739 offset: range.start, 3740 size: range.end - range.start, 3741 ..Default::default() 3742 } 3743 }) 3744 .collect(); 3745 3746 let image_memory_barriers_vk: SmallVec<[_; 8]> = image_memory_barriers 3747 .iter() 3748 .map(|barrier| { 3749 let &ImageMemoryBarrier { 3750 src_stages, 3751 src_access, 3752 dst_stages, 3753 dst_access, 3754 old_layout, 3755 new_layout, 3756 queue_family_ownership_transfer, 3757 ref image, 3758 ref subresource_range, 3759 _ne: _, 3760 } = barrier; 3761 3762 src_stage_mask |= src_stages.into(); 3763 dst_stage_mask |= dst_stages.into(); 3764 3765 let (src_queue_family_index, dst_queue_family_index) = 3766 queue_family_ownership_transfer.map_or( 3767 (ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED), 3768 Into::into, 3769 ); 3770 3771 ash::vk::ImageMemoryBarrier { 3772 src_access_mask: src_access.into(), 3773 dst_access_mask: dst_access.into(), 3774 old_layout: old_layout.into(), 3775 new_layout: new_layout.into(), 3776 src_queue_family_index, 3777 dst_queue_family_index, 3778 image: image.handle(), 3779 subresource_range: subresource_range.clone().into(), 3780 ..Default::default() 3781 } 3782 }) 3783 .collect(); 3784 3785 if src_stage_mask.is_empty() { 3786 // "VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT is [...] equivalent to 3787 // VK_PIPELINE_STAGE_2_NONE in the first scope." 3788 src_stage_mask |= ash::vk::PipelineStageFlags::TOP_OF_PIPE; 3789 } 3790 3791 if dst_stage_mask.is_empty() { 3792 // "VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT is [...] equivalent to 3793 // VK_PIPELINE_STAGE_2_NONE in the second scope." 3794 dst_stage_mask |= ash::vk::PipelineStageFlags::BOTTOM_OF_PIPE; 3795 } 3796 3797 (fns.v1_0.cmd_wait_events)( 3798 self.handle(), 3799 1, 3800 events_vk.as_ptr(), 3801 src_stage_mask, 3802 dst_stage_mask, 3803 memory_barriers_vk.len() as u32, 3804 memory_barriers_vk.as_ptr(), 3805 buffer_memory_barriers_vk.len() as u32, 3806 buffer_memory_barriers_vk.as_ptr(), 3807 image_memory_barriers_vk.len() as u32, 3808 image_memory_barriers_vk.as_ptr(), 3809 ); 3810 } 3811 } 3812 3813 self.resources 3814 .extend(events.into_iter().map(|(event, _)| Box::new(event) as _)); 3815 3816 // TODO: sync state update 3817 3818 self.next_command_index += 1; 3819 self 3820 } 3821 3822 /// Resets an [`Event`] back to the unsignaled state. 3823 /// 3824 /// # Safety 3825 /// 3826 /// - Appropriate synchronization must be provided for `event` against any previous 3827 /// [`set_event`] or [`wait_events`] command. 3828 /// 3829 /// [`set_event`]: Self::set_event 3830 /// [`wait_events`]: Self::wait_events 3831 #[inline] reset_event( &mut self, event: Arc<Event>, stages: PipelineStages, ) -> Result<&mut Self, SynchronizationError>3832 pub unsafe fn reset_event( 3833 &mut self, 3834 event: Arc<Event>, 3835 stages: PipelineStages, 3836 ) -> Result<&mut Self, SynchronizationError> { 3837 self.validate_reset_event(&event, stages)?; 3838 3839 unsafe { Ok(self.reset_event_unchecked(event, stages)) } 3840 } 3841 validate_reset_event( &self, event: &Event, stages: PipelineStages, ) -> Result<(), SynchronizationError>3842 fn validate_reset_event( 3843 &self, 3844 event: &Event, 3845 stages: PipelineStages, 3846 ) -> Result<(), SynchronizationError> { 3847 // VUID-vkCmdResetEvent2-renderpass 3848 if self.builder_state.render_pass.is_some() { 3849 return Err(SynchronizationError::ForbiddenInsideRenderPass); 3850 } 3851 3852 // VUID-vkCmdResetEvent2-commandBuffer-03833 3853 // TODO: 3854 3855 let device = self.device(); 3856 let queue_family_properties = self.queue_family_properties(); 3857 3858 // VUID-vkCmdResetEvent2-commandBuffer-cmdpool 3859 if !queue_family_properties.queue_flags.intersects( 3860 QueueFlags::GRAPHICS 3861 | QueueFlags::COMPUTE 3862 | QueueFlags::VIDEO_DECODE 3863 | QueueFlags::VIDEO_ENCODE, 3864 ) { 3865 return Err(SynchronizationError::NotSupportedByQueueFamily); 3866 } 3867 3868 // VUID-vkCmdResetEvent2-commonparent 3869 assert_eq!(device, event.device()); 3870 3871 // VUID-vkCmdResetEvent2-stageMask-parameter 3872 stages.validate_device(device)?; 3873 3874 // VUID-vkCmdResetEvent2-synchronization2-03829 3875 if !device.enabled_features().synchronization2 { 3876 if stages.is_2() { 3877 return Err(SynchronizationError::RequirementNotMet { 3878 required_for: "`stages` contains flags from `VkPipelineStageFlagBits2`", 3879 requires_one_of: RequiresOneOf { 3880 features: &["synchronization2"], 3881 ..Default::default() 3882 }, 3883 }); 3884 } 3885 } 3886 3887 // VUID-vkCmdResetEvent2-stageMask-03929 3888 if stages.intersects(PipelineStages::GEOMETRY_SHADER) 3889 && !device.enabled_features().geometry_shader 3890 { 3891 return Err(SynchronizationError::RequirementNotMet { 3892 required_for: "`stages` contains `PipelineStages::GEOMETRY_SHADER`", 3893 requires_one_of: RequiresOneOf { 3894 features: &["geometry_shader"], 3895 ..Default::default() 3896 }, 3897 }); 3898 } 3899 3900 // VUID-vkCmdResetEvent2-stageMask-03930 3901 if stages.intersects( 3902 PipelineStages::TESSELLATION_CONTROL_SHADER 3903 | PipelineStages::TESSELLATION_EVALUATION_SHADER, 3904 ) && !device.enabled_features().tessellation_shader 3905 { 3906 return Err(SynchronizationError::RequirementNotMet { 3907 required_for: "`stages` contains `PipelineStages::TESSELLATION_CONTROL_SHADER` or \ 3908 `PipelineStages::TESSELLATION_EVALUATION_SHADER`", 3909 requires_one_of: RequiresOneOf { 3910 features: &["tessellation_shader"], 3911 ..Default::default() 3912 }, 3913 }); 3914 } 3915 3916 // VUID-vkCmdResetEvent2-stageMask-03931 3917 if stages.intersects(PipelineStages::CONDITIONAL_RENDERING) 3918 && !device.enabled_features().conditional_rendering 3919 { 3920 return Err(SynchronizationError::RequirementNotMet { 3921 required_for: "`stages` contains `PipelineStages::CONDITIONAL_RENDERING`", 3922 requires_one_of: RequiresOneOf { 3923 features: &["conditional_rendering"], 3924 ..Default::default() 3925 }, 3926 }); 3927 } 3928 3929 // VUID-vkCmdResetEvent2-stageMask-03932 3930 if stages.intersects(PipelineStages::FRAGMENT_DENSITY_PROCESS) 3931 && !device.enabled_features().fragment_density_map 3932 { 3933 return Err(SynchronizationError::RequirementNotMet { 3934 required_for: "`stages` contains `PipelineStages::FRAGMENT_DENSITY_PROCESS`", 3935 requires_one_of: RequiresOneOf { 3936 features: &["fragment_density_map"], 3937 ..Default::default() 3938 }, 3939 }); 3940 } 3941 3942 // VUID-vkCmdResetEvent2-stageMask-03933 3943 if stages.intersects(PipelineStages::TRANSFORM_FEEDBACK) 3944 && !device.enabled_features().transform_feedback 3945 { 3946 return Err(SynchronizationError::RequirementNotMet { 3947 required_for: "`stages` contains `PipelineStages::TRANSFORM_FEEDBACK`", 3948 requires_one_of: RequiresOneOf { 3949 features: &["transform_feedback"], 3950 ..Default::default() 3951 }, 3952 }); 3953 } 3954 3955 // VUID-vkCmdResetEvent2-stageMask-03934 3956 if stages.intersects(PipelineStages::MESH_SHADER) && !device.enabled_features().mesh_shader 3957 { 3958 return Err(SynchronizationError::RequirementNotMet { 3959 required_for: "`stages` contains `PipelineStages::MESH_SHADER`", 3960 requires_one_of: RequiresOneOf { 3961 features: &["mesh_shader"], 3962 ..Default::default() 3963 }, 3964 }); 3965 } 3966 3967 // VUID-vkCmdResetEvent2-stageMask-03935 3968 if stages.intersects(PipelineStages::TASK_SHADER) && !device.enabled_features().task_shader 3969 { 3970 return Err(SynchronizationError::RequirementNotMet { 3971 required_for: "`stages` contains `PipelineStages::TASK_SHADER`", 3972 requires_one_of: RequiresOneOf { 3973 features: &["task_shader"], 3974 ..Default::default() 3975 }, 3976 }); 3977 } 3978 3979 // VUID-vkCmdResetEvent2-shadingRateImage-07316 3980 if stages.intersects(PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT) 3981 && !(device.enabled_features().attachment_fragment_shading_rate 3982 || device.enabled_features().shading_rate_image) 3983 { 3984 return Err(SynchronizationError::RequirementNotMet { 3985 required_for: "`stages` contains \ 3986 `PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT`", 3987 requires_one_of: RequiresOneOf { 3988 features: &["attachment_fragment_shading_rate", "shading_rate_image"], 3989 ..Default::default() 3990 }, 3991 }); 3992 } 3993 3994 // VUID-vkCmdResetEvent2-stageMask-04957 3995 if stages.intersects(PipelineStages::SUBPASS_SHADING) 3996 && !device.enabled_features().subpass_shading 3997 { 3998 return Err(SynchronizationError::RequirementNotMet { 3999 required_for: "`stages` contains `PipelineStages::SUBPASS_SHADING`", 4000 requires_one_of: RequiresOneOf { 4001 features: &["subpass_shading"], 4002 ..Default::default() 4003 }, 4004 }); 4005 } 4006 4007 // VUID-vkCmdResetEvent2-stageMask-04995 4008 if stages.intersects(PipelineStages::INVOCATION_MASK) 4009 && !device.enabled_features().invocation_mask 4010 { 4011 return Err(SynchronizationError::RequirementNotMet { 4012 required_for: "`stages` contains `PipelineStages::INVOCATION_MASK`", 4013 requires_one_of: RequiresOneOf { 4014 features: &["invocation_mask"], 4015 ..Default::default() 4016 }, 4017 }); 4018 } 4019 4020 // VUID-vkCmdResetEvent-stageMask-03937 4021 if stages.is_empty() && !device.enabled_features().synchronization2 { 4022 return Err(SynchronizationError::RequirementNotMet { 4023 required_for: "`stages` is empty", 4024 requires_one_of: RequiresOneOf { 4025 features: &["synchronization2"], 4026 ..Default::default() 4027 }, 4028 }); 4029 } 4030 4031 // VUID-vkCmdResetEvent2-stageMask-03830 4032 if stages.intersects(PipelineStages::HOST) { 4033 todo!() 4034 } 4035 4036 // VUID-vkCmdResetEvent2-event-03831 4037 // VUID-vkCmdResetEvent2-event-03832 4038 // TODO: 4039 4040 Ok(()) 4041 } 4042 4043 #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] reset_event_unchecked( &mut self, event: Arc<Event>, stages: PipelineStages, ) -> &mut Self4044 pub unsafe fn reset_event_unchecked( 4045 &mut self, 4046 event: Arc<Event>, 4047 stages: PipelineStages, 4048 ) -> &mut Self { 4049 let fns = self.device().fns(); 4050 4051 if self.device().enabled_features().synchronization2 { 4052 if self.device().api_version() >= Version::V1_3 { 4053 (fns.v1_3.cmd_reset_event2)(self.handle(), event.handle(), stages.into()); 4054 } else { 4055 debug_assert!(self.device().enabled_extensions().khr_synchronization2); 4056 (fns.khr_synchronization2.cmd_reset_event2_khr)( 4057 self.handle(), 4058 event.handle(), 4059 stages.into(), 4060 ); 4061 } 4062 } else { 4063 (fns.v1_0.cmd_reset_event)(self.handle(), event.handle(), stages.into()); 4064 } 4065 4066 self.resources.push(Box::new(event)); 4067 4068 // TODO: sync state update 4069 4070 self.next_command_index += 1; 4071 self 4072 } 4073 } 4074 4075 /// Error that can happen when recording a synchronization command. 4076 #[derive(Clone, Debug)] 4077 pub enum SynchronizationError { 4078 RequirementNotMet { 4079 required_for: &'static str, 4080 requires_one_of: RequiresOneOf, 4081 }, 4082 4083 /// One or more accesses of a buffer memory barrier are not supported by the corresponding 4084 /// pipeline stages. 4085 BufferMemoryBarrierAccessNotSupportedByStages { barrier_index: usize }, 4086 4087 /// Buffer memory barriers are forbidden inside a render pass instance. 4088 BufferMemoryBarrierForbiddenInsideRenderPass, 4089 4090 /// The end of `range` of a buffer memory barrier is greater than the size of `buffer`. 4091 BufferMemoryBarrierOutOfRange { 4092 barrier_index: usize, 4093 range_end: DeviceSize, 4094 buffer_size: DeviceSize, 4095 }, 4096 4097 /// A buffer memory barrier contains a queue family ownership transfer, but either the 4098 /// `src_stages` or `dst_stages` contain [`HOST`]. 4099 /// 4100 /// [`HOST`]: crate::sync::PipelineStages::HOST 4101 BufferMemoryBarrierOwnershipTransferHostNotAllowed { barrier_index: usize }, 4102 4103 /// The provided `src_index` or `dst_index` in the queue family ownership transfer of a 4104 /// buffer memory barrier is not less than the number of queue families in the physical device. 4105 BufferMemoryBarrierOwnershipTransferIndexOutOfRange { 4106 barrier_index: usize, 4107 provided_queue_family_index: u32, 4108 queue_family_count: u32, 4109 }, 4110 4111 /// The provided `queue_family_ownership_transfer` value of a buffer memory barrier does not 4112 /// match the sharing mode of `buffer`. 4113 BufferMemoryBarrierOwnershipTransferSharingMismatch { barrier_index: usize }, 4114 4115 /// One or more pipeline stages of a buffer memory barrier are not supported by the queue 4116 /// family of the command buffer. 4117 BufferMemoryBarrierStageNotSupported { barrier_index: usize }, 4118 4119 /// A render pass instance is not active, and the `VIEW_LOCAL` dependency flag was provided. 4120 DependencyFlagsViewLocalNotAllowed, 4121 4122 /// Operation forbidden inside a render pass. 4123 ForbiddenInsideRenderPass, 4124 4125 /// Operation forbidden inside a render pass instance that was begun with `begin_rendering`. 4126 ForbiddenWithBeginRendering, 4127 4128 /// One or more accesses of an image memory barrier are not supported by the corresponding 4129 /// pipeline stages. 4130 ImageMemoryBarrierAccessNotSupportedByStages { barrier_index: usize }, 4131 4132 /// The end of the range of array layers of the subresource range of an image memory barrier 4133 /// is greater than the number of array layers in the image. 4134 ImageMemoryBarrierArrayLayersOutOfRange { 4135 barrier_index: usize, 4136 array_layers_range_end: u32, 4137 image_array_layers: u32, 4138 }, 4139 4140 /// The aspects of the subresource range of an image memory barrier contain aspects that are 4141 /// not present in the image, or that are not allowed. 4142 ImageMemoryBarrierAspectsNotAllowed { 4143 barrier_index: usize, 4144 aspects: ImageAspects, 4145 }, 4146 4147 /// For the `old_layout` or `new_layout` of an image memory barrier, `image` does not have a 4148 /// usage that is required. 4149 ImageMemoryBarrierImageMissingUsageForLayout { 4150 barrier_index: usize, 4151 layout: ImageLayout, 4152 requires_one_of_usage: ImageUsage, 4153 }, 4154 4155 /// An image memory barrier contains an image layout transition, but a render pass 4156 /// instance is active. 4157 ImageMemoryBarrierLayoutTransitionForbiddenInsideRenderPass { barrier_index: usize }, 4158 4159 /// The end of the range of mip levels of the subresource range of an image memory barrier 4160 /// is greater than the number of mip levels in the image. 4161 ImageMemoryBarrierMipLevelsOutOfRange { 4162 barrier_index: usize, 4163 mip_levels_range_end: u32, 4164 image_mip_levels: u32, 4165 }, 4166 4167 /// The `new_layout` of an image memory barrier is `Undefined` or `Preinitialized`. 4168 ImageMemoryBarrierNewLayoutInvalid { barrier_index: usize }, 4169 4170 /// A render pass instance is active, and the image of an image memory barrier is not a color 4171 /// or depth/stencil attachment of the current subpass. 4172 ImageMemoryBarrierNotColorDepthStencilAttachment { barrier_index: usize }, 4173 4174 /// A render pass instance is active, and the image of an image memory barrier is not an input 4175 /// attachment of the current subpass. 4176 ImageMemoryBarrierNotInputAttachment { barrier_index: usize }, 4177 4178 /// The `src_stages` of an image memory barrier contains [`HOST`], but `old_layout` is not 4179 /// `Preinitialized`, `Undefined` or `General`. 4180 /// 4181 /// [`HOST`]: crate::sync::PipelineStages::HOST 4182 ImageMemoryBarrierOldLayoutFromHostInvalid { 4183 barrier_index: usize, 4184 old_layout: ImageLayout, 4185 }, 4186 4187 /// An image memory barrier contains a queue family ownership transfer, but a render pass 4188 /// instance is active. 4189 ImageMemoryBarrierOwnershipTransferForbiddenInsideRenderPass { barrier_index: usize }, 4190 4191 /// An image memory barrier contains a queue family ownership transfer, but either the 4192 /// `src_stages` or `dst_stages` contain [`HOST`]. 4193 /// 4194 /// [`HOST`]: crate::sync::PipelineStages::HOST 4195 ImageMemoryBarrierOwnershipTransferHostForbidden { barrier_index: usize }, 4196 4197 /// The provided `src_index` or `dst_index` in the queue family ownership transfer of an 4198 /// image memory barrier is not less than the number of queue families in the physical device. 4199 ImageMemoryBarrierOwnershipTransferIndexOutOfRange { 4200 barrier_index: usize, 4201 provided_queue_family_index: u32, 4202 queue_family_count: u32, 4203 }, 4204 4205 /// The provided `queue_family_ownership_transfer` value of an image memory barrier does not 4206 /// match the sharing mode of `image`. 4207 ImageMemoryBarrierOwnershipTransferSharingMismatch { barrier_index: usize }, 4208 4209 /// One or more pipeline stages of an image memory barrier are not supported by the queue 4210 /// family of the command buffer. 4211 ImageMemoryBarrierStageNotSupported { barrier_index: usize }, 4212 4213 /// One or more accesses of a memory barrier are not supported by the corresponding 4214 /// pipeline stages. 4215 MemoryBarrierAccessNotSupportedByStages { barrier_index: usize }, 4216 4217 /// A render pass instance is active, but the render pass does not have a subpass 4218 /// self-dependency for the current subpass that is a superset of the barriers. 4219 MemoryBarrierNoMatchingSubpassSelfDependency, 4220 4221 /// One or more pipeline stages of a memory barrier are not supported by the queue 4222 /// family of the command buffer. 4223 MemoryBarrierStageNotSupported { barrier_index: usize }, 4224 4225 /// The queue family doesn't allow this operation. 4226 NotSupportedByQueueFamily, 4227 } 4228 4229 impl Error for SynchronizationError {} 4230 4231 impl Display for SynchronizationError { fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>4232 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { 4233 match self { 4234 Self::RequirementNotMet { 4235 required_for, 4236 requires_one_of, 4237 } => write!( 4238 f, 4239 "a requirement was not met for: {}; requires one of: {}", 4240 required_for, requires_one_of, 4241 ), 4242 4243 Self::BufferMemoryBarrierAccessNotSupportedByStages { barrier_index } => write!( 4244 f, 4245 "one or more accesses of buffer memory barrier {} are not supported by the \ 4246 corresponding pipeline stages", 4247 barrier_index, 4248 ), 4249 Self::BufferMemoryBarrierForbiddenInsideRenderPass => write!( 4250 f, 4251 "buffer memory barriers are forbidden inside a render pass instance", 4252 ), 4253 Self::BufferMemoryBarrierOutOfRange { 4254 barrier_index, 4255 range_end, 4256 buffer_size, 4257 } => write!( 4258 f, 4259 "the end of `range` ({}) of buffer memory barrier {} is greater than the size of \ 4260 `buffer` ({})", 4261 range_end, barrier_index, buffer_size, 4262 ), 4263 Self::BufferMemoryBarrierOwnershipTransferHostNotAllowed { barrier_index } => write!( 4264 f, 4265 "buffer memory barrier {} contains a queue family ownership transfer, but either \ 4266 the `src_stages` or `dst_stages` contain `HOST`", 4267 barrier_index, 4268 ), 4269 Self::BufferMemoryBarrierOwnershipTransferIndexOutOfRange { 4270 barrier_index, 4271 provided_queue_family_index, 4272 queue_family_count, 4273 } => write!( 4274 f, 4275 "the provided `src_index` or `dst_index` ({}) in the queue family ownership \ 4276 transfer of buffer memory barrier {} is not less than the number of queue \ 4277 families in the physical device ({})", 4278 provided_queue_family_index, barrier_index, queue_family_count, 4279 ), 4280 Self::BufferMemoryBarrierOwnershipTransferSharingMismatch { barrier_index } => write!( 4281 f, 4282 "the provided `queue_family_ownership_transfer` value of buffer memory barrier {} \ 4283 does not match the sharing mode of `buffer`", 4284 barrier_index, 4285 ), 4286 Self::BufferMemoryBarrierStageNotSupported { barrier_index } => write!( 4287 f, 4288 "one or more pipeline stages of buffer memory barrier {} are not supported by the \ 4289 queue family of the command buffer", 4290 barrier_index, 4291 ), 4292 Self::DependencyFlagsViewLocalNotAllowed => write!( 4293 f, 4294 "a render pass instance is not active, and the `VIEW_LOCAL` dependency flag was \ 4295 provided", 4296 ), 4297 Self::ForbiddenInsideRenderPass => { 4298 write!(f, "operation forbidden inside a render pass") 4299 } 4300 Self::ForbiddenWithBeginRendering => write!( 4301 f, 4302 "operation forbidden inside a render pass instance that was begun with \ 4303 `begin_rendering`", 4304 ), 4305 Self::ImageMemoryBarrierAccessNotSupportedByStages { barrier_index } => write!( 4306 f, 4307 "one or more accesses of image memory barrier {} are not supported by the \ 4308 corresponding pipeline stages", 4309 barrier_index, 4310 ), 4311 Self::ImageMemoryBarrierArrayLayersOutOfRange { 4312 barrier_index, 4313 array_layers_range_end, 4314 image_array_layers, 4315 } => write!( 4316 f, 4317 "the end of the range of array layers ({}) of the subresource range of image \ 4318 memory barrier {} is greater than the number of array layers in the image ({})", 4319 array_layers_range_end, barrier_index, image_array_layers, 4320 ), 4321 Self::ImageMemoryBarrierAspectsNotAllowed { 4322 barrier_index, 4323 aspects, 4324 } => write!( 4325 f, 4326 "the aspects of the subresource range of image memory barrier {} contain aspects \ 4327 that are not present in the image, or that are not allowed ({:?})", 4328 barrier_index, aspects, 4329 ), 4330 Self::ImageMemoryBarrierImageMissingUsageForLayout { 4331 barrier_index, 4332 layout, 4333 requires_one_of_usage, 4334 } => write!( 4335 f, 4336 "for the `old_layout` or `new_layout` ({:?}) of image memory barrier {}, `image` \ 4337 does not have a usage that is required ({}{:?})", 4338 layout, 4339 barrier_index, 4340 if requires_one_of_usage.count() > 1 { 4341 "one of " 4342 } else { 4343 "" 4344 }, 4345 requires_one_of_usage, 4346 ), 4347 Self::ImageMemoryBarrierLayoutTransitionForbiddenInsideRenderPass { barrier_index } => { 4348 write!( 4349 f, 4350 "image memory barrier {} contains an image layout transition, but a render \ 4351 pass instance is active", 4352 barrier_index, 4353 ) 4354 } 4355 Self::ImageMemoryBarrierMipLevelsOutOfRange { 4356 barrier_index, 4357 mip_levels_range_end, 4358 image_mip_levels, 4359 } => write!( 4360 f, 4361 "the end of the range of mip levels ({}) of the subresource range of image \ 4362 memory barrier {} is greater than the number of mip levels in the image ({})", 4363 mip_levels_range_end, barrier_index, image_mip_levels, 4364 ), 4365 Self::ImageMemoryBarrierNewLayoutInvalid { barrier_index } => write!( 4366 f, 4367 "the `new_layout` of image memory barrier {} is `Undefined` or `Preinitialized`", 4368 barrier_index, 4369 ), 4370 Self::ImageMemoryBarrierNotColorDepthStencilAttachment { barrier_index } => write!( 4371 f, 4372 "a render pass instance is active, and the image of image memory barrier {} is \ 4373 not a color or depth/stencil attachment of the current subpass", 4374 barrier_index, 4375 ), 4376 Self::ImageMemoryBarrierNotInputAttachment { barrier_index } => write!( 4377 f, 4378 "a render pass instance is active, and the image of image memory barrier {} is \ 4379 not an input attachment of the current subpass", 4380 barrier_index, 4381 ), 4382 Self::ImageMemoryBarrierOldLayoutFromHostInvalid { 4383 barrier_index, 4384 old_layout, 4385 } => write!( 4386 f, 4387 "the `src_stages` of image memory barrier {} contains `HOST`, but `old_layout` 4388 ({:?}) is not `Preinitialized`, `Undefined` or `General`", 4389 barrier_index, old_layout, 4390 ), 4391 Self::ImageMemoryBarrierOwnershipTransferForbiddenInsideRenderPass { 4392 barrier_index, 4393 } => write!( 4394 f, 4395 "image memory barrier {} contains a queue family ownership transfer, but a render \ 4396 pass instance is active", 4397 barrier_index, 4398 ), 4399 Self::ImageMemoryBarrierOwnershipTransferHostForbidden { barrier_index } => write!( 4400 f, 4401 "image memory barrier {} contains a queue family ownership transfer, but either \ 4402 the `src_stages` or `dst_stages` contain `HOST`", 4403 barrier_index, 4404 ), 4405 Self::ImageMemoryBarrierOwnershipTransferIndexOutOfRange { 4406 barrier_index, 4407 provided_queue_family_index, 4408 queue_family_count, 4409 } => write!( 4410 f, 4411 "the provided `src_index` or `dst_index` ({}) in the queue family ownership \ 4412 transfer of image memory barrier {} is not less than the number of queue 4413 families in the physical device ({})", 4414 provided_queue_family_index, barrier_index, queue_family_count, 4415 ), 4416 Self::ImageMemoryBarrierOwnershipTransferSharingMismatch { barrier_index } => write!( 4417 f, 4418 "the provided `queue_family_ownership_transfer` value of image memory barrier {} \ 4419 does not match the sharing mode of `image`", 4420 barrier_index, 4421 ), 4422 Self::ImageMemoryBarrierStageNotSupported { barrier_index } => write!( 4423 f, 4424 "one or more pipeline stages of image memory barrier {} are not supported by the \ 4425 queue family of the command buffer", 4426 barrier_index, 4427 ), 4428 Self::MemoryBarrierAccessNotSupportedByStages { barrier_index } => write!( 4429 f, 4430 "one or more accesses of memory barrier {} are not supported by the \ 4431 corresponding pipeline stages", 4432 barrier_index, 4433 ), 4434 Self::MemoryBarrierNoMatchingSubpassSelfDependency => write!( 4435 f, 4436 "a render pass instance is active, but the render pass does not have a subpass \ 4437 self-dependency for the current subpass that is a superset of the barriers", 4438 ), 4439 Self::MemoryBarrierStageNotSupported { barrier_index } => write!( 4440 f, 4441 "one or more pipeline stages of memory barrier {} are not supported by the \ 4442 queue family of the command buffer", 4443 barrier_index, 4444 ), 4445 Self::NotSupportedByQueueFamily => { 4446 write!(f, "the queue family doesn't allow this operation") 4447 } 4448 } 4449 } 4450 } 4451 4452 impl From<RequirementNotMet> for SynchronizationError { from(err: RequirementNotMet) -> Self4453 fn from(err: RequirementNotMet) -> Self { 4454 Self::RequirementNotMet { 4455 required_for: err.required_for, 4456 requires_one_of: err.requires_one_of, 4457 } 4458 } 4459 } 4460