• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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