screen_13/driver/vk_sync/
lib.rs

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