1#![doc(html_logo_url = "https://raw.githubusercontent.com/vulkano-rs/vulkano/master/logo.png")]
2pub use ash::vk::Handle;
123use bytemuck::{Pod, Zeroable};
124pub use extensions::ExtensionProperties;
125pub use half;
126pub use library::{LoadingError, VulkanLibrary};
127use std::{
128 borrow::Cow,
129 error::Error,
130 fmt::{Debug, Display, Error as FmtError, Formatter},
131 num::NonZeroU64,
132 ops::Deref,
133 sync::Arc,
134};
135pub use version::Version;
136
137#[macro_use]
138mod tests;
139#[macro_use]
140mod extensions;
141pub mod acceleration_structure;
142pub mod buffer;
143pub mod command_buffer;
144pub mod deferred;
145pub mod descriptor_set;
146pub mod device;
147pub mod display;
148pub mod format;
149mod version;
150#[macro_use]
151pub mod render_pass;
152mod cache;
153mod fns;
154pub mod image;
155pub mod instance;
156pub mod library;
157mod macros;
158pub mod memory;
159pub mod padded;
160pub mod pipeline;
161pub mod query;
162mod range_map;
163pub mod range_set;
164pub mod shader;
165pub mod swapchain;
166pub mod sync;
167
168pub use ash::vk::DeviceSize;
171
172pub type NonZeroDeviceSize = NonZeroU64;
174
175pub use ash::vk::DeviceAddress;
177
178pub type NonNullDeviceAddress = NonZeroU64;
180
181#[derive(Debug, Copy, Clone, Default)]
183pub struct StridedDeviceAddressRegion {
184 pub device_address: DeviceAddress,
185 pub stride: DeviceSize,
186 pub size: DeviceSize,
187}
188
189impl StridedDeviceAddressRegion {
190 #[doc(hidden)]
191 pub fn to_vk(&self) -> ash::vk::StridedDeviceAddressRegionKHR {
192 ash::vk::StridedDeviceAddressRegionKHR {
193 device_address: self.device_address,
194 stride: self.stride,
195 size: self.size,
196 }
197 }
198}
199
200#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Debug, Zeroable, Pod)]
205#[repr(transparent)]
206pub struct Packed24_8(u32);
207
208impl Packed24_8 {
209 #[inline]
211 pub fn new(low_24: u32, high_8: u8) -> Self {
212 Self((low_24 & 0x00ff_ffff) | (u32::from(high_8) << 24))
213 }
214
215 #[inline]
217 pub fn low_24(&self) -> u32 {
218 self.0 & 0xffffff
219 }
220
221 #[inline]
223 pub fn high_8(&self) -> u8 {
224 (self.0 >> 24) as u8
225 }
226}
227
228#[allow(unused_extern_crates)]
233extern crate self as vulkano;
234
235pub unsafe trait SafeDeref: Deref {}
237unsafe impl<T: ?Sized> SafeDeref for &T {}
238unsafe impl<T: ?Sized> SafeDeref for Arc<T> {}
239unsafe impl<T: ?Sized> SafeDeref for Box<T> {}
240
241pub unsafe trait VulkanObject {
243 type Handle: Handle;
245
246 fn handle(&self) -> Self::Handle;
248}
249
250unsafe impl<T, U> VulkanObject for T
251where
252 T: SafeDeref<Target = U>,
253 U: VulkanObject + ?Sized,
254{
255 type Handle = U::Handle;
256
257 #[inline]
258 fn handle(&self) -> Self::Handle {
259 (**self).handle()
260 }
261}
262
263#[repr(transparent)]
267struct DebugWrapper<T>(T);
268
269impl<T> Debug for DebugWrapper<T>
270where
271 T: Debug + VulkanObject,
272{
273 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
274 write!(f, "0x{:x}", self.0.handle().as_raw())
275 }
276}
277
278impl<T> Deref for DebugWrapper<T> {
279 type Target = T;
280
281 fn deref(&self) -> &Self::Target {
282 &self.0
283 }
284}
285
286include!(concat!(env!("OUT_DIR"), "/errors.rs"));
288
289impl Error for VulkanError {}
290
291impl Display for VulkanError {
292 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
293 let msg = match self {
294 VulkanError::NotReady => "a resource is not yet ready",
295 VulkanError::Timeout => "an operation has not completed in the specified time",
296 VulkanError::OutOfHostMemory => "a host memory allocation has failed",
297 VulkanError::OutOfDeviceMemory => "a device memory allocation has failed",
298 VulkanError::InitializationFailed => {
299 "initialization of an object could not be completed for implementation-specific \
300 reasons"
301 }
302 VulkanError::DeviceLost => "the logical or physical device has been lost",
303 VulkanError::MemoryMapFailed => "mapping of a memory object has failed",
304 VulkanError::LayerNotPresent => {
305 "a requested layer is not present or could not be loaded"
306 }
307 VulkanError::ExtensionNotPresent => "a requested extension is not supported",
308 VulkanError::FeatureNotPresent => "a requested feature is not supported",
309 VulkanError::IncompatibleDriver => {
310 "the requested version of Vulkan is not supported by the driver or is otherwise \
311 incompatible for implementation-specific reasons"
312 }
313 VulkanError::TooManyObjects => "too many objects of the type have already been created",
314 VulkanError::FormatNotSupported => "a requested format is not supported on this device",
315 VulkanError::FragmentedPool => {
316 "a pool allocation has failed due to fragmentation of the pool's memory"
317 }
318 VulkanError::Unknown => {
319 "an unknown error has occurred; either the application has provided invalid input, \
320 or an implementation failure has occurred"
321 }
322 VulkanError::OutOfPoolMemory => "a pool memory allocation has failed",
323 VulkanError::InvalidExternalHandle => {
324 "an external handle is not a valid handle of the specified type"
325 }
326 VulkanError::Fragmentation => {
327 "a descriptor pool creation has failed due to fragmentation"
328 }
329 VulkanError::InvalidOpaqueCaptureAddress => {
330 "a buffer creation or memory allocation failed because the requested address is \
331 not available. A shader group handle assignment failed because the requested \
332 shader group handle information is no longer valid"
333 }
334 VulkanError::IncompatibleDisplay => {
335 "the display used by a swapchain does not use the same presentable image layout, \
336 or is incompatible in a way that prevents sharing an image"
337 }
338 VulkanError::NotPermitted => "a requested operation was not permitted",
339 VulkanError::SurfaceLost => "a surface is no longer available",
340 VulkanError::NativeWindowInUse => {
341 "the requested window is already in use by Vulkan or another API in a manner which \
342 prevents it from being used again"
343 }
344 VulkanError::OutOfDate => {
345 "a surface has changed in such a way that it is no longer compatible with the \
346 swapchain, and further presentation requests using the swapchain will fail"
347 }
348 VulkanError::InvalidVideoStdParameters => {
349 "the provided Video Std parameters do not adhere to the requirements of the used \
350 video compression standard"
351 }
352 VulkanError::ValidationFailed => "validation failed",
353 VulkanError::FullScreenExclusiveModeLost => {
354 "an operation on a swapchain created with application controlled full-screen \
355 access failed as it did not have exclusive full-screen access"
356 }
357 VulkanError::InvalidDrmFormatModifierPlaneLayout => {
358 "the requested DRM format modifier plane layout is invalid"
359 }
360 VulkanError::InvalidShader => "one or more shaders failed to compile or link",
361 VulkanError::ImageUsageNotSupported => "the requested `ImageUsage` are not supported",
362 VulkanError::VideoPictureLayoutNotSupported => {
363 "the requested video picture layout is not supported"
364 }
365 VulkanError::VideoProfileOperationNotSupported => {
366 "a video profile operation specified via `VideoProfileInfo::video_codec_operation` \
367 is not supported"
368 }
369 VulkanError::VideoProfileFormatNotSupported => {
370 "format parameters in a requested `VideoProfileInfo` chain are not supported"
371 }
372 VulkanError::VideoProfileCodecNotSupported => {
373 "codec-specific parameters in a requested `VideoProfileInfo` chain are not \
374 supported"
375 }
376 VulkanError::VideoStdVersionNotSupported => {
377 "the specified video Std header version is not supported"
378 }
379 VulkanError::CompressionExhausted => {
380 "an image creation failed because internal resources required for compression are \
381 exhausted"
382 }
383 VulkanError::Unnamed(result) => {
384 return write!(f, "unnamed error, VkResult value {}", result.as_raw());
385 }
386 };
387
388 write!(f, "{msg}")
389 }
390}
391
392impl From<VulkanError> for Validated<VulkanError> {
393 fn from(err: VulkanError) -> Self {
394 Self::Error(err)
395 }
396}
397
398#[derive(Clone)]
400pub enum Validated<E> {
401 Error(E),
403
404 ValidationError(Box<ValidationError>),
406}
407
408impl<E> Validated<E> {
409 #[inline]
412 pub fn map<F>(self, f: impl FnOnce(E) -> F) -> Validated<F> {
413 match self {
414 Self::Error(err) => Validated::Error(f(err)),
415 Self::ValidationError(err) => Validated::ValidationError(err),
416 }
417 }
418
419 #[inline]
420 fn map_validation(self, f: impl FnOnce(Box<ValidationError>) -> Box<ValidationError>) -> Self {
421 match self {
422 Self::Error(err) => Self::Error(err),
423 Self::ValidationError(err) => Self::ValidationError(f(err)),
424 }
425 }
426
427 #[inline(always)]
429 #[track_caller]
430 pub fn unwrap(self) -> E {
431 match self {
432 Self::Error(err) => err,
433 Self::ValidationError(err) => {
434 panic!(
435 "called `Validated::unwrap` on a `ValidationError` value: {:?}",
436 err
437 )
438 }
439 }
440 }
441}
442
443impl<E> Error for Validated<E>
444where
445 E: Error + 'static,
446{
447 fn source(&self) -> Option<&(dyn Error + 'static)> {
448 match self {
449 Self::Error(err) => Some(err),
450 Self::ValidationError(err) => Some(err),
451 }
452 }
453}
454
455impl<E> Display for Validated<E> {
456 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
457 match self {
458 Self::Error(_) => write!(f, "a non-validation error occurred"),
459 Self::ValidationError(_) => write!(f, "a validation error occurred"),
460 }
461 }
462}
463
464impl<E> Debug for Validated<E>
465where
466 E: Display,
467{
468 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
469 match self {
470 Self::Error(err) => write!(f, "a non-validation error occurred: {err}"),
471 Self::ValidationError(err) => {
472 write!(f, "a validation error occurred\n\nCaused by:\n {err:?}")
473 }
474 }
475 }
476}
477
478impl<E> From<Box<ValidationError>> for Validated<E> {
479 fn from(err: Box<ValidationError>) -> Self {
480 Self::ValidationError(err)
481 }
482}
483
484#[derive(Clone, Default)]
486pub struct ValidationError {
487 pub context: Cow<'static, str>,
489
490 pub problem: Cow<'static, str>,
492
493 pub requires_one_of: RequiresOneOf,
495
496 pub vuids: &'static [&'static str],
498}
499
500impl ValidationError {
501 fn from_error<E: Error>(err: E) -> Self {
502 Self {
503 context: "".into(),
504 problem: err.to_string().into(),
505 requires_one_of: RequiresOneOf::default(),
506 vuids: &[],
507 }
508 }
509
510 fn add_context(mut self: Box<Self>, context: impl Into<Cow<'static, str>>) -> Box<Self> {
511 if self.context.is_empty() {
512 self.context = context.into();
513 } else {
514 self.context = format!("{}.{}", context.into(), self.context).into();
515 }
516
517 self
518 }
519
520 fn set_vuids(mut self: Box<Self>, vuids: &'static [&'static str]) -> Box<Self> {
521 self.vuids = vuids;
522 self
523 }
524}
525
526impl Debug for ValidationError {
527 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
528 if self.context.is_empty() {
529 write!(f, "{}", self.problem)?;
530 } else {
531 write!(f, "{}: {}", self.context, self.problem)?;
532 }
533
534 if !self.requires_one_of.is_empty() {
535 if self.context.is_empty() && self.problem.is_empty() {
536 write!(f, "{:?}", self.requires_one_of)?;
537 } else {
538 write!(f, "\n\n{:?}", self.requires_one_of)?;
539 }
540 }
541
542 if !self.vuids.is_empty() {
543 write!(f, "\n\nVulkan VUIDs:")?;
544
545 for vuid in self.vuids {
546 write!(f, "\n {}", vuid)?;
547 }
548 }
549
550 Ok(())
551 }
552}
553
554impl Display for ValidationError {
555 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
556 if self.context.is_empty() {
557 write!(f, "{}", self.problem)?;
558 } else {
559 write!(f, "{}: {}", self.context, self.problem)?;
560 }
561
562 if !self.requires_one_of.is_empty() {
563 if self.problem.is_empty() {
564 write!(f, "{}", self.requires_one_of)?;
565 } else {
566 write!(f, " -- {}", self.requires_one_of)?;
567 }
568 }
569
570 if let Some((first, rest)) = self.vuids.split_first() {
571 write!(f, " (Vulkan VUIDs: {}", first)?;
572
573 for vuid in rest {
574 write!(f, ", {}", vuid)?;
575 }
576
577 write!(f, ")")?;
578 }
579
580 Ok(())
581 }
582}
583
584impl Error for ValidationError {}
585
586#[derive(Clone, Copy, Default, PartialEq, Eq)]
589pub struct RequiresOneOf(pub &'static [RequiresAllOf]);
590
591impl RequiresOneOf {
592 pub fn len(&self) -> usize {
594 self.0.len()
595 }
596
597 pub fn is_empty(&self) -> bool {
599 self.0.is_empty()
600 }
601}
602
603impl Debug for RequiresOneOf {
604 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
605 write!(f, "Requires one of:")?;
606
607 for requires_all_of in self.0 {
608 write!(f, "\n {}", requires_all_of)?;
609 }
610
611 Ok(())
612 }
613}
614
615impl Display for RequiresOneOf {
616 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
617 write!(f, "requires one of: ")?;
618
619 if let Some((first, rest)) = self.0.split_first() {
620 if first.0.len() > 1 {
621 write!(f, "({})", first)?;
622 } else {
623 write!(f, "{}", first)?;
624 }
625
626 for rest in rest {
627 if first.0.len() > 1 {
628 write!(f, " or ({})", rest)?;
629 } else {
630 write!(f, " or {}", rest)?;
631 }
632 }
633 }
634
635 Ok(())
636 }
637}
638
639#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
642pub struct RequiresAllOf(pub &'static [Requires]);
643
644impl Display for RequiresAllOf {
645 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
646 if let Some((first, rest)) = self.0.split_first() {
647 write!(f, "{}", first)?;
648
649 for rest in rest {
650 write!(f, " + {}", rest)?;
651 }
652 }
653
654 Ok(())
655 }
656}
657
658#[derive(Clone, Copy, Debug, PartialEq, Eq)]
660pub enum Requires {
661 APIVersion(Version),
662 DeviceFeature(&'static str),
663 DeviceExtension(&'static str),
664 InstanceExtension(&'static str),
665}
666
667impl Display for Requires {
668 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
669 match self {
670 Requires::APIVersion(Version { major, minor, .. }) => {
671 write!(f, "Vulkan API version {}.{}", major, minor)
672 }
673 Requires::DeviceFeature(device_feature) => {
674 write!(f, "device feature `{}`", device_feature)
675 }
676 Requires::DeviceExtension(device_extension) => {
677 write!(f, "device extension `{}`", device_extension)
678 }
679 Requires::InstanceExtension(instance_extension) => {
680 write!(f, "instance extension `{}`", instance_extension)
681 }
682 }
683 }
684}
685
686#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct NonExhaustive(pub(crate) ());