bort_vk/
memory_pool.rs

1use crate::{AllocatorAccess, Device, MemoryAllocator};
2use ash::{prelude::VkResult, vk};
3use std::sync::Arc;
4
5pub struct MemoryPool {
6    inner: bort_vma::AllocatorPool,
7    properties: MemoryPoolPropeties,
8
9    // dependencies
10    memory_allocator: Arc<MemoryAllocator>,
11}
12
13impl MemoryPool {
14    pub fn new(
15        memory_allocator: Arc<MemoryAllocator>,
16        properties: MemoryPoolPropeties,
17    ) -> VkResult<Self> {
18        let create_info = properties.create_info();
19
20        let inner =
21            bort_vma::AllocatorPool::new(memory_allocator.inner_arc().clone(), &create_info)?;
22
23        Ok(Self {
24            inner,
25            properties,
26            memory_allocator,
27        })
28    }
29
30    pub unsafe fn new_from_create_info(
31        memory_allocator: Arc<MemoryAllocator>,
32        create_info: &bort_vma::PoolCreateInfo,
33    ) -> VkResult<Self> {
34        let inner =
35            bort_vma::AllocatorPool::new(memory_allocator.inner_arc().clone(), create_info)?;
36
37        let properties = MemoryPoolPropeties::from_create_info(create_info);
38
39        Ok(Self {
40            inner,
41            properties,
42            memory_allocator,
43        })
44    }
45
46    // Getters
47
48    /// Access the `bort_vma::AllocatorPool` struct that `self` contains. Allows you to access pool-related
49    /// vma related functions.
50    #[inline]
51    pub fn inner(&self) -> &bort_vma::AllocatorPool {
52        &self.inner
53    }
54
55    #[inline]
56    pub fn properties(&self) -> MemoryPoolPropeties {
57        self.properties
58    }
59}
60
61impl AllocatorAccess for MemoryPool {
62    fn vma_alloc_ref(&self) -> &dyn bort_vma::Alloc {
63        &self.inner
64    }
65
66    #[inline]
67    fn device(&self) -> &Arc<Device> {
68        self.memory_allocator.device()
69    }
70}
71
72// `bort_vma::PoolCreateInfo` would have been pretty good here (unlike the ash create_infos and
73// their dangling pnext pointers) but that would require explicit lifetime specifiers for
74// `MemoryPool` which propogates up every stuct containing it which is kinda a pain in the ass
75// for goshenite...
76#[derive(Clone, Copy)]
77pub struct MemoryPoolPropeties {
78    /// Use combination of `VmaPoolCreateFlagBits`.
79    pub flags: bort_vma::AllocatorPoolCreateFlags,
80
81    /// Vulkan memory type index to allocate this pool from.
82    pub memory_type_index: u32,
83
84    /// Size of a single `VkDeviceMemory` block to be allocated as part of this pool, in bytes. Optional.
85    ///
86    /// Specify nonzero to set explicit, constant size of memory blocks used by this
87    /// pool.
88    ///
89    /// Leave 0 to use default and let the library manage block sizes automatically.
90    /// Sizes of particular blocks may vary.
91    /// In this case, the pool will also support dedicated allocations.
92    pub block_size: vk::DeviceSize,
93
94    /// Minimum number of blocks to be always allocated in this pool, even if they stay empty.
95    ///
96    /// Set to 0 to have no preallocated blocks and allow the pool be completely empty.
97    pub min_block_count: usize,
98
99    /// Maximum number of blocks that can be allocated in this pool. Optional.
100    ///
101    /// Set to 0 to use default, which is `SIZE_MAX`, which means no limit.
102    ///
103    /// Set to same value as VmaPoolCreateInfo::minBlockCount to have fixed amount of memory allocated
104    /// throughout whole lifetime of this pool.
105    pub max_block_count: usize,
106
107    /// A floating-point value between 0 and 1, indicating the priority of the allocations in this pool relative to other memory allocations.
108    ///
109    /// It is used only when #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT flag was used during creation of the #VmaAllocator object.
110    /// Otherwise, this variable is ignored.
111    pub priority: f32,
112
113    /// Additional minimum alignment to be used for all allocations created from this pool. Can be 0.
114    ///
115    /// Leave 0 (default) not to impose any additional alignment. If not 0, it must be a power of two.
116    /// It can be useful in cases where alignment returned by Vulkan by functions like `vkGetBufferMemoryRequirements` is not enough,
117    /// e.g. when doing interop with OpenGL.
118    pub min_allocation_alignment: vk::DeviceSize,
119}
120
121impl Default for MemoryPoolPropeties {
122    fn default() -> Self {
123        Self {
124            flags: bort_vma::AllocatorPoolCreateFlags::empty(),
125            memory_type_index: 0,
126            block_size: 0,
127            min_block_count: 0,
128            max_block_count: 0,
129            priority: 0.,
130            min_allocation_alignment: 0,
131        }
132    }
133}
134
135impl MemoryPoolPropeties {
136    pub fn create_info(&self) -> bort_vma::PoolCreateInfo {
137        bort_vma::PoolCreateInfo::new()
138            .flags(self.flags)
139            .memory_type_index(self.memory_type_index)
140            .block_size(self.block_size)
141            .min_block_count(self.min_block_count)
142            .max_block_count(self.max_block_count)
143            .priority(self.priority)
144            .min_allocation_alignment(self.min_allocation_alignment)
145    }
146
147    pub fn from_create_info(value: &bort_vma::PoolCreateInfo) -> Self {
148        Self {
149            flags: value.get_flags(),
150            memory_type_index: value.get_memory_type_index(),
151            block_size: value.get_block_size(),
152            min_block_count: value.get_min_block_count(),
153            max_block_count: value.get_max_block_count(),
154            priority: value.get_priority(),
155            min_allocation_alignment: value.get_min_allocation_alignment(),
156        }
157    }
158}