vk_mem/
virtual_block.rs

1use crate::ffi;
2use ash::prelude::VkResult;
3use std::mem;
4
5use crate::definitions::*;
6
7/// Handle to a virtual block object that allows to use core allocation algorithm without allocating any real GPU memory.
8///
9/// For more info: <https://gpuopen-librariesandsdks.github.io/VulkanMemoryAllocator/html/virtual_allocator.html>
10pub struct VirtualBlock {
11    internal: ffi::VmaVirtualBlock,
12}
13
14/// Represents single memory allocation done inside VirtualBlock.
15#[derive(Debug)]
16pub struct VirtualAllocation(ffi::VmaVirtualAllocation);
17unsafe impl Send for VirtualAllocation {}
18unsafe impl Sync for VirtualAllocation {}
19
20impl VirtualBlock {
21    /// Creates new VirtualBlock object.
22    pub fn new(create_info: VirtualBlockCreateInfo) -> VkResult<Self> {
23        unsafe {
24            let mut internal: ffi::VmaVirtualBlock = mem::zeroed();
25            let raw_info = ffi::VmaVirtualBlockCreateInfo {
26                size: create_info.size,
27                flags: create_info.flags.bits(),
28                pAllocationCallbacks: create_info
29                    .allocation_callbacks
30                    .map(|a| std::mem::transmute(a))
31                    .unwrap_or(std::ptr::null()),
32            };
33            ffi::vmaCreateVirtualBlock(&raw_info, &mut internal).result()?;
34
35            Ok(VirtualBlock { internal })
36        }
37    }
38
39    /// Allocates new virtual allocation inside given VirtualBlock.
40    ///
41    /// Possible error values:
42    ///
43    /// - `ash::vk::Result::ERROR_OUT_OF_DEVICE_MEMORY` - Allocation failed due to not enough free space in the virtual block.
44    ///     (despite the function doesn't ever allocate actual GPU memory)
45    pub unsafe fn allocate(
46        &mut self,
47        allocation_info: VirtualAllocationCreateInfo,
48    ) -> VkResult<(VirtualAllocation, u64)> {
49        let create_info: ffi::VmaVirtualAllocationCreateInfo = allocation_info.into();
50        let mut allocation: ffi::VmaVirtualAllocation = std::mem::zeroed();
51        let mut offset = 0;
52        ffi::vmaVirtualAllocate(self.internal, &create_info, &mut allocation, &mut offset)
53            .result()?;
54        Ok((VirtualAllocation(allocation), offset))
55    }
56
57    /// Frees virtual allocation inside given VirtualBlock.
58    ///
59    /// It is correct to call this function with `allocation == VK_NULL_HANDLE` - it does nothing.
60    pub unsafe fn free(&mut self, allocation: &mut VirtualAllocation) {
61        ffi::vmaVirtualFree(self.internal, allocation.0);
62    }
63
64    /// Frees all virtual allocations inside given VirtualBlock.
65    ///
66    /// You must either call this function or free each virtual allocation individually with vmaVirtualFree()
67    /// before destroying a virtual block. Otherwise, an assert is called.
68    ///
69    /// If you keep pointer to some additional metadata associated with your virtual allocation in its `user_data`,
70    /// don't forget to free it as well.
71    ///
72    /// Any VirtualAllocations created previously in the VirtualBlock will no longer be valid!
73    pub unsafe fn clear(&mut self) {
74        ffi::vmaClearVirtualBlock(self.internal);
75    }
76
77    /// Returns information about a specific virtual allocation within a virtual block, like its size and user_data pointer.
78    pub unsafe fn get_allocation_info(
79        &self,
80        allocation: &VirtualAllocation,
81    ) -> VkResult<VirtualAllocationInfo> {
82        let mut allocation_info: ffi::VmaVirtualAllocationInfo = mem::zeroed();
83        ffi::vmaGetVirtualAllocationInfo(self.internal, allocation.0, &mut allocation_info);
84        Ok(allocation_info.into())
85    }
86
87    /// Changes custom pointer associated with given virtual allocation.
88    pub unsafe fn set_allocation_user_data(
89        &self,
90        allocation: &mut VirtualAllocation,
91        user_data: *mut ::std::os::raw::c_void,
92    ) {
93        ffi::vmaSetVirtualAllocationUserData(self.internal, allocation.0, user_data);
94    }
95}
96
97/// Custom `Drop` implementation to clean up internal VirtualBlock instance
98impl Drop for VirtualBlock {
99    fn drop(&mut self) {
100        unsafe {
101            ffi::vmaDestroyVirtualBlock(self.internal);
102            self.internal = std::ptr::null_mut();
103        }
104    }
105}