screen_13/driver/
mod.rs

1//! [Vulkan 1.2](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/index.html) interface
2//! based on smart pointers.
3//!
4//! # Resources
5//!
6//! Each resource contains an opaque Vulkan object handle and an information structure which
7//! describes the object. Resources also contain an atomic [`AccessType`] state value which is used to
8//! maintain consistency in any system which accesses the resource.
9//!
10//! The following resources are available:
11//!
12//! - [`AccelerationStructure`](accel_struct::AccelerationStructure)
13//! - [`Buffer`]
14//! - [`Image`](image::Image)
15//!
16//! # Pipelines
17//!
18//! Pipelines allow you to run shader code which read and write resources using graphics hardware.
19//!
20//! Each pipeline contains an opaque Vulkan object handle and an information structure which
21//! describes the configuration and shaders. They are immutable once created.
22//!
23//! The following pipelines are available:
24//!
25//! - [`ComputePipeline`](compute::ComputePipeline)
26//! - [`GraphicPipeline`]
27//! - [`RayTracePipeline`](ray_trace::RayTracePipeline)
28
29pub mod accel_struct;
30pub mod buffer;
31pub mod compute;
32pub mod device;
33pub mod graphic;
34pub mod image;
35pub mod physical_device;
36pub mod ray_trace;
37pub mod render_pass;
38pub mod shader;
39pub mod surface;
40pub mod swapchain;
41
42mod cmd_buf;
43mod descriptor_set;
44mod descriptor_set_layout;
45mod instance;
46
47// HACK: Custom vk-sync until a fork is published or PRs get merged
48#[allow(unused)]
49#[path = "../../contrib/vk-sync/src/lib.rs"]
50pub(crate) mod vk_sync;
51
52pub use {
53    self::{cmd_buf::CommandBuffer, instance::Instance},
54    ash::{self},
55    vk_sync::AccessType,
56};
57
58/// Specifying depth and stencil resolve modes.
59#[deprecated = "Use driver::render_pass::ResolveMode instead"]
60pub type ResolveMode = self::render_pass::ResolveMode;
61
62pub(crate) use self::{
63    cmd_buf::CommandBufferInfo,
64    descriptor_set::{DescriptorPool, DescriptorPoolInfo, DescriptorSet},
65    descriptor_set_layout::DescriptorSetLayout,
66    render_pass::{
67        AttachmentInfo, AttachmentRef, FramebufferAttachmentImageInfo, FramebufferInfo, RenderPass,
68        RenderPassInfo, SubpassDependency, SubpassInfo,
69    },
70    shader::{Descriptor, DescriptorBindingMap, DescriptorInfo},
71    surface::Surface,
72};
73
74use {
75    self::{
76        buffer::{Buffer, BufferInfo},
77        graphic::{DepthStencilMode, GraphicPipeline, VertexInputState},
78        image::SampleCount,
79    },
80    ash::vk,
81    std::{
82        cmp::Ordering,
83        error::Error,
84        fmt::{Display, Formatter},
85    },
86    vk_sync::ImageLayout,
87};
88
89pub(super) const fn format_aspect_mask(fmt: vk::Format) -> vk::ImageAspectFlags {
90    match fmt {
91        vk::Format::D16_UNORM | vk::Format::D32_SFLOAT | vk::Format::X8_D24_UNORM_PACK32 => {
92            vk::ImageAspectFlags::DEPTH
93        }
94        vk::Format::S8_UINT => vk::ImageAspectFlags::STENCIL,
95        vk::Format::D16_UNORM_S8_UINT
96        | vk::Format::D24_UNORM_S8_UINT
97        | vk::Format::D32_SFLOAT_S8_UINT => vk::ImageAspectFlags::from_raw(
98            vk::ImageAspectFlags::DEPTH.as_raw() | vk::ImageAspectFlags::STENCIL.as_raw(),
99        ),
100        _ => vk::ImageAspectFlags::COLOR,
101    }
102}
103
104/// See [Representation and Texel Block Size](https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#texel-block-size)
105pub const fn format_texel_block_size(fmt: vk::Format) -> u32 {
106    match fmt {
107        vk::Format::R4G4_UNORM_PACK8
108        | vk::Format::R8_UNORM
109        | vk::Format::R8_SNORM
110        | vk::Format::R8_USCALED
111        | vk::Format::R8_SSCALED
112        | vk::Format::R8_UINT
113        | vk::Format::R8_SINT
114        | vk::Format::R8_SRGB => 1,
115        vk::Format::A1B5G5R5_UNORM_PACK16_KHR
116        | vk::Format::R10X6_UNORM_PACK16
117        | vk::Format::R12X4_UNORM_PACK16
118        | vk::Format::A4R4G4B4_UNORM_PACK16
119        | vk::Format::A4B4G4R4_UNORM_PACK16
120        | vk::Format::R4G4B4A4_UNORM_PACK16
121        | vk::Format::B4G4R4A4_UNORM_PACK16
122        | vk::Format::R5G6B5_UNORM_PACK16
123        | vk::Format::B5G6R5_UNORM_PACK16
124        | vk::Format::R5G5B5A1_UNORM_PACK16
125        | vk::Format::B5G5R5A1_UNORM_PACK16
126        | vk::Format::A1R5G5B5_UNORM_PACK16
127        | vk::Format::R8G8_UNORM
128        | vk::Format::R8G8_SNORM
129        | vk::Format::R8G8_USCALED
130        | vk::Format::R8G8_SSCALED
131        | vk::Format::R8G8_UINT
132        | vk::Format::R8G8_SINT
133        | vk::Format::R8G8_SRGB
134        | vk::Format::R16_UNORM
135        | vk::Format::R16_SNORM
136        | vk::Format::R16_USCALED
137        | vk::Format::R16_SSCALED
138        | vk::Format::R16_UINT
139        | vk::Format::R16_SINT
140        | vk::Format::R16_SFLOAT => 2,
141        vk::Format::A8_UNORM_KHR => 1,
142        vk::Format::R8G8B8_UNORM
143        | vk::Format::R8G8B8_SNORM
144        | vk::Format::R8G8B8_USCALED
145        | vk::Format::R8G8B8_SSCALED
146        | vk::Format::R8G8B8_UINT
147        | vk::Format::R8G8B8_SINT
148        | vk::Format::R8G8B8_SRGB
149        | vk::Format::B8G8R8_UNORM
150        | vk::Format::B8G8R8_SNORM
151        | vk::Format::B8G8R8_USCALED
152        | vk::Format::B8G8R8_SSCALED
153        | vk::Format::B8G8R8_UINT
154        | vk::Format::B8G8R8_SINT
155        | vk::Format::B8G8R8_SRGB => 3,
156        vk::Format::R10X6G10X6_UNORM_2PACK16
157        | vk::Format::R12X4G12X4_UNORM_2PACK16
158        | vk::Format::R16G16_S10_5_NV
159        | vk::Format::R8G8B8A8_UNORM
160        | vk::Format::R8G8B8A8_SNORM
161        | vk::Format::R8G8B8A8_USCALED
162        | vk::Format::R8G8B8A8_SSCALED
163        | vk::Format::R8G8B8A8_UINT
164        | vk::Format::R8G8B8A8_SINT
165        | vk::Format::R8G8B8A8_SRGB
166        | vk::Format::B8G8R8A8_UNORM
167        | vk::Format::B8G8R8A8_SNORM
168        | vk::Format::B8G8R8A8_USCALED
169        | vk::Format::B8G8R8A8_SSCALED
170        | vk::Format::B8G8R8A8_UINT
171        | vk::Format::B8G8R8A8_SINT
172        | vk::Format::B8G8R8A8_SRGB
173        | vk::Format::A8B8G8R8_UNORM_PACK32
174        | vk::Format::A8B8G8R8_SNORM_PACK32
175        | vk::Format::A8B8G8R8_USCALED_PACK32
176        | vk::Format::A8B8G8R8_SSCALED_PACK32
177        | vk::Format::A8B8G8R8_UINT_PACK32
178        | vk::Format::A8B8G8R8_SINT_PACK32
179        | vk::Format::A8B8G8R8_SRGB_PACK32
180        | vk::Format::A2R10G10B10_UNORM_PACK32
181        | vk::Format::A2R10G10B10_SNORM_PACK32
182        | vk::Format::A2R10G10B10_USCALED_PACK32
183        | vk::Format::A2R10G10B10_SSCALED_PACK32
184        | vk::Format::A2R10G10B10_UINT_PACK32
185        | vk::Format::A2R10G10B10_SINT_PACK32
186        | vk::Format::A2B10G10R10_UNORM_PACK32
187        | vk::Format::A2B10G10R10_SNORM_PACK32
188        | vk::Format::A2B10G10R10_USCALED_PACK32
189        | vk::Format::A2B10G10R10_SSCALED_PACK32
190        | vk::Format::A2B10G10R10_UINT_PACK32
191        | vk::Format::A2B10G10R10_SINT_PACK32
192        | vk::Format::R16G16_UNORM
193        | vk::Format::R16G16_SNORM
194        | vk::Format::R16G16_USCALED
195        | vk::Format::R16G16_SSCALED
196        | vk::Format::R16G16_UINT
197        | vk::Format::R16G16_SINT
198        | vk::Format::R16G16_SFLOAT
199        | vk::Format::R32_UINT
200        | vk::Format::R32_SINT
201        | vk::Format::R32_SFLOAT
202        | vk::Format::B10G11R11_UFLOAT_PACK32
203        | vk::Format::E5B9G9R9_UFLOAT_PACK32 => 4,
204        vk::Format::R16G16B16_UNORM
205        | vk::Format::R16G16B16_SNORM
206        | vk::Format::R16G16B16_USCALED
207        | vk::Format::R16G16B16_SSCALED
208        | vk::Format::R16G16B16_UINT
209        | vk::Format::R16G16B16_SINT
210        | vk::Format::R16G16B16_SFLOAT => 6,
211        vk::Format::R16G16B16A16_UNORM
212        | vk::Format::R16G16B16A16_SNORM
213        | vk::Format::R16G16B16A16_USCALED
214        | vk::Format::R16G16B16A16_SSCALED
215        | vk::Format::R16G16B16A16_UINT
216        | vk::Format::R16G16B16A16_SINT
217        | vk::Format::R16G16B16A16_SFLOAT
218        | vk::Format::R32G32_UINT
219        | vk::Format::R32G32_SINT
220        | vk::Format::R32G32_SFLOAT
221        | vk::Format::R64_UINT
222        | vk::Format::R64_SINT
223        | vk::Format::R64_SFLOAT => 8,
224        vk::Format::R32G32B32_UINT | vk::Format::R32G32B32_SINT | vk::Format::R32G32B32_SFLOAT => {
225            12
226        }
227        vk::Format::R32G32B32A32_UINT
228        | vk::Format::R32G32B32A32_SINT
229        | vk::Format::R32G32B32A32_SFLOAT
230        | vk::Format::R64G64_UINT
231        | vk::Format::R64G64_SINT
232        | vk::Format::R64G64_SFLOAT => 16,
233        vk::Format::R64G64B64_UINT | vk::Format::R64G64B64_SINT | vk::Format::R64G64B64_SFLOAT => {
234            24
235        }
236        vk::Format::R64G64B64A64_UINT
237        | vk::Format::R64G64B64A64_SINT
238        | vk::Format::R64G64B64A64_SFLOAT => 32,
239        vk::Format::D16_UNORM => 2,
240        vk::Format::X8_D24_UNORM_PACK32 => 4,
241        vk::Format::D32_SFLOAT => 4,
242        vk::Format::S8_UINT => 1,
243        vk::Format::D16_UNORM_S8_UINT => 3,
244        vk::Format::D24_UNORM_S8_UINT => 4,
245        vk::Format::D32_SFLOAT_S8_UINT => 5,
246        _ => {
247            // Remaining formats should be implemented in the future
248            unimplemented!()
249        }
250    }
251}
252
253pub(super) const fn image_subresource_range_from_layers(
254    vk::ImageSubresourceLayers {
255        aspect_mask,
256        mip_level,
257        base_array_layer,
258        layer_count,
259    }: vk::ImageSubresourceLayers,
260) -> vk::ImageSubresourceRange {
261    vk::ImageSubresourceRange {
262        aspect_mask,
263        base_mip_level: mip_level,
264        level_count: 1,
265        base_array_layer,
266        layer_count,
267    }
268}
269
270pub(super) const fn image_access_layout(access: AccessType) -> ImageLayout {
271    if matches!(access, AccessType::Present | AccessType::ComputeShaderWrite) {
272        ImageLayout::General
273    } else {
274        ImageLayout::Optimal
275    }
276}
277
278pub(super) const fn initial_image_layout_access(ty: AccessType) -> AccessType {
279    use AccessType::*;
280    match ty {
281        DepthStencilAttachmentReadWrite => DepthStencilAttachmentRead,
282        _ => ty,
283    }
284}
285
286pub(super) const fn is_read_access(ty: AccessType) -> bool {
287    !is_write_access(ty)
288}
289
290pub(super) const fn is_write_access(ty: AccessType) -> bool {
291    use AccessType::*;
292    match ty {
293        Nothing
294        | CommandBufferReadNVX
295        | IndirectBuffer
296        | IndexBuffer
297        | VertexBuffer
298        | VertexShaderReadUniformBuffer
299        | VertexShaderReadSampledImageOrUniformTexelBuffer
300        | VertexShaderReadOther
301        | TessellationControlShaderReadUniformBuffer
302        | TessellationControlShaderReadSampledImageOrUniformTexelBuffer
303        | TessellationControlShaderReadOther
304        | TessellationEvaluationShaderReadUniformBuffer
305        | TessellationEvaluationShaderReadSampledImageOrUniformTexelBuffer
306        | TessellationEvaluationShaderReadOther
307        | GeometryShaderReadUniformBuffer
308        | GeometryShaderReadSampledImageOrUniformTexelBuffer
309        | GeometryShaderReadOther
310        | FragmentShaderReadUniformBuffer
311        | FragmentShaderReadSampledImageOrUniformTexelBuffer
312        | FragmentShaderReadColorInputAttachment
313        | FragmentShaderReadDepthStencilInputAttachment
314        | FragmentShaderReadOther
315        | ColorAttachmentRead
316        | DepthStencilAttachmentRead
317        | ComputeShaderReadUniformBuffer
318        | ComputeShaderReadSampledImageOrUniformTexelBuffer
319        | ComputeShaderReadOther
320        | AnyShaderReadUniformBuffer
321        | AnyShaderReadUniformBufferOrVertexBuffer
322        | AnyShaderReadSampledImageOrUniformTexelBuffer
323        | AnyShaderReadOther
324        | TransferRead
325        | HostRead
326        | Present
327        | RayTracingShaderReadSampledImageOrUniformTexelBuffer
328        | RayTracingShaderReadColorInputAttachment
329        | RayTracingShaderReadDepthStencilInputAttachment
330        | RayTracingShaderReadAccelerationStructure
331        | RayTracingShaderReadOther
332        | AccelerationStructureBuildRead => false,
333        CommandBufferWriteNVX
334        | VertexShaderWrite
335        | TessellationControlShaderWrite
336        | TessellationEvaluationShaderWrite
337        | GeometryShaderWrite
338        | FragmentShaderWrite
339        | ColorAttachmentWrite
340        | DepthStencilAttachmentWrite
341        | DepthStencilAttachmentReadWrite
342        | DepthAttachmentWriteStencilReadOnly
343        | StencilAttachmentWriteDepthReadOnly
344        | ComputeShaderWrite
345        | AnyShaderWrite
346        | TransferWrite
347        | HostWrite
348        | ColorAttachmentReadWrite
349        | General
350        | AccelerationStructureBuildWrite
351        | AccelerationStructureBufferWrite
352        | ComputeShaderReadWrite => true,
353    }
354}
355
356// Convert overlapping push constant regions such as this:
357// VERTEX 0..64
358// FRAGMENT 0..80
359//
360// To this:
361// VERTEX | FRAGMENT 0..64
362// FRAGMENT 64..80
363//
364// We do this so that submission doesn't need to check for overlaps
365// See https://github.com/KhronosGroup/Vulkan-Docs/issues/609
366#[profiling::function]
367fn merge_push_constant_ranges(pcr: &[vk::PushConstantRange]) -> Vec<vk::PushConstantRange> {
368    // Each specified range must be for a single stage and each stage must be specified once
369    #[cfg(debug_assertions)]
370    {
371        let mut stage_flags = vk::ShaderStageFlags::empty();
372        for item in pcr.iter() {
373            assert_eq!(item.stage_flags.as_raw().count_ones(), 1);
374            assert!(!stage_flags.contains(item.stage_flags));
375            assert!(item.size > 0);
376
377            stage_flags |= item.stage_flags;
378        }
379    }
380
381    match pcr.len() {
382        0 => vec![],
383        1 => vec![pcr[0]],
384        _ => {
385            let mut res = pcr.to_vec();
386            let sort_fn = |lhs: &vk::PushConstantRange, rhs: &vk::PushConstantRange| match lhs
387                .offset
388                .cmp(&rhs.offset)
389            {
390                Ordering::Equal => lhs.size.cmp(&rhs.size),
391                res => res,
392            };
393
394            res.sort_unstable_by(sort_fn);
395
396            let mut i = 0;
397            let mut j = 1;
398
399            while j < res.len() {
400                let lhs = res[i];
401                let rhs = res[j];
402
403                if lhs.offset == rhs.offset && lhs.size == rhs.size {
404                    res[i].stage_flags |= rhs.stage_flags;
405                    let _ = res.remove(j);
406                } else if lhs.offset == rhs.offset {
407                    res[i].stage_flags |= rhs.stage_flags;
408                    res[j].offset += lhs.size;
409                    res[j].size -= lhs.size;
410                    res[j..].sort_unstable_by(sort_fn);
411                } else if lhs.offset + lhs.size > rhs.offset + rhs.size {
412                    res[i].size = rhs.offset - lhs.offset;
413                    res[j].stage_flags = lhs.stage_flags;
414                    res[j].offset += rhs.size;
415                    res[j].size = (lhs.offset + lhs.size) - (rhs.offset + rhs.size);
416                    res.insert(
417                        j,
418                        vk::PushConstantRange {
419                            stage_flags: lhs.stage_flags | rhs.stage_flags,
420                            offset: rhs.offset,
421                            size: rhs.size,
422                        },
423                    );
424                    i += 1;
425                    j += 1;
426                } else if lhs.offset + lhs.size == rhs.offset + rhs.size {
427                    res[i].size -= rhs.size;
428                    res[j].stage_flags |= lhs.stage_flags;
429                    i += 1;
430                    j += 1;
431                } else if lhs.offset + lhs.size > rhs.offset
432                    && lhs.offset + lhs.size < rhs.offset + rhs.size
433                {
434                    res[i].size = rhs.offset - lhs.offset;
435                    res[j].offset = lhs.offset + lhs.size;
436                    res[j].size = (rhs.offset + rhs.size) - (lhs.offset + lhs.size);
437                    res.insert(
438                        j,
439                        vk::PushConstantRange {
440                            stage_flags: lhs.stage_flags | rhs.stage_flags,
441                            offset: rhs.offset,
442                            size: (lhs.offset + lhs.size) - rhs.offset,
443                        },
444                    );
445                    res[j..].sort_unstable_by(sort_fn);
446                } else {
447                    i += 1;
448                    j += 1;
449                }
450            }
451
452            res
453        }
454    }
455}
456
457pub(super) const fn pipeline_stage_access_flags(
458    access_type: AccessType,
459) -> (vk::PipelineStageFlags, vk::AccessFlags) {
460    use {
461        AccessType as ty,
462        vk::{AccessFlags as access, PipelineStageFlags as stage},
463    };
464
465    match access_type {
466        ty::Nothing => (stage::empty(), access::empty()),
467        ty::CommandBufferReadNVX => (
468            stage::COMMAND_PREPROCESS_NV,
469            access::COMMAND_PREPROCESS_READ_NV,
470        ),
471        ty::IndirectBuffer => (stage::DRAW_INDIRECT, access::INDIRECT_COMMAND_READ),
472        ty::IndexBuffer => (stage::VERTEX_INPUT, access::INDEX_READ),
473        ty::VertexBuffer => (stage::VERTEX_INPUT, access::VERTEX_ATTRIBUTE_READ),
474        ty::VertexShaderReadUniformBuffer => (stage::VERTEX_SHADER, access::SHADER_READ),
475        ty::VertexShaderReadSampledImageOrUniformTexelBuffer => {
476            (stage::VERTEX_SHADER, access::SHADER_READ)
477        }
478        ty::VertexShaderReadOther => (stage::VERTEX_SHADER, access::SHADER_READ),
479        ty::TessellationControlShaderReadUniformBuffer => {
480            (stage::TESSELLATION_CONTROL_SHADER, access::UNIFORM_READ)
481        }
482        ty::TessellationControlShaderReadSampledImageOrUniformTexelBuffer => {
483            (stage::TESSELLATION_CONTROL_SHADER, access::SHADER_READ)
484        }
485        ty::TessellationControlShaderReadOther => {
486            (stage::TESSELLATION_CONTROL_SHADER, access::SHADER_READ)
487        }
488        ty::TessellationEvaluationShaderReadUniformBuffer => {
489            (stage::TESSELLATION_EVALUATION_SHADER, access::UNIFORM_READ)
490        }
491        ty::TessellationEvaluationShaderReadSampledImageOrUniformTexelBuffer => {
492            (stage::TESSELLATION_EVALUATION_SHADER, access::SHADER_READ)
493        }
494        ty::TessellationEvaluationShaderReadOther => {
495            (stage::TESSELLATION_EVALUATION_SHADER, access::SHADER_READ)
496        }
497        ty::GeometryShaderReadUniformBuffer => (stage::GEOMETRY_SHADER, access::UNIFORM_READ),
498        ty::GeometryShaderReadSampledImageOrUniformTexelBuffer => {
499            (stage::GEOMETRY_SHADER, access::SHADER_READ)
500        }
501        ty::GeometryShaderReadOther => (stage::GEOMETRY_SHADER, access::SHADER_READ),
502        ty::FragmentShaderReadUniformBuffer => (stage::FRAGMENT_SHADER, access::UNIFORM_READ),
503        ty::FragmentShaderReadSampledImageOrUniformTexelBuffer => {
504            (stage::FRAGMENT_SHADER, access::SHADER_READ)
505        }
506        ty::FragmentShaderReadColorInputAttachment => {
507            (stage::FRAGMENT_SHADER, access::INPUT_ATTACHMENT_READ)
508        }
509        ty::FragmentShaderReadDepthStencilInputAttachment => {
510            (stage::FRAGMENT_SHADER, access::INPUT_ATTACHMENT_READ)
511        }
512        ty::FragmentShaderReadOther => (stage::FRAGMENT_SHADER, access::SHADER_READ),
513        ty::ColorAttachmentRead => (
514            stage::COLOR_ATTACHMENT_OUTPUT,
515            access::COLOR_ATTACHMENT_READ,
516        ),
517        ty::DepthStencilAttachmentRead => (
518            stage::from_raw(
519                stage::EARLY_FRAGMENT_TESTS.as_raw()
520                    | vk::PipelineStageFlags::LATE_FRAGMENT_TESTS.as_raw(),
521            ),
522            access::DEPTH_STENCIL_ATTACHMENT_READ,
523        ),
524        ty::ComputeShaderReadUniformBuffer => (stage::COMPUTE_SHADER, access::UNIFORM_READ),
525        ty::ComputeShaderReadSampledImageOrUniformTexelBuffer => {
526            (stage::COMPUTE_SHADER, access::SHADER_READ)
527        }
528        ty::ComputeShaderReadOther => (stage::COMPUTE_SHADER, access::SHADER_READ),
529        ty::AnyShaderReadUniformBuffer => (stage::ALL_COMMANDS, access::UNIFORM_READ),
530        ty::AnyShaderReadUniformBufferOrVertexBuffer => (
531            stage::ALL_COMMANDS,
532            access::from_raw(
533                access::UNIFORM_READ.as_raw() | vk::AccessFlags::VERTEX_ATTRIBUTE_READ.as_raw(),
534            ),
535        ),
536        ty::AnyShaderReadSampledImageOrUniformTexelBuffer => {
537            (stage::ALL_COMMANDS, access::SHADER_READ)
538        }
539        ty::AnyShaderReadOther => (stage::ALL_COMMANDS, access::SHADER_READ),
540        ty::TransferRead => (stage::TRANSFER, access::TRANSFER_READ),
541        ty::HostRead => (stage::HOST, access::HOST_READ),
542        ty::Present => (stage::empty(), access::empty()),
543        ty::CommandBufferWriteNVX => (
544            stage::COMMAND_PREPROCESS_NV,
545            access::COMMAND_PREPROCESS_WRITE_NV,
546        ),
547        ty::VertexShaderWrite => (stage::VERTEX_SHADER, access::SHADER_WRITE),
548        ty::TessellationControlShaderWrite => {
549            (stage::TESSELLATION_CONTROL_SHADER, access::SHADER_WRITE)
550        }
551        ty::TessellationEvaluationShaderWrite => {
552            (stage::TESSELLATION_EVALUATION_SHADER, access::SHADER_WRITE)
553        }
554        ty::GeometryShaderWrite => (stage::GEOMETRY_SHADER, access::SHADER_WRITE),
555        ty::FragmentShaderWrite => (stage::FRAGMENT_SHADER, access::SHADER_WRITE),
556        ty::ColorAttachmentWrite => (
557            stage::COLOR_ATTACHMENT_OUTPUT,
558            access::COLOR_ATTACHMENT_WRITE,
559        ),
560        ty::DepthStencilAttachmentWrite => (
561            stage::from_raw(
562                stage::EARLY_FRAGMENT_TESTS.as_raw()
563                    | vk::PipelineStageFlags::LATE_FRAGMENT_TESTS.as_raw(),
564            ),
565            access::DEPTH_STENCIL_ATTACHMENT_WRITE,
566        ),
567        ty::DepthStencilAttachmentReadWrite => (
568            stage::from_raw(
569                stage::EARLY_FRAGMENT_TESTS.as_raw()
570                    | vk::PipelineStageFlags::LATE_FRAGMENT_TESTS.as_raw(),
571            ),
572            access::from_raw(
573                access::DEPTH_STENCIL_ATTACHMENT_WRITE.as_raw()
574                    | vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ.as_raw(),
575            ),
576        ),
577        ty::DepthAttachmentWriteStencilReadOnly => (
578            stage::from_raw(
579                stage::EARLY_FRAGMENT_TESTS.as_raw()
580                    | vk::PipelineStageFlags::LATE_FRAGMENT_TESTS.as_raw(),
581            ),
582            access::from_raw(
583                access::DEPTH_STENCIL_ATTACHMENT_WRITE.as_raw()
584                    | vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ.as_raw(),
585            ),
586        ),
587        ty::StencilAttachmentWriteDepthReadOnly => (
588            stage::from_raw(
589                stage::EARLY_FRAGMENT_TESTS.as_raw()
590                    | vk::PipelineStageFlags::LATE_FRAGMENT_TESTS.as_raw(),
591            ),
592            access::from_raw(
593                access::DEPTH_STENCIL_ATTACHMENT_WRITE.as_raw()
594                    | vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ.as_raw(),
595            ),
596        ),
597        ty::ComputeShaderWrite => (stage::COMPUTE_SHADER, access::SHADER_WRITE),
598        ty::ComputeShaderReadWrite => (
599            stage::COMPUTE_SHADER,
600            access::from_raw(access::SHADER_WRITE.as_raw() | access::SHADER_READ.as_raw()),
601        ),
602        ty::AnyShaderWrite => (stage::ALL_COMMANDS, access::SHADER_WRITE),
603        ty::TransferWrite => (stage::TRANSFER, access::TRANSFER_WRITE),
604        ty::HostWrite => (stage::HOST, access::HOST_WRITE),
605        ty::ColorAttachmentReadWrite => (
606            stage::COLOR_ATTACHMENT_OUTPUT,
607            access::from_raw(
608                access::COLOR_ATTACHMENT_READ.as_raw()
609                    | vk::AccessFlags::COLOR_ATTACHMENT_WRITE.as_raw(),
610            ),
611        ),
612        ty::General => (
613            stage::ALL_COMMANDS,
614            access::from_raw(access::MEMORY_READ.as_raw() | vk::AccessFlags::MEMORY_WRITE.as_raw()),
615        ),
616        ty::RayTracingShaderReadSampledImageOrUniformTexelBuffer => {
617            (stage::RAY_TRACING_SHADER_KHR, access::SHADER_READ)
618        }
619        ty::RayTracingShaderReadColorInputAttachment => {
620            (stage::RAY_TRACING_SHADER_KHR, access::INPUT_ATTACHMENT_READ)
621        }
622        ty::RayTracingShaderReadDepthStencilInputAttachment => {
623            (stage::RAY_TRACING_SHADER_KHR, access::INPUT_ATTACHMENT_READ)
624        }
625        ty::RayTracingShaderReadAccelerationStructure => (
626            stage::RAY_TRACING_SHADER_KHR,
627            access::ACCELERATION_STRUCTURE_READ_KHR,
628        ),
629        ty::RayTracingShaderReadOther => (stage::RAY_TRACING_SHADER_KHR, access::SHADER_READ),
630        ty::AccelerationStructureBuildWrite => (
631            stage::ACCELERATION_STRUCTURE_BUILD_KHR,
632            access::ACCELERATION_STRUCTURE_WRITE_KHR,
633        ),
634        ty::AccelerationStructureBuildRead => (
635            stage::ACCELERATION_STRUCTURE_BUILD_KHR,
636            access::ACCELERATION_STRUCTURE_READ_KHR,
637        ),
638        ty::AccelerationStructureBufferWrite => (
639            stage::ACCELERATION_STRUCTURE_BUILD_KHR,
640            access::TRANSFER_WRITE,
641        ),
642    }
643}
644
645/// Describes the general category of all graphics driver failure cases.
646///
647/// In the event of a failure you should follow the _Screen 13_ code to the responsible Vulkan API
648/// and then to the `Ash` stub call; it will generally contain a link to the appropriate
649/// specification. The specifications provide a table of possible error conditions which can be a
650/// good starting point to debug the issue.
651///
652/// Feel free to open an issue on GitHub, [here](https://github.com/attackgoat/screen-13/issues) for
653/// help debugging the issue.
654#[derive(Debug)]
655pub enum DriverError {
656    /// The input data, or referenced data, is not valid for the current state.
657    InvalidData,
658
659    /// The requested feature, or input configuration, is not supported for the current state.
660    Unsupported,
661
662    /// The device has run out of physical memory.
663    ///
664    /// Many drivers return this value for generic or unhandled error conditions.
665    OutOfMemory,
666}
667
668impl Display for DriverError {
669    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
670        write!(f, "{:?}", self)
671    }
672}
673
674impl Error for DriverError {}
675
676#[cfg(test)]
677mod tests {
678    use {super::merge_push_constant_ranges, ash::vk};
679
680    macro_rules! assert_pcr_eq {
681        ($lhs: expr, $rhs: expr,) => {
682            assert_eq!($lhs.stage_flags, $rhs.stage_flags, "Stages flags not equal");
683            assert_eq!($lhs.offset, $rhs.offset, "Offset not equal");
684            assert_eq!($lhs.size, $rhs.size, "Size not equal");
685        };
686    }
687
688    #[test]
689    pub fn push_constant_ranges_complex() {
690        let res = merge_push_constant_ranges(&[
691            vk::PushConstantRange {
692                stage_flags: vk::ShaderStageFlags::VERTEX,
693                offset: 8,
694                size: 16,
695            },
696            vk::PushConstantRange {
697                stage_flags: vk::ShaderStageFlags::GEOMETRY,
698                offset: 20,
699                size: 48,
700            },
701            vk::PushConstantRange {
702                stage_flags: vk::ShaderStageFlags::TESSELLATION_CONTROL,
703                offset: 24,
704                size: 8,
705            },
706            vk::PushConstantRange {
707                stage_flags: vk::ShaderStageFlags::TESSELLATION_EVALUATION,
708                offset: 28,
709                size: 32,
710            },
711            vk::PushConstantRange {
712                stage_flags: vk::ShaderStageFlags::FRAGMENT,
713                offset: 40,
714                size: 128,
715            },
716        ]);
717
718        assert_eq!(res.len(), 8);
719        assert_pcr_eq!(
720            res[0],
721            vk::PushConstantRange {
722                stage_flags: vk::ShaderStageFlags::VERTEX,
723                offset: 8,
724                size: 12,
725            },
726        );
727        assert_pcr_eq!(
728            res[1],
729            vk::PushConstantRange {
730                stage_flags: vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::GEOMETRY,
731                offset: 20,
732                size: 4,
733            },
734        );
735        assert_pcr_eq!(
736            res[2],
737            vk::PushConstantRange {
738                stage_flags: vk::ShaderStageFlags::TESSELLATION_CONTROL
739                    | vk::ShaderStageFlags::GEOMETRY,
740                offset: 24,
741                size: 4,
742            },
743        );
744        assert_pcr_eq!(
745            res[3],
746            vk::PushConstantRange {
747                stage_flags: vk::ShaderStageFlags::TESSELLATION_CONTROL
748                    | vk::ShaderStageFlags::TESSELLATION_EVALUATION
749                    | vk::ShaderStageFlags::GEOMETRY,
750                offset: 28,
751                size: 4,
752            },
753        );
754        assert_pcr_eq!(
755            res[4],
756            vk::PushConstantRange {
757                stage_flags: vk::ShaderStageFlags::GEOMETRY
758                    | vk::ShaderStageFlags::TESSELLATION_EVALUATION,
759                offset: 32,
760                size: 8,
761            },
762        );
763        assert_pcr_eq!(
764            res[5],
765            vk::PushConstantRange {
766                stage_flags: vk::ShaderStageFlags::GEOMETRY
767                    | vk::ShaderStageFlags::TESSELLATION_EVALUATION
768                    | vk::ShaderStageFlags::FRAGMENT,
769                offset: 40,
770                size: 20,
771            },
772        );
773        assert_pcr_eq!(
774            res[6],
775            vk::PushConstantRange {
776                stage_flags: vk::ShaderStageFlags::FRAGMENT | vk::ShaderStageFlags::GEOMETRY,
777                offset: 60,
778                size: 8,
779            },
780        );
781        assert_pcr_eq!(
782            res[7],
783            vk::PushConstantRange {
784                stage_flags: vk::ShaderStageFlags::FRAGMENT,
785                offset: 68,
786                size: 100,
787            },
788        );
789    }
790
791    #[test]
792    pub fn push_constant_ranges_disjoint() {
793        let res = merge_push_constant_ranges(&[
794            vk::PushConstantRange {
795                stage_flags: vk::ShaderStageFlags::VERTEX,
796                offset: 0,
797                size: 32,
798            },
799            vk::PushConstantRange {
800                stage_flags: vk::ShaderStageFlags::FRAGMENT,
801                offset: 32,
802                size: 64,
803            },
804        ]);
805
806        assert_eq!(res.len(), 2);
807        assert_pcr_eq!(
808            res[0],
809            vk::PushConstantRange {
810                stage_flags: vk::ShaderStageFlags::VERTEX,
811                offset: 0,
812                size: 32,
813            },
814        );
815        assert_pcr_eq!(
816            res[1],
817            vk::PushConstantRange {
818                stage_flags: vk::ShaderStageFlags::FRAGMENT,
819                offset: 32,
820                size: 64,
821            },
822        );
823    }
824
825    #[test]
826    pub fn push_constant_ranges_equal() {
827        let res = merge_push_constant_ranges(&[
828            vk::PushConstantRange {
829                stage_flags: vk::ShaderStageFlags::VERTEX,
830                offset: 0,
831                size: 32,
832            },
833            vk::PushConstantRange {
834                stage_flags: vk::ShaderStageFlags::FRAGMENT,
835                offset: 0,
836                size: 32,
837            },
838        ]);
839
840        assert_eq!(res.len(), 1);
841        assert_pcr_eq!(
842            res[0],
843            vk::PushConstantRange {
844                stage_flags: vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::FRAGMENT,
845                offset: 0,
846                size: 32,
847            },
848        );
849    }
850
851    #[test]
852    pub fn push_constant_ranges_overlap() {
853        let res = merge_push_constant_ranges(&[
854            vk::PushConstantRange {
855                stage_flags: vk::ShaderStageFlags::VERTEX,
856                offset: 0,
857                size: 24,
858            },
859            vk::PushConstantRange {
860                stage_flags: vk::ShaderStageFlags::GEOMETRY,
861                offset: 8,
862                size: 24,
863            },
864            vk::PushConstantRange {
865                stage_flags: vk::ShaderStageFlags::FRAGMENT,
866                offset: 20,
867                size: 28,
868            },
869        ]);
870
871        assert_eq!(res.len(), 5);
872        assert_pcr_eq!(
873            res[0],
874            vk::PushConstantRange {
875                stage_flags: vk::ShaderStageFlags::VERTEX,
876                offset: 0,
877                size: 8,
878            },
879        );
880        assert_pcr_eq!(
881            res[1],
882            vk::PushConstantRange {
883                stage_flags: vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::GEOMETRY,
884                offset: 8,
885                size: 12,
886            },
887        );
888        assert_pcr_eq!(
889            res[2],
890            vk::PushConstantRange {
891                stage_flags: vk::ShaderStageFlags::VERTEX
892                    | vk::ShaderStageFlags::GEOMETRY
893                    | vk::ShaderStageFlags::FRAGMENT,
894                offset: 20,
895                size: 4,
896            },
897        );
898        assert_pcr_eq!(
899            res[3],
900            vk::PushConstantRange {
901                stage_flags: vk::ShaderStageFlags::GEOMETRY | vk::ShaderStageFlags::FRAGMENT,
902                offset: 24,
903                size: 8,
904            },
905        );
906        assert_pcr_eq!(
907            res[4],
908            vk::PushConstantRange {
909                stage_flags: vk::ShaderStageFlags::FRAGMENT,
910                offset: 32,
911                size: 16,
912            },
913        );
914    }
915
916    #[test]
917    pub fn push_constant_ranges_subset() {
918        let res = merge_push_constant_ranges(&[
919            vk::PushConstantRange {
920                stage_flags: vk::ShaderStageFlags::VERTEX,
921                offset: 0,
922                size: 64,
923            },
924            vk::PushConstantRange {
925                stage_flags: vk::ShaderStageFlags::FRAGMENT,
926                offset: 16,
927                size: 8,
928            },
929        ]);
930
931        assert_eq!(res.len(), 3);
932        assert_pcr_eq!(
933            res[0],
934            vk::PushConstantRange {
935                stage_flags: vk::ShaderStageFlags::VERTEX,
936                offset: 0,
937                size: 16,
938            },
939        );
940        assert_pcr_eq!(
941            res[1],
942            vk::PushConstantRange {
943                stage_flags: vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::FRAGMENT,
944                offset: 16,
945                size: 8,
946            },
947        );
948        assert_pcr_eq!(
949            res[2],
950            vk::PushConstantRange {
951                stage_flags: vk::ShaderStageFlags::VERTEX,
952                offset: 24,
953                size: 40,
954            },
955        );
956    }
957
958    #[test]
959    pub fn push_constant_ranges_superset() {
960        let res = merge_push_constant_ranges(&[
961            vk::PushConstantRange {
962                stage_flags: vk::ShaderStageFlags::VERTEX,
963                offset: 0,
964                size: 64,
965            },
966            vk::PushConstantRange {
967                stage_flags: vk::ShaderStageFlags::FRAGMENT,
968                offset: 0,
969                size: 80,
970            },
971        ]);
972
973        assert_eq!(res.len(), 2);
974        assert_pcr_eq!(
975            res[0],
976            vk::PushConstantRange {
977                stage_flags: vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::FRAGMENT,
978                offset: 0,
979                size: 64,
980            },
981        );
982        assert_pcr_eq!(
983            res[1],
984            vk::PushConstantRange {
985                stage_flags: vk::ShaderStageFlags::FRAGMENT,
986                offset: 64,
987                size: 16,
988            },
989        );
990    }
991}