1use alloc::vec::Vec;
4use core::mem;
5
6use vulkanalia::ResultExt;
7use vulkanalia::prelude::v1_0::*;
8
9use crate::allocator::Allocator;
10use crate::enums::MemoryUsage;
11use crate::flags::AllocationCreateFlags;
12use crate::pool::{Pool, PoolHandle};
13use crate::vma::*;
14
15#[derive(Copy, Clone, Debug, Default)]
16pub struct AllocationOptions {
17 pub flags: AllocationCreateFlags,
18 pub usage: MemoryUsage,
19 pub required_flags: vk::MemoryPropertyFlags,
20 pub preferred_flags: vk::MemoryPropertyFlags,
21 pub memory_type_bits: u32,
22 pub priority: f32,
23}
24
25impl From<&AllocationOptions> for VmaAllocationCreateInfo {
26 fn from(value: &AllocationOptions) -> Self {
27 Self {
28 flags: value.flags.bits(),
29 usage: value.usage.into(),
30 requiredFlags: value.required_flags,
31 preferredFlags: value.preferred_flags,
32 memoryTypeBits: value.memory_type_bits,
33 pool: core::ptr::null_mut(),
34 pUserData: core::ptr::null_mut(),
35 priority: value.priority,
36 }
37 }
38}
39
40#[repr(transparent)]
41#[derive(Copy, Clone, Debug)]
42pub struct Allocation(pub(crate) VmaAllocation);
43
44unsafe impl Send for Allocation {}
45unsafe impl Sync for Allocation {}
46
47pub trait Alloc {
48 fn allocator(&self) -> &Allocator;
49
50 fn pool(&self) -> PoolHandle;
51
52 unsafe fn find_memory_type_index(
53 &self,
54 memory_type_bits: u32,
55 options: &AllocationOptions,
56 ) -> VkResult<u32> {
57 let mut info: VmaAllocationCreateInfo = options.into();
58 info.pool = self.pool().0;
59
60 let mut memory_type_index = 0;
61 vmaFindMemoryTypeIndex(
62 self.allocator().0,
63 memory_type_bits,
64 &info,
65 &mut memory_type_index,
66 )
67 .result()?;
68
69 Ok(memory_type_index)
70 }
71
72 unsafe fn find_memory_type_index_for_buffer_info(
73 &self,
74 buffer_info: impl vk::Cast<Target = vk::BufferCreateInfo>,
75 options: &AllocationOptions,
76 ) -> VkResult<u32> {
77 let mut info: VmaAllocationCreateInfo = options.into();
78 info.pool = self.pool().0;
79
80 let mut memory_type_index = 0;
81 vmaFindMemoryTypeIndexForBufferInfo(
82 self.allocator().0,
83 buffer_info.as_ref(),
84 &info,
85 &mut memory_type_index,
86 )
87 .result()?;
88
89 Ok(memory_type_index)
90 }
91
92 unsafe fn find_memory_type_index_for_image_info(
93 &self,
94 image_info: impl vk::Cast<Target = vk::ImageCreateInfo>,
95 options: &AllocationOptions,
96 ) -> VkResult<u32> {
97 let mut info: VmaAllocationCreateInfo = options.into();
98 info.pool = self.pool().0;
99
100 let mut memory_type_index = 0;
101 vmaFindMemoryTypeIndexForImageInfo(
102 self.allocator().0,
103 image_info.as_ref(),
104 &info,
105 &mut memory_type_index,
106 )
107 .result()?;
108
109 Ok(memory_type_index)
110 }
111
112 unsafe fn allocate_memory(
113 &self,
114 requirements: impl vk::Cast<Target = vk::MemoryRequirements>,
115 options: &AllocationOptions,
116 ) -> VkResult<Allocation> {
117 let mut info: VmaAllocationCreateInfo = options.into();
118 info.pool = self.pool().0;
119
120 let mut allocation: VmaAllocation = mem::zeroed();
121 vmaAllocateMemory(
122 self.allocator().0,
123 requirements.as_ref(),
124 &info,
125 &mut allocation,
126 core::ptr::null_mut(),
127 )
128 .result()?;
129
130 Ok(Allocation(allocation))
131 }
132
133 unsafe fn allocate_memory_pages(
134 &self,
135 requirements: impl vk::Cast<Target = vk::MemoryRequirements>,
136 options: &AllocationOptions,
137 num_pages: usize,
138 ) -> VkResult<Vec<Allocation>> {
139 let mut info: VmaAllocationCreateInfo = options.into();
140 info.pool = self.pool().0;
141
142 let mut allocations = Vec::with_capacity(num_pages);
143 vmaAllocateMemoryPages(
144 self.allocator().0,
145 requirements.as_ref(),
146 &info,
147 num_pages,
148 allocations.as_mut_ptr(),
149 core::ptr::null_mut(),
150 )
151 .result()?;
152
153 allocations.set_len(num_pages);
154
155 Ok(allocations.into_iter().map(Allocation).collect())
156 }
157
158 unsafe fn allocate_memory_for_buffer(
159 &self,
160 buffer: vk::Buffer,
161 options: &AllocationOptions,
162 ) -> VkResult<Allocation> {
163 let mut info: VmaAllocationCreateInfo = options.into();
164 info.pool = self.pool().0;
165
166 let mut allocation: VmaAllocation = mem::zeroed();
167 vmaAllocateMemoryForBuffer(
168 self.allocator().0,
169 buffer,
170 &info,
171 &mut allocation,
172 core::ptr::null_mut(),
173 )
174 .result()?;
175
176 Ok(Allocation(allocation))
177 }
178
179 unsafe fn allocate_memory_for_image(
180 &self,
181 image: vk::Image,
182 options: &AllocationOptions,
183 ) -> VkResult<Allocation> {
184 let mut info: VmaAllocationCreateInfo = options.into();
185 info.pool = self.pool().0;
186
187 let mut allocation: VmaAllocation = mem::zeroed();
188 vmaAllocateMemoryForImage(
189 self.allocator().0,
190 image,
191 &info,
192 &mut allocation,
193 core::ptr::null_mut(),
194 )
195 .result()?;
196
197 Ok(Allocation(allocation))
198 }
199
200 unsafe fn create_buffer(
201 &self,
202 buffer_info: impl vk::Cast<Target = vk::BufferCreateInfo>,
203 options: &AllocationOptions,
204 ) -> VkResult<(vk::Buffer, Allocation)> {
205 let mut info: VmaAllocationCreateInfo = options.into();
206 info.pool = self.pool().0;
207
208 let mut buffer = vk::Buffer::null();
209 let mut allocation: VmaAllocation = mem::zeroed();
210 vmaCreateBuffer(
211 self.allocator().0,
212 buffer_info.as_ref(),
213 &info,
214 &mut buffer,
215 &mut allocation,
216 core::ptr::null_mut(),
217 )
218 .result()?;
219
220 Ok((buffer, Allocation(allocation)))
221 }
222
223 unsafe fn create_buffer_with_alignment(
224 &self,
225 buffer_info: impl vk::Cast<Target = vk::BufferCreateInfo>,
226 options: &AllocationOptions,
227 min_alignment: vk::DeviceSize,
228 ) -> VkResult<(vk::Buffer, Allocation)> {
229 let mut info: VmaAllocationCreateInfo = options.into();
230 info.pool = self.pool().0;
231
232 let mut buffer = vk::Buffer::null();
233 let mut allocation: VmaAllocation = mem::zeroed();
234 vmaCreateBufferWithAlignment(
235 self.allocator().0,
236 buffer_info.as_ref(),
237 &info,
238 min_alignment,
239 &mut buffer,
240 &mut allocation,
241 core::ptr::null_mut(),
242 )
243 .result()?;
244
245 Ok((buffer, Allocation(allocation)))
246 }
247
248 unsafe fn create_image(
249 &self,
250 image_info: impl vk::Cast<Target = vk::ImageCreateInfo>,
251 options: &AllocationOptions,
252 ) -> VkResult<(vk::Image, Allocation)> {
253 let mut info: VmaAllocationCreateInfo = options.into();
254 info.pool = self.pool().0;
255
256 let mut image = vk::Image::null();
257 let mut allocation: VmaAllocation = mem::zeroed();
258 vmaCreateImage(
259 self.allocator().0,
260 image_info.as_ref(),
261 &info,
262 &mut image,
263 &mut allocation,
264 core::ptr::null_mut(),
265 )
266 .result()?;
267
268 Ok((image, Allocation(allocation)))
269 }
270}
271
272impl Alloc for Allocator {
273 fn allocator(&self) -> &Allocator {
274 self
275 }
276
277 fn pool(&self) -> PoolHandle {
278 PoolHandle::DEFAULT
279 }
280}
281
282impl Alloc for Pool {
283 fn allocator(&self) -> &Allocator {
284 &self.allocator
285 }
286
287 fn pool(&self) -> PoolHandle {
288 self.handle
289 }
290}