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