ash/vk/
prelude.rs

1use core::ffi::c_char;
2use core::fmt;
3
4use crate::vk;
5
6/// Holds 24 bits in the least significant bits of memory,
7/// and 8 bytes in the most significant bits of that memory,
8/// occupying a single [`u32`] in total. This is commonly used in
9/// [acceleration structure instances] such as
10/// [`vk::AccelerationStructureInstanceKHR`],
11/// [`vk::AccelerationStructureSRTMotionInstanceNV`] and
12/// [`vk::AccelerationStructureMatrixMotionInstanceNV`].
13///
14/// [acceleration structure instances]: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkAccelerationStructureInstanceKHR.html#_description
15#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
16#[repr(transparent)]
17pub struct Packed24_8(u32);
18
19impl Packed24_8 {
20    pub fn new(low_24: u32, high_8: u8) -> Self {
21        Self((low_24 & 0x00ff_ffff) | (u32::from(high_8) << 24))
22    }
23
24    /// Extracts the least-significant 24 bits (3 bytes) of this integer
25    pub fn low_24(&self) -> u32 {
26        self.0 & 0xffffff
27    }
28
29    /// Extracts the most significant 8 bits (single byte) of this integer
30    pub fn high_8(&self) -> u8 {
31        (self.0 >> 24) as u8
32    }
33}
34
35impl vk::ColorComponentFlags {
36    /// Contraction of [`R`][Self::R] | [`G`][Self::G] | [`B`][Self::B] | [`A`][Self::A]
37    pub const RGBA: Self = Self(Self::R.0 | Self::G.0 | Self::B.0 | Self::A.0);
38}
39
40impl From<vk::Extent2D> for vk::Extent3D {
41    fn from(value: vk::Extent2D) -> Self {
42        Self {
43            width: value.width,
44            height: value.height,
45            depth: 1,
46        }
47    }
48}
49
50impl From<vk::Extent2D> for vk::Rect2D {
51    fn from(extent: vk::Extent2D) -> Self {
52        Self {
53            offset: Default::default(),
54            extent,
55        }
56    }
57}
58
59/// Structures implementing this trait are layout-compatible with [`vk::BaseInStructure`] and
60/// [`vk::BaseOutStructure`]. Such structures have an `s_type` field indicating its type, which
61/// must always match the value of [`TaggedStructure::STRUCTURE_TYPE`].
62pub unsafe trait TaggedStructure {
63    const STRUCTURE_TYPE: vk::StructureType;
64}
65
66#[inline]
67pub(crate) fn wrap_c_str_slice_until_nul(
68    str: &[c_char],
69) -> Result<&core::ffi::CStr, core::ffi::FromBytesUntilNulError> {
70    // SAFETY: The cast from c_char to u8 is ok because a c_char is always one byte.
71    let bytes = unsafe { core::slice::from_raw_parts(str.as_ptr().cast(), str.len()) };
72    core::ffi::CStr::from_bytes_until_nul(bytes)
73}
74
75#[derive(Debug)]
76pub struct CStrTooLargeForStaticArray {
77    pub static_array_size: usize,
78    pub c_str_size: usize,
79}
80#[cfg(feature = "std")]
81impl std::error::Error for CStrTooLargeForStaticArray {}
82impl fmt::Display for CStrTooLargeForStaticArray {
83    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84        write!(
85            f,
86            "static `c_char` target array of length `{}` is too small to write a `CStr` (with `NUL`-terminator) of length `{}`",
87            self.static_array_size, self.c_str_size
88        )
89    }
90}
91
92#[inline]
93pub(crate) fn write_c_str_slice_with_nul(
94    target: &mut [c_char],
95    str: &core::ffi::CStr,
96) -> Result<(), CStrTooLargeForStaticArray> {
97    let bytes = str.to_bytes_with_nul();
98    // SAFETY: The cast from c_char to u8 is ok because a c_char is always one byte.
99    let bytes = unsafe { core::slice::from_raw_parts(bytes.as_ptr().cast(), bytes.len()) };
100    let static_array_size = target.len();
101    target
102        .get_mut(..bytes.len())
103        .ok_or(CStrTooLargeForStaticArray {
104            static_array_size,
105            c_str_size: bytes.len(),
106        })?
107        .copy_from_slice(bytes);
108    Ok(())
109}