summaryrefslogtreecommitdiffstats
path: root/third_party/rust/ash/src/prelude.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/ash/src/prelude.rs')
-rw-r--r--third_party/rust/ash/src/prelude.rs122
1 files changed, 122 insertions, 0 deletions
diff --git a/third_party/rust/ash/src/prelude.rs b/third_party/rust/ash/src/prelude.rs
new file mode 100644
index 0000000000..321c3aaddd
--- /dev/null
+++ b/third_party/rust/ash/src/prelude.rs
@@ -0,0 +1,122 @@
+use std::convert::TryInto;
+#[cfg(feature = "debug")]
+use std::fmt;
+use std::mem;
+
+use crate::vk;
+pub type VkResult<T> = Result<T, vk::Result>;
+
+impl vk::Result {
+ #[inline]
+ pub fn result(self) -> VkResult<()> {
+ self.result_with_success(())
+ }
+
+ #[inline]
+ pub fn result_with_success<T>(self, v: T) -> VkResult<T> {
+ match self {
+ Self::SUCCESS => Ok(v),
+ _ => Err(self),
+ }
+ }
+
+ #[inline]
+ pub unsafe fn assume_init_on_success<T>(self, v: mem::MaybeUninit<T>) -> VkResult<T> {
+ self.result().map(move |()| v.assume_init())
+ }
+}
+
+/// Repeatedly calls `f` until it does not return [`vk::Result::INCOMPLETE`] anymore,
+/// ensuring all available data has been read into the vector.
+///
+/// See for example [`vkEnumerateInstanceExtensionProperties`]: the number of available
+/// items may change between calls; [`vk::Result::INCOMPLETE`] is returned when the count
+/// increased (and the vector is not large enough after querying the initial size),
+/// requiring Ash to try again.
+///
+/// [`vkEnumerateInstanceExtensionProperties`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkEnumerateInstanceExtensionProperties.html
+pub(crate) unsafe fn read_into_uninitialized_vector<N: Copy + Default + TryInto<usize>, T>(
+ f: impl Fn(&mut N, *mut T) -> vk::Result,
+) -> VkResult<Vec<T>>
+where
+ <N as TryInto<usize>>::Error: std::fmt::Debug,
+{
+ loop {
+ let mut count = N::default();
+ f(&mut count, std::ptr::null_mut()).result()?;
+ let mut data =
+ Vec::with_capacity(count.try_into().expect("`N` failed to convert to `usize`"));
+
+ let err_code = f(&mut count, data.as_mut_ptr());
+ if err_code != vk::Result::INCOMPLETE {
+ err_code.result()?;
+ data.set_len(count.try_into().expect("`N` failed to convert to `usize`"));
+ break Ok(data);
+ }
+ }
+}
+
+/// Repeatedly calls `f` until it does not return [`vk::Result::INCOMPLETE`] anymore,
+/// ensuring all available data has been read into the vector.
+///
+/// Items in the target vector are [`default()`][`Default::default()`]-initialized which
+/// is required for [`vk::BaseOutStructure`]-like structs where [`vk::BaseOutStructure::s_type`]
+/// needs to be a valid type and [`vk::BaseOutStructure::p_next`] a valid or
+/// [`null`][`std::ptr::null_mut()`] pointer.
+///
+/// See for example [`vkEnumerateInstanceExtensionProperties`]: the number of available
+/// items may change between calls; [`vk::Result::INCOMPLETE`] is returned when the count
+/// increased (and the vector is not large enough after querying the initial size),
+/// requiring Ash to try again.
+///
+/// [`vkEnumerateInstanceExtensionProperties`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkEnumerateInstanceExtensionProperties.html
+pub(crate) unsafe fn read_into_defaulted_vector<
+ N: Copy + Default + TryInto<usize>,
+ T: Default + Clone,
+>(
+ f: impl Fn(&mut N, *mut T) -> vk::Result,
+) -> VkResult<Vec<T>>
+where
+ <N as TryInto<usize>>::Error: std::fmt::Debug,
+{
+ loop {
+ let mut count = N::default();
+ f(&mut count, std::ptr::null_mut()).result()?;
+ let mut data =
+ vec![Default::default(); count.try_into().expect("`N` failed to convert to `usize`")];
+
+ let err_code = f(&mut count, data.as_mut_ptr());
+ if err_code != vk::Result::INCOMPLETE {
+ data.set_len(count.try_into().expect("`N` failed to convert to `usize`"));
+ break err_code.result_with_success(data);
+ }
+ }
+}
+
+#[cfg(feature = "debug")]
+pub(crate) fn debug_flags<Value: Into<u64> + Copy>(
+ f: &mut fmt::Formatter,
+ known: &[(Value, &'static str)],
+ value: Value,
+) -> fmt::Result {
+ let mut first = true;
+ let mut accum = value.into();
+ for &(bit, name) in known {
+ let bit = bit.into();
+ if bit != 0 && accum & bit == bit {
+ if !first {
+ f.write_str(" | ")?;
+ }
+ f.write_str(name)?;
+ first = false;
+ accum &= !bit;
+ }
+ }
+ if accum != 0 {
+ if !first {
+ f.write_str(" | ")?;
+ }
+ write!(f, "{:b}", accum)?;
+ }
+ Ok(())
+}