bedrock/resources/
buffer.rs

1use crate::ffi_helper::slice_as_ptr_empty_null;
2use crate::*;
3use derives::implements;
4
5pub trait Buffer: VkHandle<Handle = VkBuffer> + DeviceChildHandle {}
6DerefContainerBracketImpl!(for Buffer {});
7GuardsImpl!(for Buffer {});
8
9pub trait BufferView: VkHandle<Handle = VkBufferView> {}
10DerefContainerBracketImpl!(for BufferView {});
11GuardsImpl!(for BufferView {});
12
13/// Opaque handle to a buffer object(constructed via [`BufferDesc`])
14#[derive(VkHandle, VkObject)]
15#[VkObject(type = VkBuffer::OBJECT_TYPE)]
16pub struct BufferObject<Device: VkHandle<Handle = VkDevice>>(pub(crate) VkBuffer, pub(crate) Device);
17#[implements]
18impl<Device: VkHandle<Handle = VkDevice>> Drop for BufferObject<Device> {
19    #[inline(always)]
20    fn drop(&mut self) {
21        unsafe {
22            crate::vkfn::destroy_buffer(self.1.native_ptr(), self.0, core::ptr::null());
23        }
24    }
25}
26unsafe impl<Device: VkHandle<Handle = VkDevice> + Sync> Sync for BufferObject<Device> {}
27unsafe impl<Device: VkHandle<Handle = VkDevice> + Send> Send for BufferObject<Device> {}
28impl<Device: VkHandle<Handle = VkDevice>> DeviceChildHandle for BufferObject<Device> {
29    #[inline(always)]
30    fn device_handle(&self) -> VkDevice {
31        self.1.native_ptr()
32    }
33}
34impl<Device: crate::Device> DeviceChild for BufferObject<Device> {
35    type ConcreteDevice = Device;
36
37    #[inline(always)]
38    fn device(&self) -> &Self::ConcreteDevice {
39        &self.1
40    }
41}
42impl<Device: VkHandle<Handle = VkDevice>> Buffer for BufferObject<Device> {}
43impl<Device: VkHandle<Handle = VkDevice>> MemoryBound for BufferObject<Device> {
44    #[cfg(feature = "VK_KHR_get_memory_requirements2")]
45    type MemoryRequirementsInfo2<'b>
46        = BufferMemoryRequirementsInfo2<'b, Self>
47    where
48        Device: 'b;
49
50    #[implements]
51    fn requirements(&self) -> VkMemoryRequirements {
52        let mut p = core::mem::MaybeUninit::uninit();
53        unsafe {
54            crate::vkfn::get_buffer_memory_requirements(self.1.native_ptr(), self.0, p.as_mut_ptr());
55
56            p.assume_init()
57        }
58    }
59
60    #[cfg(feature = "VK_KHR_get_memory_requirements2")]
61    fn requirements2<'b>(&'b self) -> Self::MemoryRequirementsInfo2<'b> {
62        BufferMemoryRequirementsInfo2::new(self)
63    }
64
65    #[inline(always)]
66    #[implements]
67    fn bind(&mut self, memory: &(impl VkHandle<Handle = VkDeviceMemory> + ?Sized), offset: usize) -> crate::Result<()>
68    where
69        Self: VkHandleMut,
70    {
71        unsafe {
72            crate::vkfn::bind_buffer_memory(self.1.native_ptr(), self.0, memory.native_ptr(), offset as _)
73                .into_result()
74                .map(drop)
75        }
76    }
77}
78impl<Device: VkHandle<Handle = VkDevice>> BufferObject<Device> {
79    /// Constructs from raw values
80    /// # Safety
81    /// the resource must be created from the parent
82    pub const unsafe fn manage(handle: VkBuffer, parent: Device) -> Self {
83        Self(handle, parent)
84    }
85
86    /// Purges internal values (Drop will not be called for this resource)
87    pub const fn unmanage(self) -> (VkBuffer, Device) {
88        let v = self.0;
89        let p = unsafe { core::ptr::read(&self.1) };
90        core::mem::forget(self);
91
92        (v, p)
93    }
94}
95impl<Device: VkHandle<Handle = VkDevice> + Clone> BufferObject<&'_ Device> {
96    /// Owning parent object by cloning it.
97    #[inline(always)]
98    pub fn clone_parent(self) -> BufferObject<Device> {
99        let r = BufferObject(self.0, self.1.clone());
100        core::mem::forget(self);
101
102        r
103    }
104}
105impl<Device: crate::Device> BufferObject<Device> {
106    /// Create a new buffer object
107    /// # Failure
108    /// On failure, this command returns
109    ///
110    /// * `VK_ERROR_OUT_OF_HOST_MEMORY`
111    /// * `VK_ERROR_OUT_OF_DEVICE_MEMORY`
112    #[implements]
113    #[inline]
114    pub fn new(device: Device, info: &BufferCreateInfo) -> crate::Result<Self> {
115        Ok(unsafe { Self::manage(device.new_buffer_raw(info, None)?, device) })
116    }
117}
118
119#[derive(VkHandle, VkObject)]
120#[VkObject(type = VkBufferView::OBJECT_TYPE)]
121/// Opaque handle to a buffer view object
122pub struct BufferViewObject<Buffer: DeviceChildHandle>(VkBufferView, Buffer);
123#[implements]
124impl<Buffer: DeviceChildHandle> Drop for BufferViewObject<Buffer> {
125    fn drop(&mut self) {
126        unsafe {
127            crate::vkfn::destroy_buffer_view(self.1.device_handle(), self.0, core::ptr::null());
128        }
129    }
130}
131unsafe impl<Buffer: DeviceChildHandle + Sync> Sync for BufferViewObject<Buffer> {}
132unsafe impl<Buffer: DeviceChildHandle + Send> Send for BufferViewObject<Buffer> {}
133impl<Buffer: DeviceChildHandle> DeviceChildHandle for BufferViewObject<Buffer> {
134    #[inline(always)]
135    fn device_handle(&self) -> VkDevice {
136        self.1.device_handle()
137    }
138}
139impl<Buffer: DeviceChild> DeviceChild for BufferViewObject<Buffer> {
140    type ConcreteDevice = Buffer::ConcreteDevice;
141
142    #[inline(always)]
143    fn device(&self) -> &Self::ConcreteDevice {
144        self.1.device()
145    }
146}
147impl<Buffer: DeviceChildHandle> BufferView for BufferViewObject<Buffer> {}
148impl<Buffer: DeviceChildHandle> core::ops::Deref for BufferViewObject<Buffer> {
149    type Target = Buffer;
150
151    #[inline(always)]
152    fn deref(&self) -> &Buffer {
153        &self.1
154    }
155}
156impl<Buffer: DeviceChildHandle> BufferViewObject<Buffer> {
157    /// Constructs from raw values
158    /// # Safety
159    /// the resource must be created from the parent
160    pub const unsafe fn manage(handle: VkBufferView, parent: Buffer) -> Self {
161        Self(handle, parent)
162    }
163
164    /// Purges internal values (Drop will not be called for this resource)
165    pub const fn unmanage(self) -> (VkBufferView, Buffer) {
166        let v = self.0;
167        let p = unsafe { core::ptr::read(&self.1) };
168        core::mem::forget(self);
169
170        (v, p)
171    }
172}
173impl<Buffer: DeviceChildHandle + Clone> BufferViewObject<&'_ Buffer> {
174    /// Owning parent object by cloning it.
175    #[inline(always)]
176    pub fn clone_parent(self) -> BufferViewObject<Buffer> {
177        let r = BufferViewObject(self.0, self.1.clone());
178        core::mem::forget(self);
179
180        r
181    }
182}
183impl<Buffer: DeviceChild> BufferViewObject<Buffer> {
184    /// Create a new buffer view object
185    /// # Failure
186    /// On failure, this command returns
187    ///
188    /// * [`VK_ERROR_OUT_OF_HOST_MEMORY`]
189    /// * [`VK_ERROR_OUT_OF_DEVICE_MEMORY`]
190    #[implements]
191    #[inline]
192    pub fn new(buffer: Buffer, info: &BufferViewCreateInfo) -> crate::Result<Self> {
193        use crate::Device;
194
195        Ok(unsafe { Self::manage(buffer.device().new_buffer_view_raw(info, None)?, buffer) })
196    }
197}
198
199/// Builder structure specifying the parameters of a newly created buffer object
200#[repr(transparent)]
201#[derive(Clone)]
202pub struct BufferCreateInfo<'s>(VkBufferCreateInfo, core::marker::PhantomData<Option<&'s [u32]>>);
203impl<'s> BufferCreateInfo<'s> {
204    /// Creates a new buffer description with provided byte-size and usage flags
205    pub const fn new(byte_size: usize, usage: BufferUsage) -> Self {
206        Self(
207            VkBufferCreateInfo {
208                sType: VkBufferCreateInfo::TYPE,
209                pNext: core::ptr::null(),
210                flags: 0,
211                size: byte_size as _,
212                usage: usage.0,
213                sharingMode: VK_SHARING_MODE_EXCLUSIVE,
214                queueFamilyIndexCount: 0,
215                pQueueFamilyIndices: core::ptr::null(),
216            },
217            core::marker::PhantomData,
218        )
219    }
220
221    /// Creates a new buffer description which fits for a type
222    #[inline(always)]
223    pub const fn new_for_type<T>(usage: BufferUsage) -> Self {
224        Self::new(core::mem::size_of::<T>(), usage)
225    }
226
227    /// Wraps raw vulkan structure
228    /// # Safety
229    /// This function does not check any references/constraints
230    pub const unsafe fn from_raw(s: VkBufferCreateInfo) -> Self {
231        Self(s, core::marker::PhantomData)
232    }
233
234    /// Unwraps raw vulkan structure
235    /// # Safety
236    /// Lifetime constraints are removed
237    pub const unsafe fn into_raw(self) -> VkBufferCreateInfo {
238        self.0
239    }
240
241    /// A list of queue families that will access this buffer
242    pub const fn sharing_queue_families(mut self, indices: &'s [u32]) -> Self {
243        self.0.sharingMode = if indices.is_empty() {
244            VK_SHARING_MODE_EXCLUSIVE
245        } else {
246            VK_SHARING_MODE_CONCURRENT
247        };
248        self.0.queueFamilyIndexCount = indices.len() as _;
249        self.0.pQueueFamilyIndices = slice_as_ptr_empty_null(indices);
250
251        self
252    }
253
254    /// A bitmask of `BufferSparseBinding` specifying additional parameters of the buffer
255    pub const fn sparse_binding_opt(mut self, opt: BufferSparseBinding) -> Self {
256        self.0.flags = opt as _;
257        self
258    }
259
260    /// Merges usage flags
261    pub const fn with_usage(mut self, usage: BufferUsage) -> Self {
262        self.0.usage |= usage.0;
263        self
264    }
265
266    /// Overwrites usage flags
267    pub const fn set_usage(mut self, usage: BufferUsage) -> Self {
268        self.0.usage = usage.0;
269        self
270    }
271
272    pub const fn size(&self) -> VkDeviceSize {
273        self.0.size
274    }
275
276    pub const fn usage(&self) -> BufferUsage {
277        BufferUsage(self.0.usage)
278    }
279}
280impl crate::VulkanStructureProvider for BufferCreateInfo<'_> {
281    type RootStructure = VkBufferCreateInfo;
282
283    fn build<'r, 's: 'r>(&'s mut self, root: &'s mut Self::RootStructure) -> &'r mut crate::GenericVulkanStructure {
284        *root = self.0.clone();
285        root.as_generic_mut()
286    }
287}
288
289#[repr(transparent)]
290#[derive(Clone)]
291pub struct BufferViewCreateInfo<'d>(
292    VkBufferViewCreateInfo,
293    core::marker::PhantomData<&'d dyn VkHandle<Handle = VkBuffer>>,
294);
295impl<'d> BufferViewCreateInfo<'d> {
296    #[inline]
297    pub fn new(
298        buffer: &'d (impl VkHandle<Handle = VkBuffer> + ?Sized),
299        format: VkFormat,
300        range: core::ops::Range<VkDeviceSize>,
301    ) -> Self {
302        Self(
303            VkBufferViewCreateInfo {
304                sType: VkBufferViewCreateInfo::TYPE,
305                pNext: core::ptr::null(),
306                flags: 0,
307                buffer: buffer.native_ptr(),
308                format,
309                offset: range.start,
310                range: range.end - range.start,
311            },
312            core::marker::PhantomData,
313        )
314    }
315
316    pub const unsafe fn from_raw(raw: VkBufferViewCreateInfo) -> Self {
317        Self(raw, core::marker::PhantomData)
318    }
319
320    pub const fn into_raw(self) -> VkBufferViewCreateInfo {
321        self.0
322    }
323}
324
325#[cfg(feature = "VK_KHR_get_memory_requirements2")]
326pub struct BufferMemoryRequirementsInfo2<'b, Buffer: VkHandle<Handle = VkBuffer> + 'b>(
327    VkBufferMemoryRequirementsInfo2KHR,
328    &'b Buffer,
329);
330#[cfg(feature = "VK_KHR_get_memory_requirements2")]
331impl<'b, Buffer: VkHandle<Handle = VkBuffer> + 'b> BufferMemoryRequirementsInfo2<'b, Buffer> {
332    pub fn new(buffer: &'b Buffer) -> Self {
333        Self(
334            VkBufferMemoryRequirementsInfo2KHR {
335                sType: VkBufferMemoryRequirementsInfo2KHR::TYPE,
336                pNext: core::ptr::null(),
337                buffer: buffer.native_ptr(),
338            },
339            buffer,
340        )
341    }
342
343    #[implements("Allow1_1APIs")]
344    pub fn query(self, sink: &mut core::mem::MaybeUninit<VkMemoryRequirements2KHR>)
345    where
346        Buffer: crate::DeviceChild,
347    {
348        unsafe {
349            crate::vkfn::get_buffer_memory_requirements2(self.1.device().native_ptr(), &self.0, sink.as_mut_ptr());
350        }
351    }
352}
353#[cfg(feature = "VK_KHR_get_memory_requirements2")]
354impl<Buffer: VkHandle<Handle = VkBuffer>> AsRef<VkBufferMemoryRequirementsInfo2KHR>
355    for BufferMemoryRequirementsInfo2<'_, Buffer>
356{
357    fn as_ref(&self) -> &VkBufferMemoryRequirementsInfo2KHR {
358        &self.0
359    }
360}
361
362#[cfg(feature = "VK_KHR_bind_memory2")]
363#[repr(transparent)]
364pub struct BindBufferMemoryInfo<'b>(
365    VkBindBufferMemoryInfoKHR,
366    core::marker::PhantomData<(VkHandleRef<'b, VkBuffer>, VkHandleRef<'b, VkDeviceMemory>)>,
367);
368#[cfg(feature = "VK_KHR_bind_memory2")]
369impl<'b> BindBufferMemoryInfo<'b> {
370    pub fn new(
371        buffer: &'b (impl VkHandle<Handle = VkBuffer> + ?Sized),
372        memory: &'b (impl VkHandle<Handle = VkDeviceMemory> + ?Sized),
373        offset: DeviceSize,
374    ) -> Self {
375        Self(
376            VkBindBufferMemoryInfoKHR {
377                sType: VkBindBufferMemoryInfoKHR::TYPE,
378                pNext: core::ptr::null(),
379                buffer: buffer.native_ptr(),
380                memory: memory.native_ptr(),
381                memoryOffset: offset,
382            },
383            core::marker::PhantomData,
384        )
385    }
386
387    pub const unsafe fn from_raw(raw: VkBindBufferMemoryInfoKHR) -> Self {
388        Self(raw, core::marker::PhantomData)
389    }
390
391    pub const fn into_raw(self) -> VkBindBufferMemoryInfoKHR {
392        self.0
393    }
394}
395
396/// Bitmask specifying allowed usage of a buffer
397#[derive(Clone, Copy, PartialEq, Eq, Debug)]
398#[repr(transparent)]
399pub struct BufferUsage(pub VkBufferUsageFlags);
400impl BufferUsage {
401    /// Specifies that the buffer can be used as the source of a transfer command
402    pub const TRANSFER_SRC: Self = Self(VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
403    /// Specifies that the buffer can be used as the destination of a transfer command
404    pub const TRANSFER_DEST: Self = Self(VK_BUFFER_USAGE_TRANSFER_DST_BIT);
405    /// Specifies that the buffer can be used to create a `BufferView` suitable for
406    /// occupying a `DescriptorSet` slot of type `VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER`
407    pub const UNIFORM_TEXEL_BUFFER: Self = Self(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT);
408    /// Specifies that the buffer can be used to create a `BufferView` suitable for
409    /// occupying a `DescriptorSet` slot of type `VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER`
410    pub const STORAGE_TEXEL_BUFFER: Self = Self(VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT);
411    /// Specifies that the buffer can be used in a `DescriptorBufferInfo` suitable for
412    /// occupying a `DescriptorSet` slot either of type `VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER` or `VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC`
413    pub const UNIFORM_BUFFER: Self = Self(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
414    /// Specifies that the buffer can be used in a `DescriptorBufferInfo` suitable for
415    /// occupying a `DescriptorSet` slot either of type `VK_DESCRIPTOR_TYPE_STORAGE_BUFFER` or `VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC`
416    pub const STORAGE_BUFFER: Self = Self(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
417    /// Specifies that the buffer is suitable for passing as the `buffer` parameter to `DrawCommandBuffer::bind_index_buffer`
418    pub const INDEX_BUFFER: Self = Self(VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
419    /// Specifies that the buffer is suitable for passing as an element of the `buffers` array to `DrawCommandBuffer::bind_vertex_buffers`
420    pub const VERTEX_BUFFER: Self = Self(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
421    /// Specifies that the buffer is suitable for passing as the `buffer` parameter to
422    /// `DrawCommandBuffer::draw_indirect`, `DrawCommandBuffer::draw_indexed_indirect`, or `ComputeCommandBuffer::dispatch_indirect`
423    pub const INDIRECT_BUFFER: Self = Self(VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
424
425    /// Specifies that the buffer can be used as the source of a transfer command
426    pub const fn transfer_src(self) -> Self {
427        Self(self.0 | Self::TRANSFER_SRC.0)
428    }
429    /// Specifies that the buffer can be used as the destination of a transfer command
430    pub const fn transfer_dest(self) -> Self {
431        Self(self.0 | Self::TRANSFER_DEST.0)
432    }
433    /// Specifies that the buffer can be used to create a `BufferView` suitable for
434    /// occupying a `DescriptorSet` slot of type `VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER`
435    pub const fn uniform_texel_buffer(self) -> Self {
436        Self(self.0 | Self::UNIFORM_TEXEL_BUFFER.0)
437    }
438    /// Specifies that the buffer can be used to create a `BufferView` suitable for
439    /// occupying a `DescriptorSet` slot of type `VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER`
440    pub const fn storage_texel_buffer(self) -> Self {
441        Self(self.0 | Self::STORAGE_TEXEL_BUFFER.0)
442    }
443    /// Specifies that the buffer can be used in a `DescriptorBufferInfo` suitable for
444    /// occupying a `DescriptorSet` slot either of type `VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER` or `VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC`
445    pub const fn uniform_buffer(self) -> Self {
446        Self(self.0 | Self::UNIFORM_BUFFER.0)
447    }
448    /// Specifies that the buffer can be used in a `DescriptorBufferInfo` suitable for
449    /// occupying a `DescriptorSet` slot either of type `VK_DESCRIPTOR_TYPE_STORAGE_BUFFER` or `VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC`
450    pub const fn storage_buffer(self) -> Self {
451        Self(self.0 | Self::STORAGE_BUFFER.0)
452    }
453    /// Specifies that the buffer is suitable for passing as the `buffer` parameter to `DrawCommandBuffer::bind_index_buffer`
454    pub const fn index_buffer(self) -> Self {
455        Self(self.0 | Self::INDEX_BUFFER.0)
456    }
457    /// Specifies that the buffer is suitable for passing as an element of the `buffers` array to `DrawCommandBuffer::bind_vertex_buffers`
458    pub const fn vertex_buffer(self) -> Self {
459        Self(self.0 | Self::VERTEX_BUFFER.0)
460    }
461    /// Specifies that the buffer is suitable for passing as the `buffer` parameter to
462    /// `DrawCommandBuffer::draw_indirect`, `DrawCommandBuffer::draw_indexed_indirect`, or `ComputeCommandBuffer::dispatch_indirect`
463    pub const fn indirect_buffer(self) -> Self {
464        Self(self.0 | Self::INDIRECT_BUFFER.0)
465    }
466
467    /// merge two flags (const alias of BitOr)
468    pub const fn merge(self, other: Self) -> Self {
469        Self(self.0 | other.0)
470    }
471
472    /// Generates a default access type mask
473    pub const fn default_access_mask(self) -> VkAccessFlags {
474        let mut bits = 0;
475        if (self.0 & Self::TRANSFER_SRC.0) != 0 {
476            bits |= VK_ACCESS_TRANSFER_READ_BIT;
477        }
478        if (self.0 & Self::TRANSFER_DEST.0) != 0 {
479            bits |= VK_ACCESS_TRANSFER_WRITE_BIT;
480        }
481        if (self.0 & Self::UNIFORM_TEXEL_BUFFER.0) != 0 {
482            bits |= VK_ACCESS_UNIFORM_READ_BIT;
483        }
484        if (self.0 & Self::STORAGE_TEXEL_BUFFER.0) != 0 {
485            bits |= VK_ACCESS_UNIFORM_READ_BIT;
486        }
487        if (self.0 & Self::UNIFORM_BUFFER.0) != 0 {
488            bits |= VK_ACCESS_UNIFORM_READ_BIT;
489        }
490        if (self.0 & Self::STORAGE_BUFFER.0) != 0 {
491            bits |= VK_ACCESS_UNIFORM_READ_BIT;
492        }
493        if (self.0 & Self::INDEX_BUFFER.0) != 0 {
494            bits |= VK_ACCESS_INDEX_READ_BIT;
495        }
496        if (self.0 & Self::VERTEX_BUFFER.0) != 0 {
497            bits |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
498        }
499        if (self.0 & Self::INDIRECT_BUFFER.0) != 0 {
500            bits |= VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
501        }
502        bits
503    }
504
505    /// Determines if flag contains usage of uniform-buffer
506    pub const fn is_uniform(self) -> bool {
507        (self.0 & (Self::UNIFORM_BUFFER.0 | Self::UNIFORM_TEXEL_BUFFER.0)) != 0
508    }
509    /// Determines if flag contains usage of storage-buffer
510    pub const fn is_storage(self) -> bool {
511        (self.0 & (Self::STORAGE_BUFFER.0 | Self::STORAGE_TEXEL_BUFFER.0)) != 0
512    }
513}
514impl core::ops::BitOr for BufferUsage {
515    type Output = Self;
516
517    #[inline(always)]
518    fn bitor(self, other: Self) -> Self {
519        BufferUsage(self.0 | other.0)
520    }
521}
522impl core::ops::BitOrAssign for BufferUsage {
523    #[inline(always)]
524    fn bitor_assign(&mut self, other: Self) {
525        self.0 |= other.0;
526    }
527}
528impl From<BufferUsage> for VkBufferUsageFlags {
529    #[inline(always)]
530    fn from(value: BufferUsage) -> Self {
531        value.0
532    }
533}
534
535/// Bitset specifying additional parameters of a buffer
536#[derive(Debug, Clone, Copy, PartialEq, Eq)]
537#[repr(C)]
538pub enum BufferSparseBinding {
539    /// No sparse binding features
540    None = 0,
541    /// the buffer will be backed using sparse memory binding
542    Bound = VK_BUFFER_CREATE_SPARSE_BINDING_BIT as _,
543    /// the buffer can be partially backed using sparse memory binding.
544    Residency = (VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) as _,
545    /// the buffer will be backed using sparse memory binding with memory ranges
546    /// that might also simultaneously be backing another buffer (or another portion of the same buffer)
547    Aliased = (VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) as _,
548    /// Aliased and Residency
549    Both = (VK_BUFFER_CREATE_SPARSE_BINDING_BIT
550        | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT
551        | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) as _,
552}