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}