vulkanalia_vma/
allocation.rs

1// SPDX-License-Identifier: Apache-2.0
2
3use 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}