vk_sync_fork/
lib.rs

1//! In an effort to make Vulkan synchronization more accessible, this library
2//! provides a simplification of core synchronization mechanisms such as
3//! pipeline barriers and events.
4//!
5//! Rather than the complex maze of enums and bit flags in Vulkan - many
6//! combinations of which are invalid or nonsensical - this library collapses
7//! this to a shorter list of distinct usage types, and a couple of options
8//! for handling image layouts.
9//!
10//! Additionally, these usage types provide an easier mapping to other graphics
11//! APIs like DirectX 12.
12//!
13//! Use of other synchronization mechanisms such as semaphores, fences and render
14//! passes are not addressed in this library at present.
15
16use ash::vk;
17
18pub mod cmd;
19
20/// Defines all potential resource usages
21#[derive(Debug, Copy, Clone, PartialEq, Default)]
22pub enum AccessType {
23    /// No access. Useful primarily for initialization
24    #[default]
25    Nothing,
26
27    /// Command buffer read operation as defined by `NVX_device_generated_commands`
28    CommandBufferReadNVX,
29
30    /// Read as an indirect buffer for drawing or dispatch
31    IndirectBuffer,
32
33    /// Read as an index buffer for drawing
34    IndexBuffer,
35
36    /// Read as a vertex buffer for drawing
37    VertexBuffer,
38
39    /// Read as a uniform buffer in a vertex shader
40    VertexShaderReadUniformBuffer,
41
42    /// Read as a sampled image/uniform texel buffer in a vertex shader
43    VertexShaderReadSampledImageOrUniformTexelBuffer,
44
45    /// Read as any other resource in a vertex shader
46    VertexShaderReadOther,
47
48    /// Read as a uniform buffer in a mesh shader
49    MeshShaderReadUniformBuffer,
50
51    /// Read as a sampled image/uniform texel buffer in a mesh shader
52    MeshShaderReadSampledImageOrUniformTexelBuffer,
53
54    /// Read as any other resource in a mesh shader
55    MeshShaderReadOther,
56
57    /// Read as a uniform buffer in a task shader
58    TaskShaderReadUniformBuffer,
59
60    /// Read as a sampled image/uniform texel buffer in a task shader
61    TaskShaderReadSampledImageOrUniformTexelBuffer,
62
63    /// Read as any other resource in a task shader
64    TaskShaderReadOther,
65
66    /// Read as a uniform buffer in a tessellation control shader
67    TessellationControlShaderReadUniformBuffer,
68
69    /// Read as a sampled image/uniform texel buffer in a tessellation control shader
70    TessellationControlShaderReadSampledImageOrUniformTexelBuffer,
71
72    /// Read as any other resource in a tessellation control shader
73    TessellationControlShaderReadOther,
74
75    /// Read as a uniform buffer in a tessellation evaluation shader
76    TessellationEvaluationShaderReadUniformBuffer,
77
78    /// Read as a sampled image/uniform texel buffer in a tessellation evaluation shader
79    TessellationEvaluationShaderReadSampledImageOrUniformTexelBuffer,
80
81    /// Read as any other resource in a tessellation evaluation shader
82    TessellationEvaluationShaderReadOther,
83
84    /// Read as a uniform buffer in a geometry shader
85    GeometryShaderReadUniformBuffer,
86
87    /// Read as a sampled image/uniform texel buffer in a geometry shader
88    GeometryShaderReadSampledImageOrUniformTexelBuffer,
89
90    /// Read as any other resource in a geometry shader
91    GeometryShaderReadOther,
92
93    /// Read as a uniform buffer in a fragment shader
94    FragmentShaderReadUniformBuffer,
95
96    /// Read as a sampled image/uniform texel buffer in a fragment shader
97    FragmentShaderReadSampledImageOrUniformTexelBuffer,
98
99    /// Read as an input attachment with a color format in a fragment shader
100    FragmentShaderReadColorInputAttachment,
101
102    /// Read as an input attachment with a depth/stencil format in a fragment shader
103    FragmentShaderReadDepthStencilInputAttachment,
104
105    /// Read as any other resource in a fragment shader
106    FragmentShaderReadOther,
107
108    /// Read by blending/logic operations or subpass load operations
109    ColorAttachmentRead,
110
111    /// Read by depth/stencil tests or subpass load operations
112    DepthStencilAttachmentRead,
113
114    /// Read or written as a depth/stencil attachment during rendering, or via a subpass store op
115    DepthStencilAttachmentReadWrite,
116
117    /// Read as a uniform buffer in a compute shader
118    ComputeShaderReadUniformBuffer,
119
120    /// Read as a sampled image/uniform texel buffer in a compute shader
121    ComputeShaderReadSampledImageOrUniformTexelBuffer,
122
123    /// Read as any other resource in a compute shader
124    ComputeShaderReadOther,
125
126    /// Read or written as any resource in a compute shader
127    ComputeShaderReadWrite,
128
129    /// Read as a uniform buffer in any shader
130    AnyShaderReadUniformBuffer,
131
132    /// Read as a uniform buffer in any shader, or a vertex buffer
133    AnyShaderReadUniformBufferOrVertexBuffer,
134
135    /// Read as a sampled image in any shader
136    AnyShaderReadSampledImageOrUniformTexelBuffer,
137
138    /// Read as any other resource (excluding attachments) in any shader
139    AnyShaderReadOther,
140
141    /// Read as the source of a transfer operation
142    TransferRead,
143
144    /// Read on the host
145    HostRead,
146
147    /// Read by the presentation engine (i.e. `vkQueuePresentKHR`)
148    Present,
149
150    /// Command buffer write operation as defined by `NVX_device_generated_commands`
151    CommandBufferWriteNVX,
152
153    /// Written as any resource in a vertex shader
154    VertexShaderWrite,
155
156    /// Written as any resource in a mesh shader
157    MeshShaderWrite,
158
159    /// Written as any resource in a task shader
160    TaskShaderWrite,
161
162    /// Written as any resource in a tessellation control shader
163    TessellationControlShaderWrite,
164
165    /// Written as any resource in a tessellation evaluation shader
166    TessellationEvaluationShaderWrite,
167
168    /// Written as any resource in a geometry shader
169    GeometryShaderWrite,
170
171    /// Written as any resource in a fragment shader
172    FragmentShaderWrite,
173
174    /// Written as a color attachment during rendering, or via a subpass store op
175    ColorAttachmentWrite,
176
177    /// Written as a depth/stencil attachment during rendering, or via a subpass store op
178    DepthStencilAttachmentWrite,
179
180    /// Written as a depth aspect of a depth/stencil attachment during rendering, whilst the
181    /// stencil aspect is read-only. Requires `VK_KHR_maintenance2` to be enabled.
182    DepthAttachmentWriteStencilReadOnly,
183
184    /// Written as a stencil aspect of a depth/stencil attachment during rendering, whilst the
185    /// depth aspect is read-only. Requires `VK_KHR_maintenance2` to be enabled.
186    StencilAttachmentWriteDepthReadOnly,
187
188    /// Written as any resource in a compute shader
189    ComputeShaderWrite,
190
191    /// Written as any resource in any shader
192    AnyShaderWrite,
193
194    /// Written as the destination of a transfer operation
195    TransferWrite,
196
197    /// Written on the host
198    HostWrite,
199
200    /// Read or written as a color attachment during rendering
201    ColorAttachmentReadWrite,
202
203    /// Covers any access - useful for debug, generally avoid for performance reasons
204    General,
205
206    /// Read as a sampled image/uniform texel buffer in a ray tracing shader
207    RayTracingShaderReadSampledImageOrUniformTexelBuffer,
208
209    /// Read as an input attachment with a color format in a ray tracing shader
210    RayTracingShaderReadColorInputAttachment,
211
212    /// Read as an input attachment with a depth/stencil format in a ray tracing shader
213    RayTracingShaderReadDepthStencilInputAttachment,
214
215    /// Read as an acceleration structure in a ray tracing shader
216    RayTracingShaderReadAccelerationStructure,
217
218    /// Read as any other resource in a ray tracing shader
219    RayTracingShaderReadOther,
220
221    /// Written as an acceleration structure during acceleration structure building
222    AccelerationStructureBuildWrite,
223
224    /// Read as an acceleration structure during acceleration structure building (e.g. a BLAS when building a TLAS)
225    AccelerationStructureBuildRead,
226
227    // Written as a buffer during acceleration structure building (e.g. a staging buffer)
228    AccelerationStructureBufferWrite,
229}
230
231/// Defines a handful of layout options for images.
232/// Rather than a list of all possible image layouts, this reduced list is
233/// correlated with the access types to map to the correct Vulkan layouts.
234/// `Optimal` is usually preferred.
235#[derive(Debug, Copy, Clone, PartialEq, Default)]
236pub enum ImageLayout {
237    /// Choose the most optimal layout for each usage. Performs layout transitions as appropriate for the access.
238    #[default]
239    Optimal,
240
241    /// Layout accessible by all Vulkan access types on a device - no layout transitions except for presentation
242    General,
243
244    /// Similar to `General`, but also allows presentation engines to access it - no layout transitions.
245    /// Requires `VK_KHR_shared_presentable_image` to be enabled, and this can only be used for shared presentable
246    /// images (i.e. single-buffered swap chains).
247    GeneralAndPresentation,
248}
249
250/// Global barriers define a set of accesses on multiple resources at once.
251/// If a buffer or image doesn't require a queue ownership transfer, or an image
252/// doesn't require a layout transition (e.g. you're using one of the
253/// `ImageLayout::General*` layouts) then a global barrier should be preferred.
254///
255/// Simply define the previous and next access types of resources affected.
256#[derive(Debug, Default, Clone)]
257pub struct GlobalBarrier<'a> {
258    pub previous_accesses: &'a [AccessType],
259    pub next_accesses: &'a [AccessType],
260}
261
262/// Buffer barriers should only be used when a queue family ownership transfer
263/// is required - prefer global barriers at all other times.
264///
265/// Access types are defined in the same way as for a global memory barrier, but
266/// they only affect the buffer range identified by `buffer`, `offset` and `size`,
267/// rather than all resources.
268///
269/// `src_queue_family_index` and `dst_queue_family_index` will be passed unmodified
270/// into a buffer memory barrier.
271///
272/// A buffer barrier defining a queue ownership transfer needs to be executed
273/// twice - once by a queue in the source queue family, and then once again by a
274/// queue in the destination queue family, with a semaphore guaranteeing
275/// execution order between them.
276#[derive(Debug, Default, Clone)]
277pub struct BufferBarrier<'a> {
278    pub previous_accesses: &'a [AccessType],
279    pub next_accesses: &'a [AccessType],
280    pub src_queue_family_index: u32,
281    pub dst_queue_family_index: u32,
282    pub buffer: vk::Buffer,
283    pub offset: usize,
284    pub size: usize,
285}
286
287/// Image barriers should only be used when a queue family ownership transfer
288/// or an image layout transition is required - prefer global barriers at all
289/// other times.
290///
291/// In general it is better to use image barriers with `ImageLayout::Optimal`
292/// than it is to use global barriers with images using either of the
293/// `ImageLayout::General*` layouts.
294///
295/// Access types are defined in the same way as for a global memory barrier, but
296/// they only affect the image subresource range identified by `image` and
297/// `range`, rather than all resources.
298///
299/// `src_queue_family_index`, `dst_queue_family_index`, `image`, and `range` will
300/// be passed unmodified into an image memory barrier.
301///
302/// An image barrier defining a queue ownership transfer needs to be executed
303/// twice - once by a queue in the source queue family, and then once again by a
304/// queue in the destination queue family, with a semaphore guaranteeing
305/// execution order between them.
306///
307/// If `discard_contents` is set to true, the contents of the image become
308/// undefined after the barrier is executed, which can result in a performance
309/// boost over attempting to preserve the contents. This is particularly useful
310/// for transient images where the contents are going to be immediately overwritten.
311/// A good example of when to use this is when an application re-uses a presented
312/// image after acquiring the next swap chain image.
313#[derive(Debug, Default, Clone)]
314pub struct ImageBarrier<'a> {
315    pub previous_accesses: &'a [AccessType],
316    pub next_accesses: &'a [AccessType],
317    pub previous_layout: ImageLayout,
318    pub next_layout: ImageLayout,
319    pub discard_contents: bool,
320    pub src_queue_family_index: u32,
321    pub dst_queue_family_index: u32,
322    pub image: vk::Image,
323    pub range: vk::ImageSubresourceRange,
324}
325
326/// Mapping function that translates a global barrier into a set of source and
327/// destination pipeline stages, and a memory barrier, that can be used with
328/// Vulkan synchronization methods.
329pub fn get_memory_barrier<'a>(
330    barrier: &GlobalBarrier<'a>,
331) -> (
332    vk::PipelineStageFlags,
333    vk::PipelineStageFlags,
334    vk::MemoryBarrier<'a>,
335) {
336    let mut src_stages = vk::PipelineStageFlags::empty();
337    let mut dst_stages = vk::PipelineStageFlags::empty();
338
339    let mut memory_barrier = vk::MemoryBarrier::default();
340
341    for previous_access in barrier.previous_accesses {
342        let previous_info = get_access_info(*previous_access);
343
344        src_stages |= previous_info.stage_mask;
345
346        // Add appropriate availability operations - for writes only.
347        if is_write_access(*previous_access) {
348            memory_barrier.src_access_mask |= previous_info.access_mask;
349        }
350    }
351
352    for next_access in barrier.next_accesses {
353        let next_info = get_access_info(*next_access);
354
355        dst_stages |= next_info.stage_mask;
356
357        // Add visibility operations as necessary.
358        // If the src access mask, this is a WAR hazard (or for some reason a "RAR"),
359        // so the dst access mask can be safely zeroed as these don't need visibility.
360        if memory_barrier.src_access_mask != vk::AccessFlags::empty() {
361            memory_barrier.dst_access_mask |= next_info.access_mask;
362        }
363    }
364
365    // Ensure that the stage masks are valid if no stages were determined
366    if src_stages == vk::PipelineStageFlags::empty() {
367        src_stages = vk::PipelineStageFlags::TOP_OF_PIPE;
368    }
369
370    if dst_stages == vk::PipelineStageFlags::empty() {
371        dst_stages = vk::PipelineStageFlags::BOTTOM_OF_PIPE;
372    }
373
374    (src_stages, dst_stages, memory_barrier)
375}
376
377/// Mapping function that translates a buffer barrier into a set of source and
378/// destination pipeline stages, and a buffer memory barrier, that can be used
379/// with Vulkan synchronization methods.
380pub fn get_buffer_memory_barrier<'a>(
381    barrier: &BufferBarrier<'a>,
382) -> (
383    vk::PipelineStageFlags,
384    vk::PipelineStageFlags,
385    vk::BufferMemoryBarrier<'a>,
386) {
387    let mut src_stages = vk::PipelineStageFlags::empty();
388    let mut dst_stages = vk::PipelineStageFlags::empty();
389
390    let mut buffer_barrier = vk::BufferMemoryBarrier {
391        src_queue_family_index: barrier.src_queue_family_index,
392        dst_queue_family_index: barrier.dst_queue_family_index,
393        buffer: barrier.buffer,
394        offset: barrier.offset as u64,
395        size: barrier.size as u64,
396        ..Default::default()
397    };
398
399    for previous_access in barrier.previous_accesses {
400        let previous_info = get_access_info(*previous_access);
401
402        src_stages |= previous_info.stage_mask;
403
404        // Add appropriate availability operations - for writes only.
405        if is_write_access(*previous_access) {
406            buffer_barrier.src_access_mask |= previous_info.access_mask;
407        }
408    }
409
410    for next_access in barrier.next_accesses {
411        let next_info = get_access_info(*next_access);
412
413        dst_stages |= next_info.stage_mask;
414
415        // Add visibility operations as necessary.
416        // If the src access mask, this is a WAR hazard (or for some reason a "RAR"),
417        // so the dst access mask can be safely zeroed as these don't need visibility.
418        if buffer_barrier.src_access_mask != vk::AccessFlags::empty() {
419            buffer_barrier.dst_access_mask |= next_info.access_mask;
420        }
421    }
422
423    // Ensure that the stage masks are valid if no stages were determined
424    if src_stages == vk::PipelineStageFlags::empty() {
425        src_stages = vk::PipelineStageFlags::TOP_OF_PIPE;
426    }
427
428    if dst_stages == vk::PipelineStageFlags::empty() {
429        dst_stages = vk::PipelineStageFlags::BOTTOM_OF_PIPE;
430    }
431
432    (src_stages, dst_stages, buffer_barrier)
433}
434
435/// Mapping function that translates an image barrier into a set of source and
436/// destination pipeline stages, and an image memory barrier, that can be used
437/// with Vulkan synchronization methods.
438pub fn get_image_memory_barrier<'a>(
439    barrier: &ImageBarrier<'a>,
440) -> (
441    vk::PipelineStageFlags,
442    vk::PipelineStageFlags,
443    vk::ImageMemoryBarrier<'a>,
444) {
445    let mut src_stages = vk::PipelineStageFlags::empty();
446    let mut dst_stages = vk::PipelineStageFlags::empty();
447
448    let mut image_barrier = vk::ImageMemoryBarrier {
449        src_queue_family_index: barrier.src_queue_family_index,
450        dst_queue_family_index: barrier.dst_queue_family_index,
451        image: barrier.image,
452        subresource_range: barrier.range,
453        ..Default::default()
454    };
455
456    for previous_access in barrier.previous_accesses {
457        let previous_info = get_access_info(*previous_access);
458
459        src_stages |= previous_info.stage_mask;
460
461        // Add appropriate availability operations - for writes only.
462        if is_write_access(*previous_access) {
463            image_barrier.src_access_mask |= previous_info.access_mask;
464        }
465
466        if barrier.discard_contents {
467            image_barrier.old_layout = vk::ImageLayout::UNDEFINED;
468        } else {
469            let layout = match barrier.previous_layout {
470                ImageLayout::General => {
471                    if *previous_access == AccessType::Present {
472                        vk::ImageLayout::PRESENT_SRC_KHR
473                    } else {
474                        vk::ImageLayout::GENERAL
475                    }
476                }
477                ImageLayout::Optimal => previous_info.image_layout,
478                ImageLayout::GeneralAndPresentation => {
479                    unimplemented!()
480                    // TODO: layout = vk::ImageLayout::VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR
481                }
482            };
483
484            image_barrier.old_layout = layout;
485        }
486    }
487
488    for next_access in barrier.next_accesses {
489        let next_info = get_access_info(*next_access);
490
491        dst_stages |= next_info.stage_mask;
492
493        // Add appropriate availability operations - in all cases beccause otherwise
494        // we get WAW and RAWs.
495        image_barrier.dst_access_mask |= next_info.access_mask;
496
497        let layout = match barrier.next_layout {
498            ImageLayout::General => {
499                if *next_access == AccessType::Present {
500                    vk::ImageLayout::PRESENT_SRC_KHR
501                } else {
502                    vk::ImageLayout::GENERAL
503                }
504            }
505            ImageLayout::Optimal => next_info.image_layout,
506            ImageLayout::GeneralAndPresentation => {
507                unimplemented!()
508                // TODO: layout = vk::ImageLayout::VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR
509            }
510        };
511
512        image_barrier.new_layout = layout;
513    }
514
515    // Ensure that the stage masks are valid if no stages were determined
516    if src_stages == vk::PipelineStageFlags::empty() {
517        src_stages = vk::PipelineStageFlags::TOP_OF_PIPE;
518    }
519
520    if dst_stages == vk::PipelineStageFlags::empty() {
521        dst_stages = vk::PipelineStageFlags::BOTTOM_OF_PIPE;
522    }
523
524    (src_stages, dst_stages, image_barrier)
525}
526
527pub(crate) struct AccessInfo {
528    pub(crate) stage_mask: vk::PipelineStageFlags,
529    pub(crate) access_mask: vk::AccessFlags,
530    pub(crate) image_layout: vk::ImageLayout,
531}
532
533pub(crate) fn get_access_info(access_type: AccessType) -> AccessInfo {
534    match access_type {
535        AccessType::Nothing => AccessInfo {
536            stage_mask: vk::PipelineStageFlags::empty(),
537            access_mask: vk::AccessFlags::empty(),
538            image_layout: vk::ImageLayout::UNDEFINED,
539        },
540        AccessType::CommandBufferReadNVX => AccessInfo {
541            stage_mask: vk::PipelineStageFlags::COMMAND_PREPROCESS_NV,
542            access_mask: vk::AccessFlags::COMMAND_PREPROCESS_READ_NV,
543            image_layout: vk::ImageLayout::UNDEFINED,
544        },
545        AccessType::IndirectBuffer => AccessInfo {
546            stage_mask: vk::PipelineStageFlags::DRAW_INDIRECT,
547            access_mask: vk::AccessFlags::INDIRECT_COMMAND_READ,
548            image_layout: vk::ImageLayout::UNDEFINED,
549        },
550        AccessType::IndexBuffer => AccessInfo {
551            stage_mask: vk::PipelineStageFlags::VERTEX_INPUT,
552            access_mask: vk::AccessFlags::INDEX_READ,
553            image_layout: vk::ImageLayout::UNDEFINED,
554        },
555        AccessType::VertexBuffer => AccessInfo {
556            stage_mask: vk::PipelineStageFlags::VERTEX_INPUT,
557            access_mask: vk::AccessFlags::VERTEX_ATTRIBUTE_READ,
558            image_layout: vk::ImageLayout::UNDEFINED,
559        },
560        AccessType::VertexShaderReadUniformBuffer => AccessInfo {
561            stage_mask: vk::PipelineStageFlags::VERTEX_SHADER,
562            access_mask: vk::AccessFlags::SHADER_READ,
563            image_layout: vk::ImageLayout::UNDEFINED,
564        },
565        AccessType::VertexShaderReadSampledImageOrUniformTexelBuffer => AccessInfo {
566            stage_mask: vk::PipelineStageFlags::VERTEX_SHADER,
567            access_mask: vk::AccessFlags::SHADER_READ,
568            image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
569        },
570        AccessType::VertexShaderReadOther => AccessInfo {
571            stage_mask: vk::PipelineStageFlags::VERTEX_SHADER,
572            access_mask: vk::AccessFlags::SHADER_READ,
573            image_layout: vk::ImageLayout::GENERAL,
574        },
575        AccessType::MeshShaderReadUniformBuffer => AccessInfo {
576            stage_mask: vk::PipelineStageFlags::MESH_SHADER_EXT,
577            access_mask: vk::AccessFlags::SHADER_READ,
578            image_layout: vk::ImageLayout::UNDEFINED,
579        },
580        AccessType::MeshShaderReadSampledImageOrUniformTexelBuffer => AccessInfo {
581            stage_mask: vk::PipelineStageFlags::MESH_SHADER_EXT,
582            access_mask: vk::AccessFlags::SHADER_READ,
583            image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
584        },
585        AccessType::MeshShaderReadOther => AccessInfo {
586            stage_mask: vk::PipelineStageFlags::MESH_SHADER_EXT,
587            access_mask: vk::AccessFlags::SHADER_READ,
588            image_layout: vk::ImageLayout::GENERAL,
589        },
590        AccessType::TaskShaderReadUniformBuffer => AccessInfo {
591            stage_mask: vk::PipelineStageFlags::TASK_SHADER_EXT,
592            access_mask: vk::AccessFlags::SHADER_READ,
593            image_layout: vk::ImageLayout::UNDEFINED,
594        },
595        AccessType::TaskShaderReadSampledImageOrUniformTexelBuffer => AccessInfo {
596            stage_mask: vk::PipelineStageFlags::TASK_SHADER_EXT,
597            access_mask: vk::AccessFlags::SHADER_READ,
598            image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
599        },
600        AccessType::TaskShaderReadOther => AccessInfo {
601            stage_mask: vk::PipelineStageFlags::TASK_SHADER_EXT,
602            access_mask: vk::AccessFlags::SHADER_READ,
603            image_layout: vk::ImageLayout::GENERAL,
604        },
605        AccessType::TessellationControlShaderReadUniformBuffer => AccessInfo {
606            stage_mask: vk::PipelineStageFlags::TESSELLATION_CONTROL_SHADER,
607            access_mask: vk::AccessFlags::UNIFORM_READ,
608            image_layout: vk::ImageLayout::UNDEFINED,
609        },
610        AccessType::TessellationControlShaderReadSampledImageOrUniformTexelBuffer => AccessInfo {
611            stage_mask: vk::PipelineStageFlags::TESSELLATION_CONTROL_SHADER,
612            access_mask: vk::AccessFlags::SHADER_READ,
613            image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
614        },
615        AccessType::TessellationControlShaderReadOther => AccessInfo {
616            stage_mask: vk::PipelineStageFlags::TESSELLATION_CONTROL_SHADER,
617            access_mask: vk::AccessFlags::SHADER_READ,
618            image_layout: vk::ImageLayout::GENERAL,
619        },
620        AccessType::TessellationEvaluationShaderReadUniformBuffer => AccessInfo {
621            stage_mask: vk::PipelineStageFlags::TESSELLATION_EVALUATION_SHADER,
622            access_mask: vk::AccessFlags::UNIFORM_READ,
623            image_layout: vk::ImageLayout::UNDEFINED,
624        },
625        AccessType::TessellationEvaluationShaderReadSampledImageOrUniformTexelBuffer => {
626            AccessInfo {
627                stage_mask: vk::PipelineStageFlags::TESSELLATION_EVALUATION_SHADER,
628                access_mask: vk::AccessFlags::SHADER_READ,
629                image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
630            }
631        }
632        AccessType::TessellationEvaluationShaderReadOther => AccessInfo {
633            stage_mask: vk::PipelineStageFlags::TESSELLATION_EVALUATION_SHADER,
634            access_mask: vk::AccessFlags::SHADER_READ,
635            image_layout: vk::ImageLayout::GENERAL,
636        },
637        AccessType::GeometryShaderReadUniformBuffer => AccessInfo {
638            stage_mask: vk::PipelineStageFlags::GEOMETRY_SHADER,
639            access_mask: vk::AccessFlags::UNIFORM_READ,
640            image_layout: vk::ImageLayout::UNDEFINED,
641        },
642        AccessType::GeometryShaderReadSampledImageOrUniformTexelBuffer => AccessInfo {
643            stage_mask: vk::PipelineStageFlags::GEOMETRY_SHADER,
644            access_mask: vk::AccessFlags::SHADER_READ,
645            image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
646        },
647        AccessType::GeometryShaderReadOther => AccessInfo {
648            stage_mask: vk::PipelineStageFlags::GEOMETRY_SHADER,
649            access_mask: vk::AccessFlags::SHADER_READ,
650            image_layout: vk::ImageLayout::GENERAL,
651        },
652        AccessType::FragmentShaderReadUniformBuffer => AccessInfo {
653            stage_mask: vk::PipelineStageFlags::FRAGMENT_SHADER,
654            access_mask: vk::AccessFlags::UNIFORM_READ,
655            image_layout: vk::ImageLayout::UNDEFINED,
656        },
657        AccessType::FragmentShaderReadSampledImageOrUniformTexelBuffer => AccessInfo {
658            stage_mask: vk::PipelineStageFlags::FRAGMENT_SHADER,
659            access_mask: vk::AccessFlags::SHADER_READ,
660            image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
661        },
662        AccessType::FragmentShaderReadColorInputAttachment => AccessInfo {
663            stage_mask: vk::PipelineStageFlags::FRAGMENT_SHADER,
664            access_mask: vk::AccessFlags::INPUT_ATTACHMENT_READ,
665            image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
666        },
667        AccessType::FragmentShaderReadDepthStencilInputAttachment => AccessInfo {
668            stage_mask: vk::PipelineStageFlags::FRAGMENT_SHADER,
669            access_mask: vk::AccessFlags::INPUT_ATTACHMENT_READ,
670            image_layout: vk::ImageLayout::DEPTH_STENCIL_READ_ONLY_OPTIMAL,
671        },
672        AccessType::FragmentShaderReadOther => AccessInfo {
673            stage_mask: vk::PipelineStageFlags::FRAGMENT_SHADER,
674            access_mask: vk::AccessFlags::SHADER_READ,
675            image_layout: vk::ImageLayout::GENERAL,
676        },
677        AccessType::ColorAttachmentRead => AccessInfo {
678            stage_mask: vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT,
679            access_mask: vk::AccessFlags::COLOR_ATTACHMENT_READ,
680            image_layout: vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,
681        },
682        AccessType::DepthStencilAttachmentRead => AccessInfo {
683            stage_mask: vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS
684                | vk::PipelineStageFlags::LATE_FRAGMENT_TESTS,
685            access_mask: vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ,
686            image_layout: vk::ImageLayout::DEPTH_STENCIL_READ_ONLY_OPTIMAL,
687        },
688        AccessType::DepthStencilAttachmentReadWrite => AccessInfo {
689            stage_mask: vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS
690                | vk::PipelineStageFlags::LATE_FRAGMENT_TESTS,
691            access_mask: vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
692                | vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE,
693            image_layout: vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
694        },
695        AccessType::ComputeShaderReadUniformBuffer => AccessInfo {
696            stage_mask: vk::PipelineStageFlags::COMPUTE_SHADER,
697            access_mask: vk::AccessFlags::UNIFORM_READ,
698            image_layout: vk::ImageLayout::UNDEFINED,
699        },
700        AccessType::ComputeShaderReadSampledImageOrUniformTexelBuffer => AccessInfo {
701            stage_mask: vk::PipelineStageFlags::COMPUTE_SHADER,
702            access_mask: vk::AccessFlags::SHADER_READ,
703            image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
704        },
705        AccessType::ComputeShaderReadOther => AccessInfo {
706            stage_mask: vk::PipelineStageFlags::COMPUTE_SHADER,
707            access_mask: vk::AccessFlags::SHADER_READ,
708            image_layout: vk::ImageLayout::GENERAL,
709        },
710        AccessType::AnyShaderReadUniformBuffer => AccessInfo {
711            stage_mask: vk::PipelineStageFlags::ALL_COMMANDS,
712            access_mask: vk::AccessFlags::UNIFORM_READ,
713            image_layout: vk::ImageLayout::UNDEFINED,
714        },
715        AccessType::AnyShaderReadUniformBufferOrVertexBuffer => AccessInfo {
716            stage_mask: vk::PipelineStageFlags::ALL_COMMANDS,
717            access_mask: vk::AccessFlags::UNIFORM_READ | vk::AccessFlags::VERTEX_ATTRIBUTE_READ,
718            image_layout: vk::ImageLayout::UNDEFINED,
719        },
720        AccessType::AnyShaderReadSampledImageOrUniformTexelBuffer => AccessInfo {
721            stage_mask: vk::PipelineStageFlags::ALL_COMMANDS,
722            access_mask: vk::AccessFlags::SHADER_READ,
723            image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
724        },
725        AccessType::AnyShaderReadOther => AccessInfo {
726            stage_mask: vk::PipelineStageFlags::ALL_COMMANDS,
727            access_mask: vk::AccessFlags::SHADER_READ,
728            image_layout: vk::ImageLayout::GENERAL,
729        },
730        AccessType::TransferRead => AccessInfo {
731            stage_mask: vk::PipelineStageFlags::TRANSFER,
732            access_mask: vk::AccessFlags::TRANSFER_READ,
733            image_layout: vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
734        },
735        AccessType::HostRead => AccessInfo {
736            stage_mask: vk::PipelineStageFlags::HOST,
737            access_mask: vk::AccessFlags::HOST_READ,
738            image_layout: vk::ImageLayout::GENERAL,
739        },
740        AccessType::Present => AccessInfo {
741            stage_mask: vk::PipelineStageFlags::empty(),
742            access_mask: vk::AccessFlags::empty(),
743            image_layout: vk::ImageLayout::PRESENT_SRC_KHR,
744        },
745        AccessType::CommandBufferWriteNVX => AccessInfo {
746            stage_mask: vk::PipelineStageFlags::COMMAND_PREPROCESS_NV,
747            access_mask: vk::AccessFlags::COMMAND_PREPROCESS_WRITE_NV,
748            image_layout: vk::ImageLayout::UNDEFINED,
749        },
750        AccessType::VertexShaderWrite => AccessInfo {
751            stage_mask: vk::PipelineStageFlags::VERTEX_SHADER,
752            access_mask: vk::AccessFlags::SHADER_WRITE,
753            image_layout: vk::ImageLayout::GENERAL,
754        },
755        AccessType::MeshShaderWrite => AccessInfo {
756            stage_mask: vk::PipelineStageFlags::MESH_SHADER_EXT,
757            access_mask: vk::AccessFlags::SHADER_WRITE,
758            image_layout: vk::ImageLayout::GENERAL,
759        },
760        AccessType::TaskShaderWrite => AccessInfo {
761            stage_mask: vk::PipelineStageFlags::TASK_SHADER_EXT,
762            access_mask: vk::AccessFlags::SHADER_WRITE,
763            image_layout: vk::ImageLayout::GENERAL,
764        },
765        AccessType::TessellationControlShaderWrite => AccessInfo {
766            stage_mask: vk::PipelineStageFlags::TESSELLATION_CONTROL_SHADER,
767            access_mask: vk::AccessFlags::SHADER_WRITE,
768            image_layout: vk::ImageLayout::GENERAL,
769        },
770        AccessType::TessellationEvaluationShaderWrite => AccessInfo {
771            stage_mask: vk::PipelineStageFlags::TESSELLATION_EVALUATION_SHADER,
772            access_mask: vk::AccessFlags::SHADER_WRITE,
773            image_layout: vk::ImageLayout::GENERAL,
774        },
775        AccessType::GeometryShaderWrite => AccessInfo {
776            stage_mask: vk::PipelineStageFlags::GEOMETRY_SHADER,
777            access_mask: vk::AccessFlags::SHADER_WRITE,
778            image_layout: vk::ImageLayout::GENERAL,
779        },
780        AccessType::FragmentShaderWrite => AccessInfo {
781            stage_mask: vk::PipelineStageFlags::FRAGMENT_SHADER,
782            access_mask: vk::AccessFlags::SHADER_WRITE,
783            image_layout: vk::ImageLayout::GENERAL,
784        },
785        AccessType::ColorAttachmentWrite => AccessInfo {
786            stage_mask: vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT,
787            access_mask: vk::AccessFlags::COLOR_ATTACHMENT_WRITE,
788            image_layout: vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,
789        },
790        AccessType::DepthStencilAttachmentWrite => AccessInfo {
791            stage_mask: vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS
792                | vk::PipelineStageFlags::LATE_FRAGMENT_TESTS,
793            access_mask: vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE,
794            image_layout: vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
795        },
796        AccessType::DepthAttachmentWriteStencilReadOnly => AccessInfo {
797            stage_mask: vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS
798                | vk::PipelineStageFlags::LATE_FRAGMENT_TESTS,
799            access_mask: vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE
800                | vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ,
801            image_layout: vk::ImageLayout::DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL,
802        },
803        AccessType::StencilAttachmentWriteDepthReadOnly => AccessInfo {
804            stage_mask: vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS
805                | vk::PipelineStageFlags::LATE_FRAGMENT_TESTS,
806            access_mask: vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE
807                | vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ,
808            image_layout: vk::ImageLayout::DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL,
809        },
810        AccessType::ComputeShaderWrite => AccessInfo {
811            stage_mask: vk::PipelineStageFlags::COMPUTE_SHADER,
812            access_mask: vk::AccessFlags::SHADER_WRITE,
813            image_layout: vk::ImageLayout::GENERAL,
814        },
815        AccessType::ComputeShaderReadWrite => AccessInfo {
816            stage_mask: vk::PipelineStageFlags::COMPUTE_SHADER,
817            access_mask: vk::AccessFlags::SHADER_READ | vk::AccessFlags::SHADER_WRITE,
818            image_layout: vk::ImageLayout::GENERAL,
819        },
820        AccessType::AnyShaderWrite => AccessInfo {
821            stage_mask: vk::PipelineStageFlags::ALL_COMMANDS,
822            access_mask: vk::AccessFlags::SHADER_WRITE,
823            image_layout: vk::ImageLayout::GENERAL,
824        },
825        AccessType::TransferWrite => AccessInfo {
826            stage_mask: vk::PipelineStageFlags::TRANSFER,
827            access_mask: vk::AccessFlags::TRANSFER_WRITE,
828            image_layout: vk::ImageLayout::TRANSFER_DST_OPTIMAL,
829        },
830        AccessType::HostWrite => AccessInfo {
831            stage_mask: vk::PipelineStageFlags::HOST,
832            access_mask: vk::AccessFlags::HOST_WRITE,
833            image_layout: vk::ImageLayout::GENERAL,
834        },
835        AccessType::ColorAttachmentReadWrite => AccessInfo {
836            stage_mask: vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT,
837            access_mask: vk::AccessFlags::COLOR_ATTACHMENT_READ
838                | vk::AccessFlags::COLOR_ATTACHMENT_WRITE,
839            image_layout: vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,
840        },
841        AccessType::General => AccessInfo {
842            stage_mask: vk::PipelineStageFlags::ALL_COMMANDS,
843            access_mask: vk::AccessFlags::MEMORY_READ | vk::AccessFlags::MEMORY_WRITE,
844            image_layout: vk::ImageLayout::GENERAL,
845        },
846        AccessType::RayTracingShaderReadSampledImageOrUniformTexelBuffer => AccessInfo {
847            stage_mask: vk::PipelineStageFlags::RAY_TRACING_SHADER_KHR,
848            access_mask: vk::AccessFlags::SHADER_READ,
849            image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
850        },
851        AccessType::RayTracingShaderReadColorInputAttachment => AccessInfo {
852            stage_mask: vk::PipelineStageFlags::RAY_TRACING_SHADER_KHR,
853            access_mask: vk::AccessFlags::INPUT_ATTACHMENT_READ,
854            image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
855        },
856        AccessType::RayTracingShaderReadDepthStencilInputAttachment => AccessInfo {
857            stage_mask: vk::PipelineStageFlags::RAY_TRACING_SHADER_KHR,
858            access_mask: vk::AccessFlags::INPUT_ATTACHMENT_READ,
859            image_layout: vk::ImageLayout::DEPTH_STENCIL_READ_ONLY_OPTIMAL,
860        },
861        AccessType::RayTracingShaderReadAccelerationStructure => AccessInfo {
862            stage_mask: vk::PipelineStageFlags::RAY_TRACING_SHADER_KHR,
863            access_mask: vk::AccessFlags::ACCELERATION_STRUCTURE_READ_KHR,
864            image_layout: vk::ImageLayout::UNDEFINED,
865        },
866        AccessType::RayTracingShaderReadOther => AccessInfo {
867            stage_mask: vk::PipelineStageFlags::RAY_TRACING_SHADER_KHR,
868            access_mask: vk::AccessFlags::SHADER_READ,
869            image_layout: vk::ImageLayout::GENERAL,
870        },
871        AccessType::AccelerationStructureBuildWrite => AccessInfo {
872            stage_mask: vk::PipelineStageFlags::ACCELERATION_STRUCTURE_BUILD_KHR,
873            access_mask: vk::AccessFlags::ACCELERATION_STRUCTURE_WRITE_KHR,
874            image_layout: vk::ImageLayout::UNDEFINED,
875        },
876        AccessType::AccelerationStructureBuildRead => AccessInfo {
877            stage_mask: vk::PipelineStageFlags::ACCELERATION_STRUCTURE_BUILD_KHR,
878            access_mask: vk::AccessFlags::ACCELERATION_STRUCTURE_READ_KHR,
879            image_layout: vk::ImageLayout::UNDEFINED,
880        },
881        AccessType::AccelerationStructureBufferWrite => AccessInfo {
882            stage_mask: vk::PipelineStageFlags::ACCELERATION_STRUCTURE_BUILD_KHR,
883            access_mask: vk::AccessFlags::TRANSFER_WRITE,
884            image_layout: vk::ImageLayout::UNDEFINED,
885        },
886    }
887}
888
889pub(crate) fn is_write_access(access_type: AccessType) -> bool {
890    matches!(
891        access_type,
892        AccessType::CommandBufferWriteNVX
893            | AccessType::VertexShaderWrite
894            | AccessType::MeshShaderWrite
895            | AccessType::TaskShaderWrite
896            | AccessType::TessellationControlShaderWrite
897            | AccessType::TessellationEvaluationShaderWrite
898            | AccessType::GeometryShaderWrite
899            | AccessType::FragmentShaderWrite
900            | AccessType::ColorAttachmentWrite
901            | AccessType::DepthStencilAttachmentWrite
902            | AccessType::DepthAttachmentWriteStencilReadOnly
903            | AccessType::DepthStencilAttachmentReadWrite
904            | AccessType::StencilAttachmentWriteDepthReadOnly
905            | AccessType::ComputeShaderWrite
906            | AccessType::ComputeShaderReadWrite
907            | AccessType::AnyShaderWrite
908            | AccessType::TransferWrite
909            | AccessType::HostWrite
910            | AccessType::ColorAttachmentReadWrite
911            | AccessType::General
912    )
913}