Skip to main content

vk_graph/driver/
mod.rs

1//! **ADVANCED**: Raw Vulkan wrappers. Most users should use [`Graph`](crate::Graph),
2//! [`cmd`](crate::cmd), and [`node`](crate::node) instead.
3//!
4//! # Resources
5//!
6//! Resources are created and destroyed using RAII-style wrapper structures.
7//!
8//! The following resources are available:
9//!
10//! - [`AccelerationStructure`](accel_struct::AccelerationStructure)
11//! - [`Buffer`]
12//! - [`DescriptorSet`](descriptor_set::DescriptorSet)
13//! - [`Image`](image::Image)
14//!
15//! Graph-tracked resources are logically mutable and contain useful read-only public fields, for
16//! example:
17//!
18//! | [`Buffer`] field | Type |
19//! | --- | --- |
20//! | [`device`](Buffer::device) | [`Device`](device::Device) |
21//! | [`handle`](Buffer::handle) | [`vk::Buffer`] |
22//! | [`info`](Buffer::info) | [`BufferInfo`] |
23//!
24//! [`DescriptorSet`](descriptor_set::DescriptorSet) is instead a shared immutable wrapper and
25//! exposes the same information through `device()`, `handle()`, and `info()` methods.
26//!
27//! Graph-tracked resources use atomic [`AccessType`](sync::AccessType) values to maintain
28//! consistency and track changes. Descriptor contents do not declare graph synchronization.
29//!
30//! # Pipelines
31//!
32//! Pipelines enable reading and writing resources using shader code running on physical graphics
33//! hardware.
34//!
35//! The following pipelines are available:
36//!
37//! - [`ComputePipeline`](compute::ComputePipeline)
38//! - [`GraphicsPipeline`](graphics::GraphicsPipeline)
39//! - [`RayTracingPipeline`](ray_tracing::RayTracingPipeline)
40//!
41//! Pipelines are immutable. All pipeline types contain useful public methods, for
42//! example:
43//!
44//! | [`ComputePipeline`](compute::ComputePipeline) method | Type |
45//! | --- | --- |
46//! | [`device(&self)`](compute::ComputePipeline::device) | [`Device`](device::Device) |
47//! | [`handle(&self)`](compute::ComputePipeline::handle) | [`vk::Pipeline`] |
48//! | [`info(&self)`](compute::ComputePipeline::info) | [`ComputePipelineInfo`](compute::ComputePipelineInfo) |
49
50pub mod accel_struct;
51pub mod buffer;
52pub mod cmd_buf;
53pub mod compute;
54pub mod descriptor_set;
55pub mod device;
56pub mod fence;
57pub mod graphics;
58pub mod image;
59pub mod instance;
60pub mod physical_device;
61pub mod ray_tracing;
62pub mod render_pass;
63pub mod shader;
64pub mod surface;
65pub mod swapchain;
66
67pub(crate) mod query_pool;
68
69mod descriptor_set_layout;
70
71/// Re-export of the [`ash`] crate — the foundational Vulkan bindings that every wrapper in this
72/// crate is built on.
73///
74/// `vk-graph` is **ash+graph**: it wraps `ash` to make Vulkan easier to use, but does not replace
75/// it. Expert users can always reach through to the raw bindings via `vk_graph::driver::ash`.
76///
77/// # Hidden from docs
78///
79/// This re-export is `#[doc(hidden)]` to avoid duplicating the entire `ash` API surface in
80/// `vk-graph`'s documentation. It is intentionally public and stable — not deprecated.
81#[doc(hidden)]
82pub use ash::{self};
83
84/// Re-export of [`vk_sync`] under the `sync` alias — Vulkan synchronization primitives.
85///
86/// Provides [`AccessType`](sync::AccessType) and related types that are the foundation of
87/// `vk-graph`'s automatic resource tracking.
88///
89/// # Hidden from docs
90///
91/// This re-export is `#[doc(hidden)]` to avoid duplicating the entire `vk_sync` API surface in
92/// `vk-graph`'s documentation. It is intentionally public and stable — not deprecated.
93#[doc(hidden)]
94pub use vk_sync::{self as sync};
95
96pub(crate) use self::{
97    descriptor_set::RawDescriptorSet,
98    descriptor_set_layout::DescriptorSetLayout,
99    render_pass::{
100        AttachmentInfo, AttachmentRef, FramebufferAttachmentImageInfo, FramebufferInfo,
101        SubpassDependency, SubpassInfo,
102    },
103    shader::{Descriptor, DescriptorBindingMap, DescriptorInfo},
104    surface::Surface,
105};
106
107use {
108    self::{
109        buffer::{Buffer, BufferInfo},
110        graphics::VertexInputState,
111    },
112    ash::vk,
113    gpu_allocator::AllocationError,
114    std::{
115        cmp::Ordering,
116        convert::Infallible,
117        error::Error,
118        fmt::{Display, Formatter},
119    },
120};
121
122macro_rules! access_type_u8_map {
123    ($($idx:literal => $name:ident),* $(,)?) => {
124        pub(super) const fn access_type_into_u8(ty: self::sync::AccessType) -> u8 {
125            use self::sync::AccessType::*;
126
127            match ty {
128                $($name => $idx,)*
129            }
130        }
131
132        pub(super) const fn access_type_from_u8(value: u8) -> self::sync::AccessType {
133            use self::sync::AccessType::*;
134
135            match value {
136                $($idx => $name,)*
137                _ => panic!("invalid packed access type"),
138            }
139        }
140    };
141}
142
143access_type_u8_map! {
144    0 => Nothing,
145    1 => CommandBufferReadNVX,
146    2 => IndirectBuffer,
147    3 => IndexBuffer,
148    4 => VertexBuffer,
149    5 => VertexShaderReadUniformBuffer,
150    6 => VertexShaderReadSampledImageOrUniformTexelBuffer,
151    7 => VertexShaderReadOther,
152    8 => TessellationControlShaderReadUniformBuffer,
153    9 => TessellationControlShaderReadSampledImageOrUniformTexelBuffer,
154    10 => TessellationControlShaderReadOther,
155    11 => TessellationEvaluationShaderReadUniformBuffer,
156    12 => TessellationEvaluationShaderReadSampledImageOrUniformTexelBuffer,
157    13 => TessellationEvaluationShaderReadOther,
158    14 => GeometryShaderReadUniformBuffer,
159    15 => GeometryShaderReadSampledImageOrUniformTexelBuffer,
160    16 => GeometryShaderReadOther,
161    17 => FragmentShaderReadUniformBuffer,
162    18 => FragmentShaderReadSampledImageOrUniformTexelBuffer,
163    19 => FragmentShaderReadColorInputAttachment,
164    20 => FragmentShaderReadDepthStencilInputAttachment,
165    21 => FragmentShaderReadOther,
166    22 => ColorAttachmentRead,
167    23 => DepthStencilAttachmentRead,
168    24 => ComputeShaderReadUniformBuffer,
169    25 => ComputeShaderReadSampledImageOrUniformTexelBuffer,
170    26 => ComputeShaderReadOther,
171    27 => AnyShaderReadUniformBuffer,
172    28 => AnyShaderReadUniformBufferOrVertexBuffer,
173    29 => AnyShaderReadSampledImageOrUniformTexelBuffer,
174    30 => AnyShaderReadOther,
175    31 => TransferRead,
176    32 => HostRead,
177    33 => Present,
178    34 => CommandBufferWriteNVX,
179    35 => VertexShaderWrite,
180    36 => TessellationControlShaderWrite,
181    37 => TessellationEvaluationShaderWrite,
182    38 => GeometryShaderWrite,
183    39 => FragmentShaderWrite,
184    40 => ColorAttachmentWrite,
185    41 => DepthStencilAttachmentWrite,
186    42 => DepthStencilAttachmentReadWrite,
187    43 => DepthAttachmentWriteStencilReadOnly,
188    44 => StencilAttachmentWriteDepthReadOnly,
189    45 => ComputeShaderWrite,
190    46 => ComputeShaderReadWrite,
191    47 => AnyShaderWrite,
192    48 => TransferWrite,
193    49 => HostWrite,
194    50 => ColorAttachmentReadWrite,
195    51 => General,
196    52 => RayTracingShaderReadSampledImageOrUniformTexelBuffer,
197    53 => RayTracingShaderReadColorInputAttachment,
198    54 => RayTracingShaderReadDepthStencilInputAttachment,
199    55 => RayTracingShaderReadAccelerationStructure,
200    56 => RayTracingShaderReadOther,
201    57 => AccelerationStructureBuildWrite,
202    58 => AccelerationStructureBuildRead,
203    59 => AccelerationStructureBufferWrite,
204    60 => MeshShaderReadUniformBuffer,
205    61 => MeshShaderReadSampledImageOrUniformTexelBuffer,
206    62 => MeshShaderReadOther,
207    63 => TaskShaderReadUniformBuffer,
208    64 => TaskShaderReadSampledImageOrUniformTexelBuffer,
209    65 => TaskShaderReadOther,
210    66 => MeshShaderWrite,
211    67 => TaskShaderWrite,
212}
213
214pub(super) const fn format_aspect_mask(fmt: vk::Format) -> vk::ImageAspectFlags {
215    match fmt {
216        vk::Format::D16_UNORM | vk::Format::D32_SFLOAT | vk::Format::X8_D24_UNORM_PACK32 => {
217            vk::ImageAspectFlags::DEPTH
218        }
219        vk::Format::S8_UINT => vk::ImageAspectFlags::STENCIL,
220        vk::Format::D16_UNORM_S8_UINT
221        | vk::Format::D24_UNORM_S8_UINT
222        | vk::Format::D32_SFLOAT_S8_UINT => vk::ImageAspectFlags::from_raw(
223            vk::ImageAspectFlags::DEPTH.as_raw() | vk::ImageAspectFlags::STENCIL.as_raw(),
224        ),
225        _ => vk::ImageAspectFlags::COLOR,
226    }
227}
228
229/// Returns number of bytes used to store one texel block (a single addressable element of an
230/// uncompressed image, or a single compressed block of a compressed image).
231///
232/// See the [Texel Block Size](https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#texel-block-size)
233/// section of the Vulkan specification.
234pub const fn format_texel_block_size(fmt: vk::Format) -> u32 {
235    match fmt {
236        vk::Format::UNDEFINED => 0,
237        vk::Format::R4G4_UNORM_PACK8
238        | vk::Format::R8_UNORM
239        | vk::Format::R8_SNORM
240        | vk::Format::R8_USCALED
241        | vk::Format::R8_SSCALED
242        | vk::Format::R8_UINT
243        | vk::Format::R8_SINT
244        | vk::Format::R8_SRGB => 1,
245        vk::Format::A1B5G5R5_UNORM_PACK16_KHR
246        | vk::Format::R10X6_UNORM_PACK16
247        | vk::Format::R12X4_UNORM_PACK16
248        | vk::Format::A4R4G4B4_UNORM_PACK16
249        | vk::Format::A4B4G4R4_UNORM_PACK16
250        | vk::Format::R4G4B4A4_UNORM_PACK16
251        | vk::Format::B4G4R4A4_UNORM_PACK16
252        | vk::Format::R5G6B5_UNORM_PACK16
253        | vk::Format::B5G6R5_UNORM_PACK16
254        | vk::Format::R5G5B5A1_UNORM_PACK16
255        | vk::Format::B5G5R5A1_UNORM_PACK16
256        | vk::Format::A1R5G5B5_UNORM_PACK16
257        | vk::Format::R8G8_UNORM
258        | vk::Format::R8G8_SNORM
259        | vk::Format::R8G8_USCALED
260        | vk::Format::R8G8_SSCALED
261        | vk::Format::R8G8_UINT
262        | vk::Format::R8G8_SINT
263        | vk::Format::R8G8_SRGB
264        | vk::Format::R16_UNORM
265        | vk::Format::R16_SNORM
266        | vk::Format::R16_USCALED
267        | vk::Format::R16_SSCALED
268        | vk::Format::R16_UINT
269        | vk::Format::R16_SINT
270        | vk::Format::R16_SFLOAT => 2,
271        vk::Format::A8_UNORM_KHR => 1,
272        vk::Format::R8G8B8_UNORM
273        | vk::Format::R8G8B8_SNORM
274        | vk::Format::R8G8B8_USCALED
275        | vk::Format::R8G8B8_SSCALED
276        | vk::Format::R8G8B8_UINT
277        | vk::Format::R8G8B8_SINT
278        | vk::Format::R8G8B8_SRGB
279        | vk::Format::B8G8R8_UNORM
280        | vk::Format::B8G8R8_SNORM
281        | vk::Format::B8G8R8_USCALED
282        | vk::Format::B8G8R8_SSCALED
283        | vk::Format::B8G8R8_UINT
284        | vk::Format::B8G8R8_SINT
285        | vk::Format::B8G8R8_SRGB => 3,
286        vk::Format::R10X6G10X6_UNORM_2PACK16
287        | vk::Format::R12X4G12X4_UNORM_2PACK16
288        | vk::Format::R16G16_S10_5_NV
289        | vk::Format::R8G8B8A8_UNORM
290        | vk::Format::R8G8B8A8_SNORM
291        | vk::Format::R8G8B8A8_USCALED
292        | vk::Format::R8G8B8A8_SSCALED
293        | vk::Format::R8G8B8A8_UINT
294        | vk::Format::R8G8B8A8_SINT
295        | vk::Format::R8G8B8A8_SRGB
296        | vk::Format::B8G8R8A8_UNORM
297        | vk::Format::B8G8R8A8_SNORM
298        | vk::Format::B8G8R8A8_USCALED
299        | vk::Format::B8G8R8A8_SSCALED
300        | vk::Format::B8G8R8A8_UINT
301        | vk::Format::B8G8R8A8_SINT
302        | vk::Format::B8G8R8A8_SRGB
303        | vk::Format::A8B8G8R8_UNORM_PACK32
304        | vk::Format::A8B8G8R8_SNORM_PACK32
305        | vk::Format::A8B8G8R8_USCALED_PACK32
306        | vk::Format::A8B8G8R8_SSCALED_PACK32
307        | vk::Format::A8B8G8R8_UINT_PACK32
308        | vk::Format::A8B8G8R8_SINT_PACK32
309        | vk::Format::A8B8G8R8_SRGB_PACK32
310        | vk::Format::A2R10G10B10_UNORM_PACK32
311        | vk::Format::A2R10G10B10_SNORM_PACK32
312        | vk::Format::A2R10G10B10_USCALED_PACK32
313        | vk::Format::A2R10G10B10_SSCALED_PACK32
314        | vk::Format::A2R10G10B10_UINT_PACK32
315        | vk::Format::A2R10G10B10_SINT_PACK32
316        | vk::Format::A2B10G10R10_UNORM_PACK32
317        | vk::Format::A2B10G10R10_SNORM_PACK32
318        | vk::Format::A2B10G10R10_USCALED_PACK32
319        | vk::Format::A2B10G10R10_SSCALED_PACK32
320        | vk::Format::A2B10G10R10_UINT_PACK32
321        | vk::Format::A2B10G10R10_SINT_PACK32
322        | vk::Format::R16G16_UNORM
323        | vk::Format::R16G16_SNORM
324        | vk::Format::R16G16_USCALED
325        | vk::Format::R16G16_SSCALED
326        | vk::Format::R16G16_UINT
327        | vk::Format::R16G16_SINT
328        | vk::Format::R16G16_SFLOAT
329        | vk::Format::R32_UINT
330        | vk::Format::R32_SINT
331        | vk::Format::R32_SFLOAT
332        | vk::Format::B10G11R11_UFLOAT_PACK32
333        | vk::Format::E5B9G9R9_UFLOAT_PACK32 => 4,
334        vk::Format::R16G16B16_UNORM
335        | vk::Format::R16G16B16_SNORM
336        | vk::Format::R16G16B16_USCALED
337        | vk::Format::R16G16B16_SSCALED
338        | vk::Format::R16G16B16_UINT
339        | vk::Format::R16G16B16_SINT
340        | vk::Format::R16G16B16_SFLOAT => 6,
341        vk::Format::R16G16B16A16_UNORM
342        | vk::Format::R16G16B16A16_SNORM
343        | vk::Format::R16G16B16A16_USCALED
344        | vk::Format::R16G16B16A16_SSCALED
345        | vk::Format::R16G16B16A16_UINT
346        | vk::Format::R16G16B16A16_SINT
347        | vk::Format::R16G16B16A16_SFLOAT
348        | vk::Format::R32G32_UINT
349        | vk::Format::R32G32_SINT
350        | vk::Format::R32G32_SFLOAT
351        | vk::Format::R64_UINT
352        | vk::Format::R64_SINT
353        | vk::Format::R64_SFLOAT => 8,
354        vk::Format::R32G32B32_UINT | vk::Format::R32G32B32_SINT | vk::Format::R32G32B32_SFLOAT => {
355            12
356        }
357        vk::Format::R32G32B32A32_UINT
358        | vk::Format::R32G32B32A32_SINT
359        | vk::Format::R32G32B32A32_SFLOAT
360        | vk::Format::R64G64_UINT
361        | vk::Format::R64G64_SINT
362        | vk::Format::R64G64_SFLOAT => 16,
363        vk::Format::R64G64B64_UINT | vk::Format::R64G64B64_SINT | vk::Format::R64G64B64_SFLOAT => {
364            24
365        }
366        vk::Format::R64G64B64A64_UINT
367        | vk::Format::R64G64B64A64_SINT
368        | vk::Format::R64G64B64A64_SFLOAT => 32,
369        vk::Format::D16_UNORM => 2,
370        vk::Format::X8_D24_UNORM_PACK32 => 4,
371        vk::Format::D32_SFLOAT => 4,
372        vk::Format::S8_UINT => 1,
373        vk::Format::D16_UNORM_S8_UINT => 3,
374        vk::Format::D24_UNORM_S8_UINT => 4,
375        vk::Format::D32_SFLOAT_S8_UINT => 5,
376        vk::Format::BC1_RGB_UNORM_BLOCK
377        | vk::Format::BC1_RGB_SRGB_BLOCK
378        | vk::Format::BC1_RGBA_UNORM_BLOCK
379        | vk::Format::BC1_RGBA_SRGB_BLOCK
380        | vk::Format::BC4_UNORM_BLOCK
381        | vk::Format::BC4_SNORM_BLOCK
382        | vk::Format::ETC2_R8G8B8_UNORM_BLOCK
383        | vk::Format::ETC2_R8G8B8_SRGB_BLOCK
384        | vk::Format::ETC2_R8G8B8A1_UNORM_BLOCK
385        | vk::Format::ETC2_R8G8B8A1_SRGB_BLOCK
386        | vk::Format::EAC_R11_UNORM_BLOCK
387        | vk::Format::EAC_R11_SNORM_BLOCK => 8,
388        vk::Format::BC2_UNORM_BLOCK
389        | vk::Format::BC2_SRGB_BLOCK
390        | vk::Format::BC3_UNORM_BLOCK
391        | vk::Format::BC3_SRGB_BLOCK
392        | vk::Format::BC5_UNORM_BLOCK
393        | vk::Format::BC5_SNORM_BLOCK
394        | vk::Format::BC6H_UFLOAT_BLOCK
395        | vk::Format::BC6H_SFLOAT_BLOCK
396        | vk::Format::BC7_UNORM_BLOCK
397        | vk::Format::BC7_SRGB_BLOCK
398        | vk::Format::ETC2_R8G8B8A8_UNORM_BLOCK
399        | vk::Format::ETC2_R8G8B8A8_SRGB_BLOCK
400        | vk::Format::EAC_R11G11_UNORM_BLOCK
401        | vk::Format::EAC_R11G11_SNORM_BLOCK => 16,
402        vk::Format::ASTC_4X4_SFLOAT_BLOCK
403        | vk::Format::ASTC_4X4_UNORM_BLOCK
404        | vk::Format::ASTC_4X4_SRGB_BLOCK
405        | vk::Format::ASTC_5X4_SFLOAT_BLOCK
406        | vk::Format::ASTC_5X4_UNORM_BLOCK
407        | vk::Format::ASTC_5X4_SRGB_BLOCK
408        | vk::Format::ASTC_5X5_SFLOAT_BLOCK
409        | vk::Format::ASTC_5X5_UNORM_BLOCK
410        | vk::Format::ASTC_5X5_SRGB_BLOCK
411        | vk::Format::ASTC_6X5_SFLOAT_BLOCK
412        | vk::Format::ASTC_6X5_UNORM_BLOCK
413        | vk::Format::ASTC_6X5_SRGB_BLOCK
414        | vk::Format::ASTC_6X6_SFLOAT_BLOCK
415        | vk::Format::ASTC_6X6_UNORM_BLOCK
416        | vk::Format::ASTC_6X6_SRGB_BLOCK
417        | vk::Format::ASTC_8X5_SFLOAT_BLOCK
418        | vk::Format::ASTC_8X5_UNORM_BLOCK
419        | vk::Format::ASTC_8X5_SRGB_BLOCK
420        | vk::Format::ASTC_8X6_SFLOAT_BLOCK
421        | vk::Format::ASTC_8X6_UNORM_BLOCK
422        | vk::Format::ASTC_8X6_SRGB_BLOCK
423        | vk::Format::ASTC_8X8_SFLOAT_BLOCK
424        | vk::Format::ASTC_8X8_UNORM_BLOCK
425        | vk::Format::ASTC_8X8_SRGB_BLOCK
426        | vk::Format::ASTC_10X5_SFLOAT_BLOCK
427        | vk::Format::ASTC_10X5_UNORM_BLOCK
428        | vk::Format::ASTC_10X5_SRGB_BLOCK
429        | vk::Format::ASTC_10X6_SFLOAT_BLOCK
430        | vk::Format::ASTC_10X6_UNORM_BLOCK
431        | vk::Format::ASTC_10X6_SRGB_BLOCK
432        | vk::Format::ASTC_10X8_SFLOAT_BLOCK
433        | vk::Format::ASTC_10X8_UNORM_BLOCK
434        | vk::Format::ASTC_10X8_SRGB_BLOCK
435        | vk::Format::ASTC_10X10_SFLOAT_BLOCK
436        | vk::Format::ASTC_10X10_UNORM_BLOCK
437        | vk::Format::ASTC_10X10_SRGB_BLOCK
438        | vk::Format::ASTC_12X10_SFLOAT_BLOCK
439        | vk::Format::ASTC_12X10_UNORM_BLOCK
440        | vk::Format::ASTC_12X10_SRGB_BLOCK
441        | vk::Format::ASTC_12X12_SFLOAT_BLOCK
442        | vk::Format::ASTC_12X12_UNORM_BLOCK
443        | vk::Format::ASTC_12X12_SRGB_BLOCK => 16,
444        vk::Format::G8B8G8R8_422_UNORM | vk::Format::B8G8R8G8_422_UNORM => 4,
445        vk::Format::G8_B8_R8_3PLANE_420_UNORM
446        | vk::Format::G8_B8R8_2PLANE_420_UNORM
447        | vk::Format::G8_B8_R8_3PLANE_422_UNORM
448        | vk::Format::G8_B8R8_2PLANE_422_UNORM
449        | vk::Format::G8_B8_R8_3PLANE_444_UNORM => 3,
450        vk::Format::R10X6G10X6B10X6A10X6_UNORM_4PACK16
451        | vk::Format::G10X6B10X6G10X6R10X6_422_UNORM_4PACK16
452        | vk::Format::B10X6G10X6R10X6G10X6_422_UNORM_4PACK16
453        | vk::Format::R12X4G12X4B12X4A12X4_UNORM_4PACK16
454        | vk::Format::G12X4B12X4G12X4R12X4_422_UNORM_4PACK16
455        | vk::Format::B12X4G12X4R12X4G12X4_422_UNORM_4PACK16
456        | vk::Format::G16B16G16R16_422_UNORM
457        | vk::Format::B16G16R16G16_422_UNORM => 8,
458        vk::Format::G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16
459        | vk::Format::G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16
460        | vk::Format::G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16
461        | vk::Format::G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16
462        | vk::Format::G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16
463        | vk::Format::G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16
464        | vk::Format::G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16
465        | vk::Format::G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16
466        | vk::Format::G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16
467        | vk::Format::G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16
468        | vk::Format::G16_B16_R16_3PLANE_420_UNORM
469        | vk::Format::G16_B16R16_2PLANE_420_UNORM
470        | vk::Format::G16_B16_R16_3PLANE_422_UNORM
471        | vk::Format::G16_B16R16_2PLANE_422_UNORM
472        | vk::Format::G16_B16_R16_3PLANE_444_UNORM => 6,
473        vk::Format::PVRTC1_2BPP_UNORM_BLOCK_IMG
474        | vk::Format::PVRTC1_2BPP_SRGB_BLOCK_IMG
475        | vk::Format::PVRTC1_4BPP_UNORM_BLOCK_IMG
476        | vk::Format::PVRTC1_4BPP_SRGB_BLOCK_IMG
477        | vk::Format::PVRTC2_2BPP_UNORM_BLOCK_IMG
478        | vk::Format::PVRTC2_2BPP_SRGB_BLOCK_IMG
479        | vk::Format::PVRTC2_4BPP_UNORM_BLOCK_IMG
480        | vk::Format::PVRTC2_4BPP_SRGB_BLOCK_IMG => 8,
481        vk::Format::G8_B8R8_2PLANE_444_UNORM => 3,
482        vk::Format::G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16
483        | vk::Format::G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16
484        | vk::Format::G16_B16R16_2PLANE_444_UNORM => 6,
485        /*
486        Vulkan is extensible; new formats can appear at any time. The caller is expected to know the
487        format is valid; no runtime assertion needed per the project's philosophy.
488        */
489        _ => 0,
490    }
491}
492
493/// Returns the extent of a block of texels for the given Vulkan format.
494/// Uncompressed formats typically have a block extent of `(1, 1)`.
495///
496/// See the [Texel Block Size](https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#texel-block-size)
497/// section of the Vulkan specification.
498pub const fn format_texel_block_extent(vk_format: vk::Format) -> (u32, u32) {
499    match vk_format {
500        vk::Format::UNDEFINED => (1, 1),
501        vk::Format::R4G4_UNORM_PACK8
502        | vk::Format::R8_UNORM
503        | vk::Format::R8_SNORM
504        | vk::Format::R8_USCALED
505        | vk::Format::R8_SSCALED
506        | vk::Format::R8_UINT
507        | vk::Format::R8_SINT
508        | vk::Format::R8_SRGB
509        | vk::Format::A1B5G5R5_UNORM_PACK16_KHR
510        | vk::Format::R10X6_UNORM_PACK16
511        | vk::Format::R12X4_UNORM_PACK16
512        | vk::Format::A4R4G4B4_UNORM_PACK16
513        | vk::Format::A4B4G4R4_UNORM_PACK16
514        | vk::Format::R4G4B4A4_UNORM_PACK16
515        | vk::Format::B4G4R4A4_UNORM_PACK16
516        | vk::Format::R5G6B5_UNORM_PACK16
517        | vk::Format::B5G6R5_UNORM_PACK16
518        | vk::Format::R5G5B5A1_UNORM_PACK16
519        | vk::Format::B5G5R5A1_UNORM_PACK16
520        | vk::Format::A1R5G5B5_UNORM_PACK16
521        | vk::Format::R8G8_UNORM
522        | vk::Format::R8G8_SNORM
523        | vk::Format::R8G8_USCALED
524        | vk::Format::R8G8_SSCALED
525        | vk::Format::R8G8_UINT
526        | vk::Format::R8G8_SINT
527        | vk::Format::R8G8_SRGB
528        | vk::Format::R16_UNORM
529        | vk::Format::R16_SNORM
530        | vk::Format::R16_USCALED
531        | vk::Format::R16_SSCALED
532        | vk::Format::R16_UINT
533        | vk::Format::R16_SINT
534        | vk::Format::R16_SFLOAT
535        | vk::Format::A8_UNORM_KHR
536        | vk::Format::R8G8B8_UNORM
537        | vk::Format::R8G8B8_SNORM
538        | vk::Format::R8G8B8_USCALED
539        | vk::Format::R8G8B8_SSCALED
540        | vk::Format::R8G8B8_UINT
541        | vk::Format::R8G8B8_SINT
542        | vk::Format::R8G8B8_SRGB
543        | vk::Format::B8G8R8_UNORM
544        | vk::Format::B8G8R8_SNORM
545        | vk::Format::B8G8R8_USCALED
546        | vk::Format::B8G8R8_SSCALED
547        | vk::Format::B8G8R8_UINT
548        | vk::Format::B8G8R8_SINT
549        | vk::Format::B8G8R8_SRGB
550        | vk::Format::R10X6G10X6_UNORM_2PACK16
551        | vk::Format::R12X4G12X4_UNORM_2PACK16
552        | vk::Format::R16G16_S10_5_NV
553        | vk::Format::R8G8B8A8_UNORM
554        | vk::Format::R8G8B8A8_SNORM
555        | vk::Format::R8G8B8A8_USCALED
556        | vk::Format::R8G8B8A8_SSCALED
557        | vk::Format::R8G8B8A8_UINT
558        | vk::Format::R8G8B8A8_SINT
559        | vk::Format::R8G8B8A8_SRGB
560        | vk::Format::B8G8R8A8_UNORM
561        | vk::Format::B8G8R8A8_SNORM
562        | vk::Format::B8G8R8A8_USCALED
563        | vk::Format::B8G8R8A8_SSCALED
564        | vk::Format::B8G8R8A8_UINT
565        | vk::Format::B8G8R8A8_SINT
566        | vk::Format::B8G8R8A8_SRGB
567        | vk::Format::A8B8G8R8_UNORM_PACK32
568        | vk::Format::A8B8G8R8_SNORM_PACK32
569        | vk::Format::A8B8G8R8_USCALED_PACK32
570        | vk::Format::A8B8G8R8_SSCALED_PACK32
571        | vk::Format::A8B8G8R8_UINT_PACK32
572        | vk::Format::A8B8G8R8_SINT_PACK32
573        | vk::Format::A8B8G8R8_SRGB_PACK32
574        | vk::Format::A2R10G10B10_UNORM_PACK32
575        | vk::Format::A2R10G10B10_SNORM_PACK32
576        | vk::Format::A2R10G10B10_USCALED_PACK32
577        | vk::Format::A2R10G10B10_SSCALED_PACK32
578        | vk::Format::A2R10G10B10_UINT_PACK32
579        | vk::Format::A2R10G10B10_SINT_PACK32
580        | vk::Format::A2B10G10R10_UNORM_PACK32
581        | vk::Format::A2B10G10R10_SNORM_PACK32
582        | vk::Format::A2B10G10R10_USCALED_PACK32
583        | vk::Format::A2B10G10R10_SSCALED_PACK32
584        | vk::Format::A2B10G10R10_UINT_PACK32
585        | vk::Format::A2B10G10R10_SINT_PACK32
586        | vk::Format::R16G16_UNORM
587        | vk::Format::R16G16_SNORM
588        | vk::Format::R16G16_USCALED
589        | vk::Format::R16G16_SSCALED
590        | vk::Format::R16G16_UINT
591        | vk::Format::R16G16_SINT
592        | vk::Format::R16G16_SFLOAT
593        | vk::Format::R32_UINT
594        | vk::Format::R32_SINT
595        | vk::Format::R32_SFLOAT
596        | vk::Format::B10G11R11_UFLOAT_PACK32
597        | vk::Format::E5B9G9R9_UFLOAT_PACK32
598        | vk::Format::R16G16B16_UNORM
599        | vk::Format::R16G16B16_SNORM
600        | vk::Format::R16G16B16_USCALED
601        | vk::Format::R16G16B16_SSCALED
602        | vk::Format::R16G16B16_UINT
603        | vk::Format::R16G16B16_SINT
604        | vk::Format::R16G16B16_SFLOAT
605        | vk::Format::R16G16B16A16_UNORM
606        | vk::Format::R16G16B16A16_SNORM
607        | vk::Format::R16G16B16A16_USCALED
608        | vk::Format::R16G16B16A16_SSCALED
609        | vk::Format::R16G16B16A16_UINT
610        | vk::Format::R16G16B16A16_SINT
611        | vk::Format::R16G16B16A16_SFLOAT
612        | vk::Format::R32G32_UINT
613        | vk::Format::R32G32_SINT
614        | vk::Format::R32G32_SFLOAT
615        | vk::Format::R64_UINT
616        | vk::Format::R64_SINT
617        | vk::Format::R64_SFLOAT
618        | vk::Format::R32G32B32_UINT
619        | vk::Format::R32G32B32_SINT
620        | vk::Format::R32G32B32_SFLOAT
621        | vk::Format::R32G32B32A32_UINT
622        | vk::Format::R32G32B32A32_SINT
623        | vk::Format::R32G32B32A32_SFLOAT
624        | vk::Format::R64G64_UINT
625        | vk::Format::R64G64_SINT
626        | vk::Format::R64G64_SFLOAT
627        | vk::Format::R64G64B64_UINT
628        | vk::Format::R64G64B64_SINT
629        | vk::Format::R64G64B64_SFLOAT
630        | vk::Format::R64G64B64A64_UINT
631        | vk::Format::R64G64B64A64_SINT
632        | vk::Format::R64G64B64A64_SFLOAT
633        | vk::Format::D16_UNORM
634        | vk::Format::X8_D24_UNORM_PACK32
635        | vk::Format::D32_SFLOAT
636        | vk::Format::S8_UINT
637        | vk::Format::D16_UNORM_S8_UINT
638        | vk::Format::D24_UNORM_S8_UINT
639        | vk::Format::D32_SFLOAT_S8_UINT => (1, 1),
640        vk::Format::BC1_RGB_UNORM_BLOCK
641        | vk::Format::BC1_RGB_SRGB_BLOCK
642        | vk::Format::BC1_RGBA_UNORM_BLOCK
643        | vk::Format::BC1_RGBA_SRGB_BLOCK
644        | vk::Format::BC2_UNORM_BLOCK
645        | vk::Format::BC2_SRGB_BLOCK
646        | vk::Format::BC3_UNORM_BLOCK
647        | vk::Format::BC3_SRGB_BLOCK
648        | vk::Format::BC4_UNORM_BLOCK
649        | vk::Format::BC4_SNORM_BLOCK
650        | vk::Format::BC5_UNORM_BLOCK
651        | vk::Format::BC5_SNORM_BLOCK
652        | vk::Format::BC6H_UFLOAT_BLOCK
653        | vk::Format::BC6H_SFLOAT_BLOCK
654        | vk::Format::BC7_UNORM_BLOCK
655        | vk::Format::BC7_SRGB_BLOCK
656        | vk::Format::ETC2_R8G8B8_UNORM_BLOCK
657        | vk::Format::ETC2_R8G8B8_SRGB_BLOCK
658        | vk::Format::ETC2_R8G8B8A1_UNORM_BLOCK
659        | vk::Format::ETC2_R8G8B8A1_SRGB_BLOCK
660        | vk::Format::ETC2_R8G8B8A8_UNORM_BLOCK
661        | vk::Format::ETC2_R8G8B8A8_SRGB_BLOCK
662        | vk::Format::EAC_R11_UNORM_BLOCK
663        | vk::Format::EAC_R11_SNORM_BLOCK
664        | vk::Format::EAC_R11G11_UNORM_BLOCK
665        | vk::Format::EAC_R11G11_SNORM_BLOCK => (4, 4),
666        vk::Format::ASTC_4X4_SFLOAT_BLOCK
667        | vk::Format::ASTC_4X4_UNORM_BLOCK
668        | vk::Format::ASTC_4X4_SRGB_BLOCK => (4, 4),
669        vk::Format::ASTC_5X4_SFLOAT_BLOCK
670        | vk::Format::ASTC_5X4_UNORM_BLOCK
671        | vk::Format::ASTC_5X4_SRGB_BLOCK => (5, 4),
672        vk::Format::ASTC_5X5_SFLOAT_BLOCK
673        | vk::Format::ASTC_5X5_UNORM_BLOCK
674        | vk::Format::ASTC_5X5_SRGB_BLOCK => (5, 5),
675        vk::Format::ASTC_6X5_SFLOAT_BLOCK
676        | vk::Format::ASTC_6X5_UNORM_BLOCK
677        | vk::Format::ASTC_6X5_SRGB_BLOCK => (6, 5),
678        vk::Format::ASTC_6X6_SFLOAT_BLOCK
679        | vk::Format::ASTC_6X6_UNORM_BLOCK
680        | vk::Format::ASTC_6X6_SRGB_BLOCK => (6, 6),
681        vk::Format::ASTC_8X5_SFLOAT_BLOCK
682        | vk::Format::ASTC_8X5_UNORM_BLOCK
683        | vk::Format::ASTC_8X5_SRGB_BLOCK => (8, 5),
684        vk::Format::ASTC_8X6_SFLOAT_BLOCK
685        | vk::Format::ASTC_8X6_UNORM_BLOCK
686        | vk::Format::ASTC_8X6_SRGB_BLOCK => (8, 6),
687        vk::Format::ASTC_8X8_SFLOAT_BLOCK
688        | vk::Format::ASTC_8X8_UNORM_BLOCK
689        | vk::Format::ASTC_8X8_SRGB_BLOCK => (8, 8),
690        vk::Format::ASTC_10X5_SFLOAT_BLOCK
691        | vk::Format::ASTC_10X5_UNORM_BLOCK
692        | vk::Format::ASTC_10X5_SRGB_BLOCK => (10, 5),
693        vk::Format::ASTC_10X6_SFLOAT_BLOCK
694        | vk::Format::ASTC_10X6_UNORM_BLOCK
695        | vk::Format::ASTC_10X6_SRGB_BLOCK => (10, 6),
696        vk::Format::ASTC_10X8_SFLOAT_BLOCK
697        | vk::Format::ASTC_10X8_UNORM_BLOCK
698        | vk::Format::ASTC_10X8_SRGB_BLOCK => (10, 8),
699        vk::Format::ASTC_10X10_SFLOAT_BLOCK
700        | vk::Format::ASTC_10X10_UNORM_BLOCK
701        | vk::Format::ASTC_10X10_SRGB_BLOCK => (10, 10),
702        vk::Format::ASTC_12X10_SFLOAT_BLOCK
703        | vk::Format::ASTC_12X10_UNORM_BLOCK
704        | vk::Format::ASTC_12X10_SRGB_BLOCK => (12, 10),
705        vk::Format::ASTC_12X12_SFLOAT_BLOCK
706        | vk::Format::ASTC_12X12_UNORM_BLOCK
707        | vk::Format::ASTC_12X12_SRGB_BLOCK => (12, 12),
708        vk::Format::G8B8G8R8_422_UNORM | vk::Format::B8G8R8G8_422_UNORM => (2, 1),
709        vk::Format::G8_B8_R8_3PLANE_420_UNORM
710        | vk::Format::G8_B8R8_2PLANE_420_UNORM
711        | vk::Format::G8_B8_R8_3PLANE_422_UNORM
712        | vk::Format::G8_B8R8_2PLANE_422_UNORM
713        | vk::Format::G8_B8_R8_3PLANE_444_UNORM
714        | vk::Format::R10X6G10X6B10X6A10X6_UNORM_4PACK16
715        | vk::Format::G10X6B10X6G10X6R10X6_422_UNORM_4PACK16
716        | vk::Format::B10X6G10X6R10X6G10X6_422_UNORM_4PACK16
717        | vk::Format::G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16
718        | vk::Format::G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16
719        | vk::Format::G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16
720        | vk::Format::G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16
721        | vk::Format::G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16
722        | vk::Format::R12X4G12X4B12X4A12X4_UNORM_4PACK16
723        | vk::Format::G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16
724        | vk::Format::G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16
725        | vk::Format::G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16
726        | vk::Format::G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16
727        | vk::Format::G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16
728        | vk::Format::G16_B16_R16_3PLANE_420_UNORM
729        | vk::Format::G16_B16R16_2PLANE_420_UNORM
730        | vk::Format::G16_B16_R16_3PLANE_422_UNORM
731        | vk::Format::G16_B16R16_2PLANE_422_UNORM
732        | vk::Format::G16_B16_R16_3PLANE_444_UNORM
733        | vk::Format::G8_B8R8_2PLANE_444_UNORM
734        | vk::Format::G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16
735        | vk::Format::G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16
736        | vk::Format::G16_B16R16_2PLANE_444_UNORM => (1, 1),
737        vk::Format::G12X4B12X4G12X4R12X4_422_UNORM_4PACK16
738        | vk::Format::B12X4G12X4R12X4G12X4_422_UNORM_4PACK16
739        | vk::Format::G16B16G16R16_422_UNORM
740        | vk::Format::B16G16R16G16_422_UNORM => (2, 1),
741        vk::Format::PVRTC1_2BPP_UNORM_BLOCK_IMG
742        | vk::Format::PVRTC1_2BPP_SRGB_BLOCK_IMG
743        | vk::Format::PVRTC2_2BPP_UNORM_BLOCK_IMG
744        | vk::Format::PVRTC2_2BPP_SRGB_BLOCK_IMG => (8, 4),
745        vk::Format::PVRTC1_4BPP_UNORM_BLOCK_IMG
746        | vk::Format::PVRTC1_4BPP_SRGB_BLOCK_IMG
747        | vk::Format::PVRTC2_4BPP_UNORM_BLOCK_IMG
748        | vk::Format::PVRTC2_4BPP_SRGB_BLOCK_IMG => (4, 4),
749        /*
750        Vulkan is extensible; new formats can appear at any time. The caller is expected to know the
751        format is valid; no runtime assertion needed per the project's philosophy.
752        */
753        _ => (1, 1),
754    }
755}
756
757pub(super) const fn image_subresource_range_from_layers(
758    vk::ImageSubresourceLayers {
759        aspect_mask,
760        mip_level,
761        base_array_layer,
762        layer_count,
763    }: vk::ImageSubresourceLayers,
764) -> vk::ImageSubresourceRange {
765    vk::ImageSubresourceRange {
766        aspect_mask,
767        base_mip_level: mip_level,
768        level_count: 1,
769        base_array_layer,
770        layer_count,
771    }
772}
773
774pub(super) const fn initial_image_layout_access(
775    ty: self::sync::AccessType,
776) -> self::sync::AccessType {
777    use self::sync::AccessType::*;
778    match ty {
779        DepthStencilAttachmentReadWrite => DepthStencilAttachmentRead,
780        _ => ty,
781    }
782}
783
784pub(super) const fn is_read_access(ty: self::sync::AccessType) -> bool {
785    use self::sync::AccessType::*;
786    match ty {
787        Nothing
788        | CommandBufferWriteNVX
789        | VertexShaderWrite
790        | TessellationControlShaderWrite
791        | TessellationEvaluationShaderWrite
792        | GeometryShaderWrite
793        | FragmentShaderWrite
794        | ColorAttachmentWrite
795        | DepthStencilAttachmentWrite
796        | ComputeShaderWrite
797        | AnyShaderWrite
798        | TransferWrite
799        | HostWrite
800        | AccelerationStructureBuildWrite
801        | AccelerationStructureBufferWrite
802        | MeshShaderWrite
803        | TaskShaderWrite => false,
804        CommandBufferReadNVX
805        | IndirectBuffer
806        | IndexBuffer
807        | VertexBuffer
808        | VertexShaderReadUniformBuffer
809        | VertexShaderReadSampledImageOrUniformTexelBuffer
810        | VertexShaderReadOther
811        | TessellationControlShaderReadUniformBuffer
812        | TessellationControlShaderReadSampledImageOrUniformTexelBuffer
813        | TessellationControlShaderReadOther
814        | TessellationEvaluationShaderReadUniformBuffer
815        | TessellationEvaluationShaderReadSampledImageOrUniformTexelBuffer
816        | TessellationEvaluationShaderReadOther
817        | GeometryShaderReadUniformBuffer
818        | GeometryShaderReadSampledImageOrUniformTexelBuffer
819        | GeometryShaderReadOther
820        | FragmentShaderReadUniformBuffer
821        | FragmentShaderReadSampledImageOrUniformTexelBuffer
822        | FragmentShaderReadColorInputAttachment
823        | FragmentShaderReadDepthStencilInputAttachment
824        | FragmentShaderReadOther
825        | ColorAttachmentRead
826        | DepthStencilAttachmentRead
827        | ComputeShaderReadUniformBuffer
828        | ComputeShaderReadSampledImageOrUniformTexelBuffer
829        | ComputeShaderReadOther
830        | AnyShaderReadUniformBuffer
831        | AnyShaderReadUniformBufferOrVertexBuffer
832        | AnyShaderReadSampledImageOrUniformTexelBuffer
833        | AnyShaderReadOther
834        | TransferRead
835        | HostRead
836        | Present
837        | RayTracingShaderReadSampledImageOrUniformTexelBuffer
838        | RayTracingShaderReadColorInputAttachment
839        | RayTracingShaderReadDepthStencilInputAttachment
840        | RayTracingShaderReadAccelerationStructure
841        | RayTracingShaderReadOther
842        | AccelerationStructureBuildRead
843        | MeshShaderReadUniformBuffer
844        | MeshShaderReadSampledImageOrUniformTexelBuffer
845        | MeshShaderReadOther
846        | TaskShaderReadUniformBuffer
847        | TaskShaderReadSampledImageOrUniformTexelBuffer
848        | TaskShaderReadOther
849        | DepthStencilAttachmentReadWrite
850        | DepthAttachmentWriteStencilReadOnly
851        | StencilAttachmentWriteDepthReadOnly
852        | ColorAttachmentReadWrite
853        | General
854        | ComputeShaderReadWrite => true,
855    }
856}
857
858// Convert overlapping push constant regions such as this:
859// VERTEX 0..64
860// FRAGMENT 0..80
861//
862// To this:
863// VERTEX | FRAGMENT 0..64
864// FRAGMENT 64..80
865//
866// We do this so that submission doesn't need to check for overlaps
867// See https://github.com/KhronosGroup/Vulkan-Docs/issues/609
868#[profiling::function]
869fn merge_push_constant_ranges(pcr: &[vk::PushConstantRange]) -> Vec<vk::PushConstantRange> {
870    // Each specified range must be for a single stage and each stage must be specified once
871    #[cfg(feature = "checked")]
872    {
873        let mut stage_flags = vk::ShaderStageFlags::empty();
874        for item in pcr.iter() {
875            assert_eq!(item.stage_flags.as_raw().count_ones(), 1);
876            assert!(!stage_flags.contains(item.stage_flags));
877            assert!(item.size > 0);
878
879            stage_flags |= item.stage_flags;
880        }
881    }
882
883    match pcr.len() {
884        0 => vec![],
885        1 => vec![pcr[0]],
886        _ => {
887            let mut res = pcr.to_vec();
888            let sort_fn = |lhs: &vk::PushConstantRange, rhs: &vk::PushConstantRange| match lhs
889                .offset
890                .cmp(&rhs.offset)
891            {
892                Ordering::Equal => lhs.size.cmp(&rhs.size),
893                res => res,
894            };
895
896            res.sort_unstable_by(sort_fn);
897
898            let mut i = 0;
899            let mut j = 1;
900
901            while j < res.len() {
902                let lhs = res[i];
903                let rhs = res[j];
904
905                if lhs.offset == rhs.offset && lhs.size == rhs.size {
906                    res[i].stage_flags |= rhs.stage_flags;
907                    let _ = res.remove(j);
908                } else if lhs.offset == rhs.offset {
909                    res[i].stage_flags |= rhs.stage_flags;
910                    res[j].offset += lhs.size;
911                    res[j].size -= lhs.size;
912                    res[j..].sort_unstable_by(sort_fn);
913                } else if lhs.offset + lhs.size > rhs.offset + rhs.size {
914                    res[i].size = rhs.offset - lhs.offset;
915                    res[j].stage_flags = lhs.stage_flags;
916                    res[j].offset += rhs.size;
917                    res[j].size = (lhs.offset + lhs.size) - (rhs.offset + rhs.size);
918                    res.insert(
919                        j,
920                        vk::PushConstantRange {
921                            stage_flags: lhs.stage_flags | rhs.stage_flags,
922                            offset: rhs.offset,
923                            size: rhs.size,
924                        },
925                    );
926                    res[j..].sort_unstable_by(sort_fn);
927                    i += 1;
928                    j += 1;
929                } else if lhs.offset + lhs.size == rhs.offset + rhs.size {
930                    res[i].size -= rhs.size;
931                    res[j].stage_flags |= lhs.stage_flags;
932                    i += 1;
933                    j += 1;
934                } else if lhs.offset + lhs.size > rhs.offset
935                    && lhs.offset + lhs.size < rhs.offset + rhs.size
936                {
937                    res[i].size = rhs.offset - lhs.offset;
938                    res[j].offset = lhs.offset + lhs.size;
939                    res[j].size = (rhs.offset + rhs.size) - (lhs.offset + lhs.size);
940                    res.insert(
941                        j,
942                        vk::PushConstantRange {
943                            stage_flags: lhs.stage_flags | rhs.stage_flags,
944                            offset: rhs.offset,
945                            size: (lhs.offset + lhs.size) - rhs.offset,
946                        },
947                    );
948                    res[j..].sort_unstable_by(sort_fn);
949                } else {
950                    i += 1;
951                    j += 1;
952                }
953            }
954
955            res
956        }
957    }
958}
959
960pub(super) const fn pipeline_stage_access_flags(
961    access_type: vk_sync::AccessType,
962) -> (vk::PipelineStageFlags, vk::AccessFlags) {
963    use {
964        vk::{AccessFlags as access, PipelineStageFlags as stage},
965        vk_sync::AccessType as ty,
966    };
967
968    match access_type {
969        ty::Nothing => (stage::empty(), access::empty()),
970        ty::CommandBufferReadNVX => (
971            stage::COMMAND_PREPROCESS_NV,
972            access::COMMAND_PREPROCESS_READ_NV,
973        ),
974        ty::IndirectBuffer => (stage::DRAW_INDIRECT, access::INDIRECT_COMMAND_READ),
975        ty::IndexBuffer => (stage::VERTEX_INPUT, access::INDEX_READ),
976        ty::VertexBuffer => (stage::VERTEX_INPUT, access::VERTEX_ATTRIBUTE_READ),
977        ty::VertexShaderReadUniformBuffer => (stage::VERTEX_SHADER, access::SHADER_READ),
978        ty::VertexShaderReadSampledImageOrUniformTexelBuffer => {
979            (stage::VERTEX_SHADER, access::SHADER_READ)
980        }
981        ty::VertexShaderReadOther => (stage::VERTEX_SHADER, access::SHADER_READ),
982        ty::TessellationControlShaderReadUniformBuffer => {
983            (stage::TESSELLATION_CONTROL_SHADER, access::UNIFORM_READ)
984        }
985        ty::TessellationControlShaderReadSampledImageOrUniformTexelBuffer => {
986            (stage::TESSELLATION_CONTROL_SHADER, access::SHADER_READ)
987        }
988        ty::TessellationControlShaderReadOther => {
989            (stage::TESSELLATION_CONTROL_SHADER, access::SHADER_READ)
990        }
991        ty::TessellationEvaluationShaderReadUniformBuffer => {
992            (stage::TESSELLATION_EVALUATION_SHADER, access::UNIFORM_READ)
993        }
994        ty::TessellationEvaluationShaderReadSampledImageOrUniformTexelBuffer => {
995            (stage::TESSELLATION_EVALUATION_SHADER, access::SHADER_READ)
996        }
997        ty::TessellationEvaluationShaderReadOther => {
998            (stage::TESSELLATION_EVALUATION_SHADER, access::SHADER_READ)
999        }
1000        ty::GeometryShaderReadUniformBuffer => (stage::GEOMETRY_SHADER, access::UNIFORM_READ),
1001        ty::GeometryShaderReadSampledImageOrUniformTexelBuffer => {
1002            (stage::GEOMETRY_SHADER, access::SHADER_READ)
1003        }
1004        ty::GeometryShaderReadOther => (stage::GEOMETRY_SHADER, access::SHADER_READ),
1005        ty::FragmentShaderReadUniformBuffer => (stage::FRAGMENT_SHADER, access::UNIFORM_READ),
1006        ty::FragmentShaderReadSampledImageOrUniformTexelBuffer => {
1007            (stage::FRAGMENT_SHADER, access::SHADER_READ)
1008        }
1009        ty::FragmentShaderReadColorInputAttachment => {
1010            (stage::FRAGMENT_SHADER, access::INPUT_ATTACHMENT_READ)
1011        }
1012        ty::FragmentShaderReadDepthStencilInputAttachment => {
1013            (stage::FRAGMENT_SHADER, access::INPUT_ATTACHMENT_READ)
1014        }
1015        ty::FragmentShaderReadOther => (stage::FRAGMENT_SHADER, access::SHADER_READ),
1016        ty::ColorAttachmentRead => (
1017            stage::COLOR_ATTACHMENT_OUTPUT,
1018            access::COLOR_ATTACHMENT_READ,
1019        ),
1020        ty::DepthStencilAttachmentRead => (
1021            stage::from_raw(
1022                stage::EARLY_FRAGMENT_TESTS.as_raw()
1023                    | vk::PipelineStageFlags::LATE_FRAGMENT_TESTS.as_raw(),
1024            ),
1025            access::DEPTH_STENCIL_ATTACHMENT_READ,
1026        ),
1027        ty::ComputeShaderReadUniformBuffer => (stage::COMPUTE_SHADER, access::UNIFORM_READ),
1028        ty::ComputeShaderReadSampledImageOrUniformTexelBuffer => {
1029            (stage::COMPUTE_SHADER, access::SHADER_READ)
1030        }
1031        ty::ComputeShaderReadOther => (stage::COMPUTE_SHADER, access::SHADER_READ),
1032        ty::AnyShaderReadUniformBuffer => (stage::ALL_COMMANDS, access::UNIFORM_READ),
1033        ty::AnyShaderReadUniformBufferOrVertexBuffer => (
1034            stage::ALL_COMMANDS,
1035            access::from_raw(
1036                access::UNIFORM_READ.as_raw() | vk::AccessFlags::VERTEX_ATTRIBUTE_READ.as_raw(),
1037            ),
1038        ),
1039        ty::AnyShaderReadSampledImageOrUniformTexelBuffer => {
1040            (stage::ALL_COMMANDS, access::SHADER_READ)
1041        }
1042        ty::AnyShaderReadOther => (stage::ALL_COMMANDS, access::SHADER_READ),
1043        ty::TransferRead => (stage::TRANSFER, access::TRANSFER_READ),
1044        ty::HostRead => (stage::HOST, access::HOST_READ),
1045        ty::Present => (stage::empty(), access::empty()),
1046        ty::CommandBufferWriteNVX => (
1047            stage::COMMAND_PREPROCESS_NV,
1048            access::COMMAND_PREPROCESS_WRITE_NV,
1049        ),
1050        ty::VertexShaderWrite => (stage::VERTEX_SHADER, access::SHADER_WRITE),
1051        ty::TessellationControlShaderWrite => {
1052            (stage::TESSELLATION_CONTROL_SHADER, access::SHADER_WRITE)
1053        }
1054        ty::TessellationEvaluationShaderWrite => {
1055            (stage::TESSELLATION_EVALUATION_SHADER, access::SHADER_WRITE)
1056        }
1057        ty::GeometryShaderWrite => (stage::GEOMETRY_SHADER, access::SHADER_WRITE),
1058        ty::FragmentShaderWrite => (stage::FRAGMENT_SHADER, access::SHADER_WRITE),
1059        ty::ColorAttachmentWrite => (
1060            stage::COLOR_ATTACHMENT_OUTPUT,
1061            access::COLOR_ATTACHMENT_WRITE,
1062        ),
1063        ty::DepthStencilAttachmentWrite => (
1064            stage::from_raw(
1065                stage::EARLY_FRAGMENT_TESTS.as_raw()
1066                    | vk::PipelineStageFlags::LATE_FRAGMENT_TESTS.as_raw(),
1067            ),
1068            access::DEPTH_STENCIL_ATTACHMENT_WRITE,
1069        ),
1070        ty::DepthStencilAttachmentReadWrite => (
1071            stage::from_raw(
1072                stage::EARLY_FRAGMENT_TESTS.as_raw()
1073                    | vk::PipelineStageFlags::LATE_FRAGMENT_TESTS.as_raw(),
1074            ),
1075            access::from_raw(
1076                access::DEPTH_STENCIL_ATTACHMENT_WRITE.as_raw()
1077                    | vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ.as_raw(),
1078            ),
1079        ),
1080        ty::DepthAttachmentWriteStencilReadOnly => (
1081            stage::from_raw(
1082                stage::EARLY_FRAGMENT_TESTS.as_raw()
1083                    | vk::PipelineStageFlags::LATE_FRAGMENT_TESTS.as_raw(),
1084            ),
1085            access::from_raw(
1086                access::DEPTH_STENCIL_ATTACHMENT_WRITE.as_raw()
1087                    | vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ.as_raw(),
1088            ),
1089        ),
1090        ty::StencilAttachmentWriteDepthReadOnly => (
1091            stage::from_raw(
1092                stage::EARLY_FRAGMENT_TESTS.as_raw()
1093                    | vk::PipelineStageFlags::LATE_FRAGMENT_TESTS.as_raw(),
1094            ),
1095            access::from_raw(
1096                access::DEPTH_STENCIL_ATTACHMENT_WRITE.as_raw()
1097                    | vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ.as_raw(),
1098            ),
1099        ),
1100        ty::ComputeShaderWrite => (stage::COMPUTE_SHADER, access::SHADER_WRITE),
1101        ty::ComputeShaderReadWrite => (
1102            stage::COMPUTE_SHADER,
1103            access::from_raw(access::SHADER_WRITE.as_raw() | access::SHADER_READ.as_raw()),
1104        ),
1105        ty::AnyShaderWrite => (stage::ALL_COMMANDS, access::SHADER_WRITE),
1106        ty::TransferWrite => (stage::TRANSFER, access::TRANSFER_WRITE),
1107        ty::HostWrite => (stage::HOST, access::HOST_WRITE),
1108        ty::ColorAttachmentReadWrite => (
1109            stage::COLOR_ATTACHMENT_OUTPUT,
1110            access::from_raw(
1111                access::COLOR_ATTACHMENT_READ.as_raw()
1112                    | vk::AccessFlags::COLOR_ATTACHMENT_WRITE.as_raw(),
1113            ),
1114        ),
1115        ty::General => (
1116            stage::ALL_COMMANDS,
1117            access::from_raw(access::MEMORY_READ.as_raw() | vk::AccessFlags::MEMORY_WRITE.as_raw()),
1118        ),
1119        ty::RayTracingShaderReadSampledImageOrUniformTexelBuffer => {
1120            (stage::RAY_TRACING_SHADER_KHR, access::SHADER_READ)
1121        }
1122        ty::RayTracingShaderReadColorInputAttachment => {
1123            (stage::RAY_TRACING_SHADER_KHR, access::INPUT_ATTACHMENT_READ)
1124        }
1125        ty::RayTracingShaderReadDepthStencilInputAttachment => {
1126            (stage::RAY_TRACING_SHADER_KHR, access::INPUT_ATTACHMENT_READ)
1127        }
1128        ty::RayTracingShaderReadAccelerationStructure => (
1129            stage::RAY_TRACING_SHADER_KHR,
1130            access::ACCELERATION_STRUCTURE_READ_KHR,
1131        ),
1132        ty::RayTracingShaderReadOther => (stage::RAY_TRACING_SHADER_KHR, access::SHADER_READ),
1133        ty::AccelerationStructureBuildWrite => (
1134            stage::ACCELERATION_STRUCTURE_BUILD_KHR,
1135            access::ACCELERATION_STRUCTURE_WRITE_KHR,
1136        ),
1137        ty::AccelerationStructureBuildRead => (
1138            stage::ACCELERATION_STRUCTURE_BUILD_KHR,
1139            access::ACCELERATION_STRUCTURE_READ_KHR,
1140        ),
1141        ty::AccelerationStructureBufferWrite => (
1142            stage::ACCELERATION_STRUCTURE_BUILD_KHR,
1143            access::TRANSFER_WRITE,
1144        ),
1145        ty::MeshShaderReadUniformBuffer => (stage::MESH_SHADER_EXT, access::SHADER_READ),
1146        ty::MeshShaderReadSampledImageOrUniformTexelBuffer => {
1147            (stage::MESH_SHADER_EXT, access::SHADER_READ)
1148        }
1149        ty::MeshShaderReadOther => (stage::MESH_SHADER_EXT, access::SHADER_READ),
1150        ty::TaskShaderReadUniformBuffer => (stage::TASK_SHADER_EXT, access::SHADER_READ),
1151        ty::TaskShaderReadSampledImageOrUniformTexelBuffer => {
1152            (stage::TASK_SHADER_EXT, access::SHADER_READ)
1153        }
1154        ty::TaskShaderReadOther => (stage::TASK_SHADER_EXT, access::SHADER_READ),
1155        ty::MeshShaderWrite => (stage::MESH_SHADER_EXT, access::SHADER_WRITE),
1156        ty::TaskShaderWrite => (stage::TASK_SHADER_EXT, access::SHADER_WRITE),
1157    }
1158}
1159
1160/// Describes the general category of all graphics driver failure cases.
1161///
1162/// In the event of a failure you should follow the _vk-graph_ code to the responsible Vulkan API
1163/// and then to the `ash` function call; it will generally contain a link to the appropriate
1164/// specification. The specifications provide a table of possible error conditions which can be a
1165/// good starting point to debug the issue.
1166///
1167/// Feel free to open an [issue on GitHub](https://github.com/attackgoat/vk-graph/issues) for help
1168/// debugging the issue.
1169#[derive(Clone, Copy, Debug)]
1170pub enum DriverError {
1171    /// The input data, or referenced data, is not valid for the current state.
1172    InvalidData,
1173
1174    /// The requested feature, or input configuration, is not supported for the current state.
1175    Unsupported,
1176
1177    /// The device has run out of physical memory.
1178    ///
1179    /// Many drivers return this value for generic or unhandled error conditions.
1180    OutOfMemory,
1181}
1182
1183impl DriverError {
1184    fn from_alloc_err(err: AllocationError) -> Self {
1185        match err {
1186            AllocationError::OutOfMemory => Self::OutOfMemory,
1187            AllocationError::InvalidAllocationCreateDesc
1188            | AllocationError::InvalidAllocatorCreateDesc(_) => Self::InvalidData,
1189            AllocationError::FailedToMap(_)
1190            | AllocationError::NoCompatibleMemoryTypeFound
1191            | AllocationError::Internal(_)
1192            | AllocationError::BarrierLayoutNeedsDevice10
1193            | AllocationError::CastableFormatsRequiresEnhancedBarriers
1194            | AllocationError::CastableFormatsRequiresAtLeastDevice12 => Self::Unsupported,
1195        }
1196    }
1197}
1198
1199impl From<Infallible> for DriverError {
1200    fn from(value: Infallible) -> Self {
1201        match value {}
1202    }
1203}
1204
1205impl Display for DriverError {
1206    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1207        write!(f, "{:?}", self)
1208    }
1209}
1210
1211impl Error for DriverError {}
1212
1213#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1214pub(super) enum SharingMode {
1215    Concurrent,
1216    Exclusive(Option<(u32, u32)>),
1217}
1218
1219impl SharingMode {
1220    const MODE_CONCURRENT: u64 = u64::MAX;
1221    const MODE_UNKNOWN: u64 = u64::MAX - 1;
1222
1223    pub(super) const fn decode(val: u64) -> Self {
1224        if val == Self::MODE_CONCURRENT {
1225            Self::Concurrent
1226        } else if val == Self::MODE_UNKNOWN {
1227            Self::Exclusive(None)
1228        } else {
1229            Self::Exclusive(Some(((val >> 32) as u32, val as u32)))
1230        }
1231    }
1232
1233    pub(super) const fn encode(self) -> u64 {
1234        match self {
1235            SharingMode::Concurrent => Self::MODE_CONCURRENT,
1236            SharingMode::Exclusive(None) => Self::MODE_UNKNOWN,
1237            SharingMode::Exclusive(Some((family, index))) => (family as u64) << 32 | index as u64,
1238        }
1239    }
1240}
1241
1242#[cfg(test)]
1243mod test {
1244    use {super::merge_push_constant_ranges, ash::vk};
1245
1246    macro_rules! assert_pcr_eq {
1247        ($lhs: expr, $rhs: expr,) => {
1248            assert_eq!($lhs.stage_flags, $rhs.stage_flags, "Stages flags not equal");
1249            assert_eq!($lhs.offset, $rhs.offset, "Offset not equal");
1250            assert_eq!($lhs.size, $rhs.size, "Size not equal");
1251        };
1252    }
1253
1254    fn reference_merge_push_constant_ranges(
1255        pcr: &[vk::PushConstantRange],
1256    ) -> Vec<vk::PushConstantRange> {
1257        if pcr.is_empty() {
1258            return vec![];
1259        }
1260        let end = pcr.iter().map(|r| r.offset + r.size).max().unwrap();
1261        let mut per_byte = vec![0u32; end as usize];
1262        for r in pcr {
1263            let raw = r.stage_flags.as_raw();
1264            let range_end = r.offset + r.size;
1265            for byte in per_byte[r.offset as usize..range_end as usize].iter_mut() {
1266                *byte |= raw;
1267            }
1268        }
1269        let mut result = Vec::new();
1270        let mut i = 0usize;
1271        while (i as u32) < end {
1272            let flags = per_byte[i];
1273            if flags == 0 {
1274                i += 1;
1275                continue;
1276            }
1277            let start = i as u32;
1278            while (i as u32) < end && per_byte[i] == flags {
1279                i += 1;
1280            }
1281            result.push(vk::PushConstantRange {
1282                stage_flags: vk::ShaderStageFlags::from_raw(flags),
1283                offset: start,
1284                size: (i as u32) - start,
1285            });
1286        }
1287        result
1288    }
1289
1290    fn assert_merge_invariants(input: &[vk::PushConstantRange], output: &[vk::PushConstantRange]) {
1291        let expected = reference_merge_push_constant_ranges(input);
1292        assert_eq!(
1293            output.len(),
1294            expected.len(),
1295            "length mismatch\n  input: {input:?}\n  got: {output:?}\n  expected: {expected:?}"
1296        );
1297        for (idx, (got, exp)) in output.iter().zip(expected.iter()).enumerate() {
1298            assert_eq!(
1299                got.stage_flags, exp.stage_flags,
1300                "result[{idx}] stage_flags mismatch\n  input: {input:?}\n  got: {output:?}\n  expected: {expected:?}"
1301            );
1302            assert_eq!(
1303                got.offset, exp.offset,
1304                "result[{idx}] offset mismatch\n  input: {input:?}\n  got: {output:?}\n  expected: {expected:?}"
1305            );
1306            assert_eq!(
1307                got.size, exp.size,
1308                "result[{idx}] size mismatch\n  input: {input:?}\n  got: {output:?}\n  expected: {expected:?}"
1309            );
1310        }
1311    }
1312
1313    #[test]
1314    pub fn push_constant_ranges_complex() {
1315        let res = merge_push_constant_ranges(&[
1316            vk::PushConstantRange {
1317                stage_flags: vk::ShaderStageFlags::VERTEX,
1318                offset: 8,
1319                size: 16,
1320            },
1321            vk::PushConstantRange {
1322                stage_flags: vk::ShaderStageFlags::GEOMETRY,
1323                offset: 20,
1324                size: 48,
1325            },
1326            vk::PushConstantRange {
1327                stage_flags: vk::ShaderStageFlags::TESSELLATION_CONTROL,
1328                offset: 24,
1329                size: 8,
1330            },
1331            vk::PushConstantRange {
1332                stage_flags: vk::ShaderStageFlags::TESSELLATION_EVALUATION,
1333                offset: 28,
1334                size: 32,
1335            },
1336            vk::PushConstantRange {
1337                stage_flags: vk::ShaderStageFlags::FRAGMENT,
1338                offset: 40,
1339                size: 128,
1340            },
1341        ]);
1342
1343        assert_eq!(res.len(), 8);
1344        assert_pcr_eq!(
1345            res[0],
1346            vk::PushConstantRange {
1347                stage_flags: vk::ShaderStageFlags::VERTEX,
1348                offset: 8,
1349                size: 12,
1350            },
1351        );
1352        assert_pcr_eq!(
1353            res[1],
1354            vk::PushConstantRange {
1355                stage_flags: vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::GEOMETRY,
1356                offset: 20,
1357                size: 4,
1358            },
1359        );
1360        assert_pcr_eq!(
1361            res[2],
1362            vk::PushConstantRange {
1363                stage_flags: vk::ShaderStageFlags::TESSELLATION_CONTROL
1364                    | vk::ShaderStageFlags::GEOMETRY,
1365                offset: 24,
1366                size: 4,
1367            },
1368        );
1369        assert_pcr_eq!(
1370            res[3],
1371            vk::PushConstantRange {
1372                stage_flags: vk::ShaderStageFlags::TESSELLATION_CONTROL
1373                    | vk::ShaderStageFlags::TESSELLATION_EVALUATION
1374                    | vk::ShaderStageFlags::GEOMETRY,
1375                offset: 28,
1376                size: 4,
1377            },
1378        );
1379        assert_pcr_eq!(
1380            res[4],
1381            vk::PushConstantRange {
1382                stage_flags: vk::ShaderStageFlags::GEOMETRY
1383                    | vk::ShaderStageFlags::TESSELLATION_EVALUATION,
1384                offset: 32,
1385                size: 8,
1386            },
1387        );
1388        assert_pcr_eq!(
1389            res[5],
1390            vk::PushConstantRange {
1391                stage_flags: vk::ShaderStageFlags::GEOMETRY
1392                    | vk::ShaderStageFlags::TESSELLATION_EVALUATION
1393                    | vk::ShaderStageFlags::FRAGMENT,
1394                offset: 40,
1395                size: 20,
1396            },
1397        );
1398        assert_pcr_eq!(
1399            res[6],
1400            vk::PushConstantRange {
1401                stage_flags: vk::ShaderStageFlags::FRAGMENT | vk::ShaderStageFlags::GEOMETRY,
1402                offset: 60,
1403                size: 8,
1404            },
1405        );
1406        assert_pcr_eq!(
1407            res[7],
1408            vk::PushConstantRange {
1409                stage_flags: vk::ShaderStageFlags::FRAGMENT,
1410                offset: 68,
1411                size: 100,
1412            },
1413        );
1414    }
1415
1416    #[test]
1417    pub fn push_constant_ranges_disjoint() {
1418        let res = merge_push_constant_ranges(&[
1419            vk::PushConstantRange {
1420                stage_flags: vk::ShaderStageFlags::VERTEX,
1421                offset: 0,
1422                size: 32,
1423            },
1424            vk::PushConstantRange {
1425                stage_flags: vk::ShaderStageFlags::FRAGMENT,
1426                offset: 32,
1427                size: 64,
1428            },
1429        ]);
1430
1431        assert_eq!(res.len(), 2);
1432        assert_pcr_eq!(
1433            res[0],
1434            vk::PushConstantRange {
1435                stage_flags: vk::ShaderStageFlags::VERTEX,
1436                offset: 0,
1437                size: 32,
1438            },
1439        );
1440        assert_pcr_eq!(
1441            res[1],
1442            vk::PushConstantRange {
1443                stage_flags: vk::ShaderStageFlags::FRAGMENT,
1444                offset: 32,
1445                size: 64,
1446            },
1447        );
1448    }
1449
1450    #[test]
1451    pub fn push_constant_ranges_equal() {
1452        let res = merge_push_constant_ranges(&[
1453            vk::PushConstantRange {
1454                stage_flags: vk::ShaderStageFlags::VERTEX,
1455                offset: 0,
1456                size: 32,
1457            },
1458            vk::PushConstantRange {
1459                stage_flags: vk::ShaderStageFlags::FRAGMENT,
1460                offset: 0,
1461                size: 32,
1462            },
1463        ]);
1464
1465        assert_eq!(res.len(), 1);
1466        assert_pcr_eq!(
1467            res[0],
1468            vk::PushConstantRange {
1469                stage_flags: vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::FRAGMENT,
1470                offset: 0,
1471                size: 32,
1472            },
1473        );
1474    }
1475
1476    #[test]
1477    pub fn push_constant_ranges_overlap() {
1478        let res = merge_push_constant_ranges(&[
1479            vk::PushConstantRange {
1480                stage_flags: vk::ShaderStageFlags::VERTEX,
1481                offset: 0,
1482                size: 24,
1483            },
1484            vk::PushConstantRange {
1485                stage_flags: vk::ShaderStageFlags::GEOMETRY,
1486                offset: 8,
1487                size: 24,
1488            },
1489            vk::PushConstantRange {
1490                stage_flags: vk::ShaderStageFlags::FRAGMENT,
1491                offset: 20,
1492                size: 28,
1493            },
1494        ]);
1495
1496        assert_eq!(res.len(), 5);
1497        assert_pcr_eq!(
1498            res[0],
1499            vk::PushConstantRange {
1500                stage_flags: vk::ShaderStageFlags::VERTEX,
1501                offset: 0,
1502                size: 8,
1503            },
1504        );
1505        assert_pcr_eq!(
1506            res[1],
1507            vk::PushConstantRange {
1508                stage_flags: vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::GEOMETRY,
1509                offset: 8,
1510                size: 12,
1511            },
1512        );
1513        assert_pcr_eq!(
1514            res[2],
1515            vk::PushConstantRange {
1516                stage_flags: vk::ShaderStageFlags::VERTEX
1517                    | vk::ShaderStageFlags::GEOMETRY
1518                    | vk::ShaderStageFlags::FRAGMENT,
1519                offset: 20,
1520                size: 4,
1521            },
1522        );
1523        assert_pcr_eq!(
1524            res[3],
1525            vk::PushConstantRange {
1526                stage_flags: vk::ShaderStageFlags::GEOMETRY | vk::ShaderStageFlags::FRAGMENT,
1527                offset: 24,
1528                size: 8,
1529            },
1530        );
1531        assert_pcr_eq!(
1532            res[4],
1533            vk::PushConstantRange {
1534                stage_flags: vk::ShaderStageFlags::FRAGMENT,
1535                offset: 32,
1536                size: 16,
1537            },
1538        );
1539    }
1540
1541    #[test]
1542    pub fn push_constant_ranges_subset() {
1543        let res = merge_push_constant_ranges(&[
1544            vk::PushConstantRange {
1545                stage_flags: vk::ShaderStageFlags::VERTEX,
1546                offset: 0,
1547                size: 64,
1548            },
1549            vk::PushConstantRange {
1550                stage_flags: vk::ShaderStageFlags::FRAGMENT,
1551                offset: 16,
1552                size: 8,
1553            },
1554        ]);
1555
1556        assert_eq!(res.len(), 3);
1557        assert_pcr_eq!(
1558            res[0],
1559            vk::PushConstantRange {
1560                stage_flags: vk::ShaderStageFlags::VERTEX,
1561                offset: 0,
1562                size: 16,
1563            },
1564        );
1565        assert_pcr_eq!(
1566            res[1],
1567            vk::PushConstantRange {
1568                stage_flags: vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::FRAGMENT,
1569                offset: 16,
1570                size: 8,
1571            },
1572        );
1573        assert_pcr_eq!(
1574            res[2],
1575            vk::PushConstantRange {
1576                stage_flags: vk::ShaderStageFlags::VERTEX,
1577                offset: 24,
1578                size: 40,
1579            },
1580        );
1581    }
1582
1583    #[test]
1584    pub fn push_constant_ranges_superset() {
1585        let res = merge_push_constant_ranges(&[
1586            vk::PushConstantRange {
1587                stage_flags: vk::ShaderStageFlags::VERTEX,
1588                offset: 0,
1589                size: 64,
1590            },
1591            vk::PushConstantRange {
1592                stage_flags: vk::ShaderStageFlags::FRAGMENT,
1593                offset: 0,
1594                size: 80,
1595            },
1596        ]);
1597
1598        assert_eq!(res.len(), 2);
1599        assert_pcr_eq!(
1600            res[0],
1601            vk::PushConstantRange {
1602                stage_flags: vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::FRAGMENT,
1603                offset: 0,
1604                size: 64,
1605            },
1606        );
1607        assert_pcr_eq!(
1608            res[1],
1609            vk::PushConstantRange {
1610                stage_flags: vk::ShaderStageFlags::FRAGMENT,
1611                offset: 64,
1612                size: 16,
1613            },
1614        );
1615    }
1616
1617    #[test]
1618    pub fn push_constant_ranges_single() {
1619        let input = [vk::PushConstantRange {
1620            stage_flags: vk::ShaderStageFlags::VERTEX,
1621            offset: 16,
1622            size: 32,
1623        }];
1624        let res = merge_push_constant_ranges(&input);
1625        assert_eq!(res.len(), 1);
1626        assert_pcr_eq!(
1627            res[0],
1628            vk::PushConstantRange {
1629                stage_flags: vk::ShaderStageFlags::VERTEX,
1630                offset: 16,
1631                size: 32,
1632            },
1633        );
1634        assert_merge_invariants(&input, &res);
1635    }
1636
1637    #[test]
1638    pub fn push_constant_ranges_three_identical() {
1639        let input = [
1640            vk::PushConstantRange {
1641                stage_flags: vk::ShaderStageFlags::VERTEX,
1642                offset: 0,
1643                size: 32,
1644            },
1645            vk::PushConstantRange {
1646                stage_flags: vk::ShaderStageFlags::FRAGMENT,
1647                offset: 0,
1648                size: 32,
1649            },
1650            vk::PushConstantRange {
1651                stage_flags: vk::ShaderStageFlags::COMPUTE,
1652                offset: 0,
1653                size: 32,
1654            },
1655        ];
1656        let res = merge_push_constant_ranges(&input);
1657        assert_eq!(res.len(), 1);
1658        assert_pcr_eq!(
1659            res[0],
1660            vk::PushConstantRange {
1661                stage_flags: vk::ShaderStageFlags::VERTEX
1662                    | vk::ShaderStageFlags::FRAGMENT
1663                    | vk::ShaderStageFlags::COMPUTE,
1664                offset: 0,
1665                size: 32,
1666            },
1667        );
1668        assert_merge_invariants(&input, &res);
1669    }
1670
1671    #[test]
1672    pub fn push_constant_ranges_three_same_offset() {
1673        let input = [
1674            vk::PushConstantRange {
1675                stage_flags: vk::ShaderStageFlags::VERTEX,
1676                offset: 0,
1677                size: 8,
1678            },
1679            vk::PushConstantRange {
1680                stage_flags: vk::ShaderStageFlags::FRAGMENT,
1681                offset: 0,
1682                size: 16,
1683            },
1684            vk::PushConstantRange {
1685                stage_flags: vk::ShaderStageFlags::COMPUTE,
1686                offset: 0,
1687                size: 32,
1688            },
1689        ];
1690        let res = merge_push_constant_ranges(&input);
1691        assert_eq!(res.len(), 3);
1692        assert_pcr_eq!(
1693            res[0],
1694            vk::PushConstantRange {
1695                stage_flags: vk::ShaderStageFlags::VERTEX
1696                    | vk::ShaderStageFlags::FRAGMENT
1697                    | vk::ShaderStageFlags::COMPUTE,
1698                offset: 0,
1699                size: 8,
1700            },
1701        );
1702        assert_pcr_eq!(
1703            res[1],
1704            vk::PushConstantRange {
1705                stage_flags: vk::ShaderStageFlags::FRAGMENT | vk::ShaderStageFlags::COMPUTE,
1706                offset: 8,
1707                size: 8,
1708            },
1709        );
1710        assert_pcr_eq!(
1711            res[2],
1712            vk::PushConstantRange {
1713                stage_flags: vk::ShaderStageFlags::COMPUTE,
1714                offset: 16,
1715                size: 16,
1716            },
1717        );
1718        assert_merge_invariants(&input, &res);
1719    }
1720
1721    #[test]
1722    pub fn push_constant_ranges_nested_chain() {
1723        let input = [
1724            vk::PushConstantRange {
1725                stage_flags: vk::ShaderStageFlags::VERTEX,
1726                offset: 0,
1727                size: 64,
1728            },
1729            vk::PushConstantRange {
1730                stage_flags: vk::ShaderStageFlags::FRAGMENT,
1731                offset: 8,
1732                size: 48,
1733            },
1734            vk::PushConstantRange {
1735                stage_flags: vk::ShaderStageFlags::COMPUTE,
1736                offset: 16,
1737                size: 32,
1738            },
1739        ];
1740        let res = merge_push_constant_ranges(&input);
1741        assert_eq!(res.len(), 5);
1742        assert_pcr_eq!(
1743            res[0],
1744            vk::PushConstantRange {
1745                stage_flags: vk::ShaderStageFlags::VERTEX,
1746                offset: 0,
1747                size: 8,
1748            },
1749        );
1750        assert_pcr_eq!(
1751            res[1],
1752            vk::PushConstantRange {
1753                stage_flags: vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::FRAGMENT,
1754                offset: 8,
1755                size: 8,
1756            },
1757        );
1758        assert_pcr_eq!(
1759            res[2],
1760            vk::PushConstantRange {
1761                stage_flags: vk::ShaderStageFlags::VERTEX
1762                    | vk::ShaderStageFlags::FRAGMENT
1763                    | vk::ShaderStageFlags::COMPUTE,
1764                offset: 16,
1765                size: 32,
1766            },
1767        );
1768        assert_pcr_eq!(
1769            res[3],
1770            vk::PushConstantRange {
1771                stage_flags: vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::FRAGMENT,
1772                offset: 48,
1773                size: 8,
1774            },
1775        );
1776        assert_pcr_eq!(
1777            res[4],
1778            vk::PushConstantRange {
1779                stage_flags: vk::ShaderStageFlags::VERTEX,
1780                offset: 56,
1781                size: 8,
1782            },
1783        );
1784        assert_merge_invariants(&input, &res);
1785    }
1786
1787    #[test]
1788    pub fn push_constant_ranges_touching() {
1789        let input = [
1790            vk::PushConstantRange {
1791                stage_flags: vk::ShaderStageFlags::VERTEX,
1792                offset: 0,
1793                size: 16,
1794            },
1795            vk::PushConstantRange {
1796                stage_flags: vk::ShaderStageFlags::FRAGMENT,
1797                offset: 16,
1798                size: 16,
1799            },
1800            vk::PushConstantRange {
1801                stage_flags: vk::ShaderStageFlags::COMPUTE,
1802                offset: 32,
1803                size: 16,
1804            },
1805        ];
1806        let res = merge_push_constant_ranges(&input);
1807        assert_eq!(res.len(), 3);
1808        assert_pcr_eq!(
1809            res[0],
1810            vk::PushConstantRange {
1811                stage_flags: vk::ShaderStageFlags::VERTEX,
1812                offset: 0,
1813                size: 16,
1814            },
1815        );
1816        assert_pcr_eq!(
1817            res[1],
1818            vk::PushConstantRange {
1819                stage_flags: vk::ShaderStageFlags::FRAGMENT,
1820                offset: 16,
1821                size: 16,
1822            },
1823        );
1824        assert_pcr_eq!(
1825            res[2],
1826            vk::PushConstantRange {
1827                stage_flags: vk::ShaderStageFlags::COMPUTE,
1828                offset: 32,
1829                size: 16,
1830            },
1831        );
1832        assert_merge_invariants(&input, &res);
1833    }
1834
1835    #[test]
1836    pub fn push_constant_ranges_complex_interleave() {
1837        let input = [
1838            vk::PushConstantRange {
1839                stage_flags: vk::ShaderStageFlags::VERTEX,
1840                offset: 0,
1841                size: 24,
1842            },
1843            vk::PushConstantRange {
1844                stage_flags: vk::ShaderStageFlags::GEOMETRY,
1845                offset: 8,
1846                size: 24,
1847            },
1848            vk::PushConstantRange {
1849                stage_flags: vk::ShaderStageFlags::COMPUTE,
1850                offset: 16,
1851                size: 24,
1852            },
1853            vk::PushConstantRange {
1854                stage_flags: vk::ShaderStageFlags::FRAGMENT,
1855                offset: 32,
1856                size: 24,
1857            },
1858        ];
1859        let res = merge_push_constant_ranges(&input);
1860        assert_eq!(res.len(), 6);
1861        assert_pcr_eq!(
1862            res[0],
1863            vk::PushConstantRange {
1864                stage_flags: vk::ShaderStageFlags::VERTEX,
1865                offset: 0,
1866                size: 8,
1867            },
1868        );
1869        assert_pcr_eq!(
1870            res[1],
1871            vk::PushConstantRange {
1872                stage_flags: vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::GEOMETRY,
1873                offset: 8,
1874                size: 8,
1875            },
1876        );
1877        assert_pcr_eq!(
1878            res[2],
1879            vk::PushConstantRange {
1880                stage_flags: vk::ShaderStageFlags::VERTEX
1881                    | vk::ShaderStageFlags::GEOMETRY
1882                    | vk::ShaderStageFlags::COMPUTE,
1883                offset: 16,
1884                size: 8,
1885            },
1886        );
1887        assert_pcr_eq!(
1888            res[3],
1889            vk::PushConstantRange {
1890                stage_flags: vk::ShaderStageFlags::GEOMETRY | vk::ShaderStageFlags::COMPUTE,
1891                offset: 24,
1892                size: 8,
1893            },
1894        );
1895        assert_pcr_eq!(
1896            res[4],
1897            vk::PushConstantRange {
1898                stage_flags: vk::ShaderStageFlags::COMPUTE | vk::ShaderStageFlags::FRAGMENT,
1899                offset: 32,
1900                size: 8,
1901            },
1902        );
1903        assert_pcr_eq!(
1904            res[5],
1905            vk::PushConstantRange {
1906                stage_flags: vk::ShaderStageFlags::FRAGMENT,
1907                offset: 40,
1908                size: 16,
1909            },
1910        );
1911        assert_merge_invariants(&input, &res);
1912    }
1913
1914    #[test]
1915    pub fn push_constant_ranges_fuzz() {
1916        use rand::Rng;
1917        use rand::SeedableRng;
1918        use rand::rngs::StdRng;
1919
1920        let stages = [
1921            vk::ShaderStageFlags::VERTEX,
1922            vk::ShaderStageFlags::FRAGMENT,
1923            vk::ShaderStageFlags::GEOMETRY,
1924            vk::ShaderStageFlags::TESSELLATION_CONTROL,
1925            vk::ShaderStageFlags::TESSELLATION_EVALUATION,
1926            vk::ShaderStageFlags::COMPUTE,
1927        ];
1928
1929        for seed in 0..10000 {
1930            let mut rng = StdRng::seed_from_u64(seed);
1931            let count = rng.random_range(0..=stages.len());
1932
1933            let mut available: Vec<usize> = (0..stages.len()).collect();
1934            for i in (1..available.len()).rev() {
1935                let j = rng.random_range(0..=i);
1936                available.swap(i, j);
1937            }
1938
1939            let input: Vec<vk::PushConstantRange> = available
1940                .iter()
1941                .take(count)
1942                .map(|&idx| {
1943                    let offset = rng.random_range(0u32..128);
1944                    let size = rng.random_range(1u32..64);
1945                    vk::PushConstantRange {
1946                        stage_flags: stages[idx],
1947                        offset,
1948                        size,
1949                    }
1950                })
1951                .collect();
1952
1953            let result = merge_push_constant_ranges(&input);
1954            assert_merge_invariants(&input, &result);
1955        }
1956    }
1957}