bedrock/
lib.rs

1//! Glue library between Vulkan and Rust
2//!
3//! # Copyright
4//! Some documentation comments are from Vulkan Manual Page.
5//! Copyright (c) 2014-2017 Khronos Group.
6//!
7//! # Compile Options
8//! - `Implements`: Enable Vulkan implementations(functions)
9//! - `Multithreaded`: Enables to use objects from some threads(experimental)
10//! - `Presentation`: Enable rendering features to Window/Display(`VK_KHR_surface`/`VK_KHR_swapchain`/`VK_KHR_display`)
11//! - `alloc`(default): Enable extra functionalities that may allocate some memory inside
12//! - `VK_***`: Enable Vulkan extensions(same name as each extensions)
13#![warn(clippy::all)]
14#![cfg_attr(docsrs, feature(doc_cfg))]
15#![doc(html_root_url = "https://docs.ct2.io/bedrock/mod-peridot/")]
16
17// Platform Extras
18#[cfg(feature = "VK_KHR_android_surface")]
19extern crate android;
20#[cfg(feature = "DynamicLoaded")]
21extern crate libloading;
22#[cfg(any(feature = "VK_KHR_xlib_surface", feature = "VK_EXT_acquire_xlib_display"))]
23extern crate x11;
24#[cfg(feature = "VK_KHR_xcb_surface")]
25extern crate xcb;
26
27#[cfg(feature = "DynamicLoaded")]
28#[cfg(unix)]
29mod libdl;
30#[cfg(feature = "DynamicLoaded")]
31#[cfg(windows)]
32mod libloaderapi;
33
34use cfg_if::cfg_if;
35use derives::*;
36
37pub use derives::SpecializationConstants;
38
39#[macro_use]
40mod vk1;
41mod vk2;
42pub mod vk {
43    pub use crate::vk1::*;
44    pub use crate::vk2::*;
45}
46use crate::vk::*;
47
48pub mod error;
49mod resolver;
50#[cfg(feature = "Implements")]
51pub use resolver::ResolverInterface;
52pub use resolver::{PFN, StaticCallable};
53
54#[cfg(feature = "Implements")]
55#[allow(dead_code)]
56pub mod vkfn;
57#[cfg(feature = "Implements")]
58pub mod vkfn_wrapper;
59
60macro_rules! DerefContainerWithGuardsBracketImpl {
61    (for $t: path { $($required: item)* }) => {
62        DerefContainerBracketImpl!(for $t { $($required)* });
63        GuardsImpl!(for $t { $($required)* });
64    }
65}
66macro_rules! DerefContainerBracketImpl {
67    (unsafe for mut $t: path { $($required: item)* }) => {
68        unsafe impl<'s, T> $t for &'s mut T where T: $t + ?Sized { $($required)* }
69        unsafe impl<T> $t for Box<T> where T: $t + ?Sized { $($required)* }
70        unsafe impl<T> $t for core::mem::ManuallyDrop<T> where T: $t { $($required)* }
71    };
72    (unsafe for $t: path { $($required: item)* }) => {
73        unsafe impl<'s, T> $t for &'s T where T: $t + ?Sized { $($required)* }
74        unsafe impl<T> $t for std::rc::Rc<T> where T: $t + ?Sized { $($required)* }
75        unsafe impl<T> $t for std::sync::Arc<T> where T: $t + ?Sized { $($required)* }
76
77        DerefContainerBracketImpl!(unsafe for mut $t { $($required)* });
78    };
79    (for mut $t: path { $($required: item)* }) => {
80        impl<'s, T> $t for &'s mut T where T: $t + ?Sized { $($required)* }
81        impl<T> $t for Box<T> where T: $t + ?Sized { $($required)* }
82        impl<T> $t for core::mem::ManuallyDrop<T> where T: $t { $($required)* }
83    };
84    (for $t: path { $($required: item)* }) => {
85        impl<'s, T> $t for &'s T where T: $t + ?Sized { $($required)* }
86        impl<T> $t for std::rc::Rc<T> where T: $t + ?Sized { $($required)* }
87        impl<T> $t for std::sync::Arc<T> where T: $t + ?Sized { $($required)* }
88
89        DerefContainerBracketImpl!(for mut $t { $($required)* });
90    };
91}
92macro_rules! GuardsImpl {
93    (for mut $t: path { $($required: item)* }) => {
94        impl<T> $t for std::cell::RefMut<'_, T> where T: $t + ?Sized { $($required)* }
95        impl<T> $t for std::sync::RwLockWriteGuard<'_, T> where T: $t + ?Sized { $($required)* }
96        impl<T> $t for std::sync::MutexGuard<'_, T> where T: $t + ?Sized { $($required)* }
97        impl<T> $t for parking_lot::MutexGuard<'_, T> where T: $t + ?Sized { $($required)* }
98        impl<T> $t for parking_lot::MappedMutexGuard<'_, T> where T: $t + ?Sized { $($required)* }
99        impl<T> $t for parking_lot::RwLockWriteGuard<'_, T> where T: $t + ?Sized { $($required)* }
100        impl<T> $t for parking_lot::MappedRwLockWriteGuard<'_, T> where T: $t + ?Sized { $($required)* }
101    };
102    (for $t: path { $($required: item)* }) => {
103        impl<T> $t for std::cell::Ref<'_, T> where T: $t + ?Sized { $($required)* }
104        impl<T> $t for std::sync::RwLockReadGuard<'_, T> where T: $t + ?Sized { $($required)* }
105        impl<T> $t for parking_lot::RwLockReadGuard<'_, T> where T: $t + ?Sized { $($required)* }
106        impl<T> $t for parking_lot::MappedRwLockReadGuard<'_, T> where T: $t + ?Sized { $($required)* }
107
108        GuardsImpl!(for mut $t { $($required)* });
109    };
110}
111macro_rules! ForwardFnPtr {
112    (deref $name: ident -> $t: ty) => {
113        #[inline(always)]
114        fn $name(&self) -> $t {
115            (**self).$name()
116        }
117    };
118}
119
120pub type Result<T> = core::result::Result<T, VkResult>;
121
122#[cfg(feature = "alloc")]
123pub(crate) mod alloc;
124
125mod handle;
126pub use self::handle::*;
127
128/// An result type of querying an array of objects
129#[derive(Debug, Clone, Copy, PartialEq, Eq)]
130pub enum ArrayQueryResult {
131    /// Objects are queried successfully
132    Complete,
133    /// There are some objects left(i.e. buffer was too small)
134    Incomplete,
135}
136
137/// An object in Vulkan
138pub trait VkObject: VkHandle {
139    const TYPE: VkObjectType;
140
141    /// Give a user-friendly name to this object.
142    /// # Failures
143    /// On failure, this command returns
144    ///
145    /// * `VK_ERROR_OUT_OF_HOST_MEMORY`
146    /// * `VK_ERROR_OUT_OF_DEVICE_MEMORY`
147    #[implements("VK_EXT_debug_utils")]
148    fn set_name(&self, name: Option<&core::ffi::CStr>) -> crate::Result<()>
149    where
150        Self: DeviceChild<ConcreteDevice: InstanceChild<ConcreteInstance: InstanceDebugUtilsExtension>>,
151        Self::Handle: VkRawHandle,
152    {
153        self.device()
154            .set_object_name(&DebugUtilsObjectNameInfo::new(self, name))
155    }
156}
157impl<T: VkObject + ?Sized> VkObject for &'_ T {
158    const TYPE: VkObjectType = T::TYPE;
159}
160impl<T: VkObject + ?Sized> VkObject for &'_ mut T {
161    const TYPE: VkObjectType = T::TYPE;
162}
163impl<T: VkObject + ?Sized> VkObject for std::rc::Rc<T> {
164    const TYPE: VkObjectType = T::TYPE;
165}
166impl<T: VkObject + ?Sized> VkObject for std::sync::Arc<T> {
167    const TYPE: VkObjectType = T::TYPE;
168}
169impl<T: VkObject + ?Sized> VkObject for std::cell::Ref<'_, T> {
170    const TYPE: VkObjectType = T::TYPE;
171}
172impl<T: VkObject + ?Sized> VkObject for std::cell::RefMut<'_, T> {
173    const TYPE: VkObjectType = T::TYPE;
174}
175impl<T: VkObject + ?Sized> VkObject for std::sync::MutexGuard<'_, T> {
176    const TYPE: VkObjectType = T::TYPE;
177}
178
179// A single Number or a Range
180pub trait AnalogNumRange<T> {
181    fn begin(&self) -> T;
182    fn end(&self) -> T;
183    fn count(&self) -> T
184    where
185        T: std::ops::Sub<T, Output = T> + Copy,
186    {
187        self.end() - self.begin()
188    }
189}
190impl<T> AnalogNumRange<T> for T
191where
192    T: std::ops::Add<u32, Output = T> + Copy,
193{
194    fn begin(&self) -> T {
195        *self
196    }
197    fn end(&self) -> T {
198        *self + 1
199    }
200}
201impl<T> AnalogNumRange<T> for std::ops::Range<T>
202where
203    T: Copy,
204{
205    fn begin(&self) -> T {
206        self.start
207    }
208    fn end(&self) -> T {
209        self.end
210    }
211}
212
213// Vulkan ReExports //
214pub type DeviceSize = VkDeviceSize;
215pub type Extent2D = VkExtent2D;
216pub type Offset2D = VkOffset2D;
217pub type Rect2D = VkRect2D;
218pub type Viewport = VkViewport;
219pub type Extent3D = VkExtent3D;
220pub type Offset3D = VkOffset3D;
221pub type Format = VkFormat;
222
223// Spreading single value to all dimensions
224impl Extent2D {
225    pub const fn spread1(value: u32) -> Self {
226        Self {
227            width: value,
228            height: value,
229        }
230    }
231}
232impl Extent3D {
233    pub const fn spread1(value: u32) -> Self {
234        Self {
235            width: value,
236            height: value,
237            depth: value,
238        }
239    }
240
241    pub const fn new1(width: u32) -> Self {
242        Self {
243            width,
244            height: 1,
245            depth: 1,
246        }
247    }
248
249    pub const fn new2(width: u32, height: u32) -> Self {
250        Self {
251            width,
252            height,
253            depth: 1,
254        }
255    }
256
257    pub const fn new(width: u32, height: u32, depth: u32) -> Self {
258        Self { width, height, depth }
259    }
260
261    pub const fn as_2d_ref(&self) -> &VkExtent2D {
262        unsafe { std::mem::transmute(self) }
263    }
264}
265impl Offset2D {
266    pub const fn spread1(value: i32) -> Self {
267        Self { x: value, y: value }
268    }
269}
270impl Offset3D {
271    pub const fn spread1(value: i32) -> Self {
272        Self {
273            x: value,
274            y: value,
275            z: value,
276        }
277    }
278
279    pub const fn new1(x: i32) -> Self {
280        Self { x, y: 0, z: 0 }
281    }
282
283    pub const fn new2(x: i32, y: i32) -> Self {
284        Self { x, y, z: 0 }
285    }
286
287    pub const fn new(x: i32, y: i32, z: i32) -> Self {
288        Self { x, y, z }
289    }
290
291    pub const fn as_2d_ref(&self) -> &VkOffset2D {
292        unsafe { std::mem::transmute(self) }
293    }
294}
295
296// into conversion to larger dimension //
297impl Extent2D {
298    pub const fn with_depth(self, depth: u32) -> Extent3D {
299        Extent3D {
300            width: self.width,
301            height: self.height,
302            depth,
303        }
304    }
305}
306impl Offset2D {
307    pub const fn with_z(self, z: i32) -> Offset3D {
308        Offset3D {
309            x: self.x,
310            y: self.y,
311            z,
312        }
313    }
314}
315// AsRef for self //
316impl AsRef<Extent3D> for Extent3D {
317    fn as_ref(&self) -> &Self {
318        self
319    }
320}
321impl AsRef<Extent2D> for Extent2D {
322    fn as_ref(&self) -> &Self {
323        self
324    }
325}
326impl AsRef<Offset3D> for Offset3D {
327    fn as_ref(&self) -> &Self {
328        self
329    }
330}
331impl AsRef<Offset2D> for Offset2D {
332    fn as_ref(&self) -> &Self {
333        self
334    }
335}
336
337// AsRef Conversion to smaller-dimension
338impl AsRef<Extent2D> for Extent3D {
339    fn as_ref(&self) -> &Extent2D {
340        unsafe { core::mem::transmute(self) }
341    }
342}
343impl AsRef<Offset2D> for Offset3D {
344    fn as_ref(&self) -> &Offset2D {
345        unsafe { core::mem::transmute(self) }
346    }
347}
348
349// From conversion to smaller-dimension
350impl From<Offset3D> for Offset2D {
351    fn from(value: Offset3D) -> Self {
352        Self { x: value.x, y: value.y }
353    }
354}
355
356impl From<Extent3D> for Extent2D {
357    fn from(value: Extent3D) -> Self {
358        Self {
359            width: value.width,
360            height: value.height,
361        }
362    }
363}
364
365// Swizzling
366impl Extent3D {
367    pub const fn wh(&self) -> Extent2D {
368        Extent2D {
369            width: self.width,
370            height: self.height,
371        }
372    }
373
374    pub const fn wd(&self) -> Extent2D {
375        Extent2D {
376            width: self.width,
377            height: self.depth,
378        }
379    }
380
381    pub const fn hw(&self) -> Extent2D {
382        Extent2D {
383            width: self.height,
384            height: self.width,
385        }
386    }
387
388    pub const fn hd(&self) -> Extent2D {
389        Extent2D {
390            width: self.height,
391            height: self.depth,
392        }
393    }
394
395    pub const fn dw(&self) -> Extent2D {
396        Extent2D {
397            width: self.depth,
398            height: self.width,
399        }
400    }
401
402    pub const fn dh(&self) -> Extent2D {
403        Extent2D {
404            width: self.depth,
405            height: self.height,
406        }
407    }
408}
409impl Offset3D {
410    pub const fn xy(&self) -> Offset2D {
411        Offset2D { x: self.x, y: self.y }
412    }
413
414    pub const fn xz(&self) -> Offset2D {
415        Offset2D { x: self.x, y: self.z }
416    }
417
418    pub const fn yx(&self) -> Offset2D {
419        Offset2D { x: self.y, y: self.x }
420    }
421
422    pub const fn yz(&self) -> Offset2D {
423        Offset2D { x: self.y, y: self.z }
424    }
425
426    pub const fn zx(&self) -> Offset2D {
427        Offset2D { x: self.z, y: self.x }
428    }
429
430    pub const fn zy(&self) -> Offset2D {
431        Offset2D { x: self.z, y: self.y }
432    }
433}
434
435/// Utility Constants
436impl Extent2D {
437    pub const ONE: Self = Self::spread1(1);
438}
439impl Extent3D {
440    pub const ONE: Self = Self::spread1(1);
441}
442impl Offset2D {
443    pub const ZERO: Self = Self::spread1(0);
444}
445impl Offset3D {
446    pub const ZERO: Self = Self::spread1(0);
447}
448
449/// Viewport and Rect Util Functions
450impl Extent2D {
451    pub const fn into_rect(self, offset: Offset2D) -> Rect2D {
452        Rect2D { offset, extent: self }
453    }
454}
455impl From<Viewport> for Rect2D {
456    fn from(vp: Viewport) -> Self {
457        Rect2D {
458            offset: Offset2D {
459                x: vp.x as _,
460                y: vp.y as _,
461            },
462            extent: Extent2D {
463                width: vp.width as _,
464                height: vp.height as _,
465            },
466        }
467    }
468}
469impl Rect2D {
470    pub const fn make_viewport(&self, depth_range: std::ops::Range<f32>) -> Viewport {
471        Viewport {
472            x: self.offset.x as _,
473            y: self.offset.y as _,
474            width: self.extent.width as _,
475            height: self.extent.height as _,
476            minDepth: depth_range.start,
477            maxDepth: depth_range.end,
478        }
479    }
480}
481impl Viewport {
482    pub const fn from_rect_with_depth_range(rect: &Rect2D, depth_range: core::ops::Range<f32>) -> Self {
483        rect.make_viewport(depth_range)
484    }
485
486    pub const fn set_offset(&mut self, offset: &Offset2D) -> &mut Self {
487        self.x = offset.x as _;
488        self.y = offset.y as _;
489        self
490    }
491    pub const fn set_extent(&mut self, extent: &Extent2D) -> &mut Self {
492        self.width = extent.width as _;
493        self.height = extent.height as _;
494        self
495    }
496    pub const fn set_depth_range(&mut self, range: core::ops::Range<f32>) -> &mut Self {
497        self.minDepth = range.start;
498        self.maxDepth = range.end;
499        self
500    }
501}
502
503pub(crate) mod ffi_helper;
504
505mod base;
506pub use base::*;
507mod device;
508pub use device::*;
509mod sync;
510pub use sync::*;
511pub mod resources;
512pub use resources::*;
513#[macro_use]
514mod descriptor;
515pub use descriptor::*;
516mod renderpass;
517pub use self::renderpass::*;
518mod framebuffer;
519pub use framebuffer::*;
520mod shading;
521pub use shading::*;
522mod command;
523pub use command::*;
524mod surface;
525pub use surface::*;
526mod debug;
527#[allow(unused_imports)]
528pub use debug::*;
529mod ext;
530pub use self::ext::*;
531mod external;
532#[allow(unused_imports)]
533pub use external::*;
534mod batching;
535pub use self::batching::*;
536mod dependency;
537#[allow(unused_imports)]
538pub use self::dependency::*;
539mod query;
540pub use self::query::*;
541
542mod fmt;
543pub use self::fmt::*;