Skip to main content

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(`brvk::VK_KHR_surface`/`brvk::VK_KHR_swapchain`/`brvk::VK_KHR_display`)
11//! - `alloc`(default): Enable extra functionalities that may allocate some memory inside
12//! - `brvk::VK_***`: Enable Vulkan extensions(same name as each extensions)
13#![cfg_attr(docsrs, feature(doc_cfg))]
14#![doc(html_root_url = "https://docs.ct2.io/bedrock/mod-peridot/")]
15
16// Platform Extras
17#[cfg(feature = "VK_KHR_android_surface")]
18extern crate android;
19#[cfg(any(feature = "VK_KHR_xlib_surface", feature = "VK_EXT_acquire_xlib_display"))]
20extern crate x11;
21#[cfg(feature = "VK_KHR_xcb_surface")]
22extern crate xcb;
23
24pub use bedrock_vk::{
25    self as vk, GenericVulkanSinkStructure, GenericVulkanStructure, TypedVulkanSinkStructure, TypedVulkanStructure,
26    VkDeviceSize as DeviceSize, VkExtent2D as Extent2D, VkExtent3D as Extent3D, VkFormat as Format,
27    VkOffset2D as Offset2D, VkOffset3D as Offset3D, VkRawHandle, VkRect2D as Rect2D, VkViewport as Viewport,
28    VulkanSinkStructure, VulkanStructure,
29};
30#[cfg(feature = "Implements")]
31pub use bedrock_vk::{ResolvedFnCell, ResolverInterface, load_function_unconstrainted, load_symbol_unconstrainted};
32
33use derives::*;
34
35#[cfg(feature = "CustomResolver")]
36pub use bedrock_vk::set_resolver;
37
38pub use derives::SpecializationConstants;
39
40pub mod error;
41
42#[cfg(feature = "Implements")]
43pub mod vkfn_wrapper;
44
45macro_rules! DerefContainerWithGuardsBracketImpl {
46    (for mut $t: path { $($required: item)* }) => {
47        DerefContainerBracketImpl!(for mut $t { $($required)* });
48        GuardsImpl!(for mut $t { $($required)* });
49    };
50    (for $t: path { $($required: item)* }) => {
51        DerefContainerBracketImpl!(for $t { $($required)* });
52        GuardsImpl!(for $t { $($required)* });
53    };
54}
55macro_rules! DerefContainerBracketImpl {
56    (unsafe for mut $t: path { $($required: item)* }) => {
57        unsafe impl<'s, T> $t for &'s mut T where T: $t + ?Sized { $($required)* }
58        unsafe impl<T> $t for Box<T> where T: $t + ?Sized { $($required)* }
59        unsafe impl<T> $t for core::mem::ManuallyDrop<T> where T: $t { $($required)* }
60    };
61    (unsafe for $t: path { $($required: item)* }) => {
62        unsafe impl<'s, T> $t for &'s T where T: $t + ?Sized { $($required)* }
63        unsafe impl<T> $t for std::rc::Rc<T> where T: $t + ?Sized { $($required)* }
64        unsafe impl<T> $t for std::sync::Arc<T> where T: $t + ?Sized { $($required)* }
65
66        DerefContainerBracketImpl!(unsafe for mut $t { $($required)* });
67    };
68    (for mut $t: path { $($required: item)* }) => {
69        impl<'s, T> $t for &'s mut T where T: $t + ?Sized { $($required)* }
70        impl<T> $t for Box<T> where T: $t + ?Sized { $($required)* }
71        impl<T> $t for core::mem::ManuallyDrop<T> where T: $t { $($required)* }
72    };
73    (for $t: path { $($required: item)* }) => {
74        impl<'s, T> $t for &'s T where T: $t + ?Sized { $($required)* }
75        impl<T> $t for std::rc::Rc<T> where T: $t + ?Sized { $($required)* }
76        impl<T> $t for std::sync::Arc<T> where T: $t + ?Sized { $($required)* }
77
78        DerefContainerBracketImpl!(for mut $t { $($required)* });
79    };
80}
81macro_rules! GuardsImpl {
82    (for mut $t: path { $($required: item)* }) => {
83        impl<T> $t for std::cell::RefMut<'_, T> where T: $t + ?Sized { $($required)* }
84        impl<T> $t for std::sync::RwLockWriteGuard<'_, T> where T: $t + ?Sized { $($required)* }
85        impl<T> $t for std::sync::MutexGuard<'_, T> where T: $t + ?Sized { $($required)* }
86        impl<T> $t for parking_lot::MutexGuard<'_, T> where T: $t + ?Sized { $($required)* }
87        impl<T> $t for parking_lot::MappedMutexGuard<'_, T> where T: $t + ?Sized { $($required)* }
88        impl<T> $t for parking_lot::RwLockWriteGuard<'_, T> where T: $t + ?Sized { $($required)* }
89        impl<T> $t for parking_lot::MappedRwLockWriteGuard<'_, T> where T: $t + ?Sized { $($required)* }
90    };
91    (for $t: path { $($required: item)* }) => {
92        impl<T> $t for std::cell::Ref<'_, T> where T: $t + ?Sized { $($required)* }
93        impl<T> $t for std::sync::RwLockReadGuard<'_, T> where T: $t + ?Sized { $($required)* }
94        impl<T> $t for parking_lot::RwLockReadGuard<'_, T> where T: $t + ?Sized { $($required)* }
95        impl<T> $t for parking_lot::MappedRwLockReadGuard<'_, T> where T: $t + ?Sized { $($required)* }
96
97        GuardsImpl!(for mut $t { $($required)* });
98    };
99}
100macro_rules! ForwardFnPtr {
101    (deref $name: ident -> $t: ty) => {
102        #[inline(always)]
103        fn $name(&self) -> $t {
104            (**self).$name()
105        }
106    };
107}
108
109pub type Result<T> = core::result::Result<T, ResultCode>;
110
111#[cfg(feature = "alloc")]
112pub(crate) mod alloc;
113
114mod handle;
115use crate::error::ResultCode;
116
117pub use self::handle::*;
118
119/// An result type of querying an array of objects
120#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
121#[must_use = "array query may finished incompletely"]
122pub struct ArrayQueryResult<T> {
123    /// The result value of the query.
124    pub result: T,
125    /// * false: Objects are queried successfully.
126    /// * true: There are some objects left(i.e. buffer was too small).
127    pub is_incomplete: bool,
128}
129impl ArrayQueryResult<()> {
130    #[inline(always)]
131    pub fn from_vk_result(r: vk::VkResult) -> Result<Self> {
132        match r {
133            vk::VK_SUCCESS => Ok(Self {
134                result: (),
135                is_incomplete: false,
136            }),
137            vk::VK_INCOMPLETE => Ok(Self {
138                result: (),
139                is_incomplete: true,
140            }),
141            e => match ResultCode(e) {
142                e if e.is_err() => Err(e),
143                e => unreachable!("unexpected result: {e:?}"),
144            },
145        }
146    }
147}
148impl<T> ArrayQueryResult<T> {
149    #[inline(always)]
150    pub fn with_result<U>(self, v: U) -> ArrayQueryResult<U> {
151        ArrayQueryResult {
152            result: v,
153            is_incomplete: self.is_incomplete,
154        }
155    }
156
157    #[inline(always)]
158    pub fn map_result<U>(self, f: impl FnOnce(T) -> U) -> ArrayQueryResult<U> {
159        ArrayQueryResult {
160            result: f(self.result),
161            is_incomplete: self.is_incomplete,
162        }
163    }
164
165    #[inline(always)]
166    pub fn assert_complete(self) -> T {
167        assert!(!self.is_incomplete, "the query was incomplete!");
168        self.result
169    }
170}
171
172#[cfg(feature = "VK_KHR_swapchain")]
173#[derive(Debug, Clone, Copy, PartialEq, Eq)]
174pub enum PresentResult {
175    /// All requests presented successfully.
176    Success,
177    /// The presentation was suboptimal, but the swapchain can still be used.
178    Suboptimal,
179}
180
181#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
182pub enum TimeoutableWaitResult {
183    /// Wait operations completed successfully.
184    Success,
185    /// Wait operations timed out.
186    Timeout,
187}
188impl TimeoutableWaitResult {
189    pub fn from_vk_result(r: vk::VkResult) -> Self {
190        match r {
191            vk::VK_SUCCESS => Self::Success,
192            vk::VK_TIMEOUT => Self::Timeout,
193            e => unreachable!("unexpected result: {:?}", ResultCode(e)),
194        }
195    }
196}
197
198/// An object in Vulkan
199pub trait VkObject: VkHandle {
200    const TYPE: vk::VkObjectType;
201
202    /// Give a user-friendly name to this object.
203    /// # Failures
204    /// On failure, this command returns
205    ///
206    /// * `brvk::VK_ERROR_OUT_OF_HOST_MEMORY`
207    /// * `brvk::VK_ERROR_OUT_OF_DEVICE_MEMORY`
208    #[implements("VK_EXT_debug_utils")]
209    fn set_name(&self, name: Option<&core::ffi::CStr>) -> crate::Result<()>
210    where
211        Self: DeviceChild<ConcreteDevice: InstanceChild<ConcreteInstance: InstanceDebugUtilsExtension>>,
212        Self::Handle: vk::VkRawHandle,
213    {
214        self.device()
215            .set_object_name(&DebugUtilsObjectNameInfo::new(self, name))
216    }
217}
218impl<T: VkObject + ?Sized> VkObject for &'_ T {
219    const TYPE: vk::VkObjectType = T::TYPE;
220}
221impl<T: VkObject + ?Sized> VkObject for &'_ mut T {
222    const TYPE: vk::VkObjectType = T::TYPE;
223}
224impl<T: VkObject + ?Sized> VkObject for std::rc::Rc<T> {
225    const TYPE: vk::VkObjectType = T::TYPE;
226}
227impl<T: VkObject + ?Sized> VkObject for std::sync::Arc<T> {
228    const TYPE: vk::VkObjectType = T::TYPE;
229}
230impl<T: VkObject + ?Sized> VkObject for std::cell::Ref<'_, T> {
231    const TYPE: vk::VkObjectType = T::TYPE;
232}
233impl<T: VkObject + ?Sized> VkObject for std::cell::RefMut<'_, T> {
234    const TYPE: vk::VkObjectType = T::TYPE;
235}
236impl<T: VkObject + ?Sized> VkObject for std::sync::MutexGuard<'_, T> {
237    const TYPE: vk::VkObjectType = T::TYPE;
238}
239
240// A single Number or a Range
241pub trait AnalogNumRange<T> {
242    fn begin(&self) -> T;
243    fn end(&self) -> T;
244    fn count(&self) -> T
245    where
246        T: std::ops::Sub<T, Output = T> + Copy,
247    {
248        self.end() - self.begin()
249    }
250}
251impl<T> AnalogNumRange<T> for T
252where
253    T: std::ops::Add<u32, Output = T> + Copy,
254{
255    fn begin(&self) -> T {
256        *self
257    }
258    fn end(&self) -> T {
259        *self + 1
260    }
261}
262impl<T> AnalogNumRange<T> for std::ops::Range<T>
263where
264    T: Copy,
265{
266    fn begin(&self) -> T {
267        self.start
268    }
269    fn end(&self) -> T {
270        self.end
271    }
272}
273
274pub(crate) mod ffi_helper;
275
276mod base;
277pub use base::*;
278mod device;
279pub use device::*;
280mod sync;
281pub use sync::*;
282pub mod resources;
283pub use resources::*;
284#[macro_use]
285mod descriptor;
286pub use descriptor::*;
287mod renderpass;
288pub use self::renderpass::*;
289mod framebuffer;
290pub use framebuffer::*;
291mod shading;
292pub use shading::*;
293mod command;
294pub use command::*;
295mod debug;
296#[allow(unused_imports)]
297pub use debug::*;
298mod ext;
299pub use self::ext::*;
300mod external;
301#[allow(unused_imports)]
302pub use external::*;
303mod batching;
304pub use self::batching::*;
305mod dependency;
306#[allow(unused_imports)]
307pub use self::dependency::*;
308mod query;
309pub use self::query::*;
310
311#[cfg(feature = "VK_KHR_surface")]
312mod surface;
313#[cfg(feature = "VK_KHR_surface")]
314pub use self::surface::*;
315
316mod fmt;
317pub use self::fmt::*;