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