vulkanalia_vma/
pool.rs

1// SPDX-License-Identifier: Apache-2.0
2
3use alloc::sync::Arc;
4use core::ffi::CStr;
5use core::marker::PhantomData;
6use core::mem;
7use core::ptr::NonNull;
8
9use vulkanalia::prelude::v1_0::*;
10use vulkanalia::{ResultExt, VkResult};
11
12use crate::allocator::Allocator;
13use crate::flags::PoolCreateFlags;
14use crate::vma::*;
15
16#[derive(Copy, Clone, Debug)]
17pub struct PoolHandle(pub(crate) VmaPool);
18
19impl PoolHandle {
20    pub const DEFAULT: Self = Self(core::ptr::null_mut());
21}
22
23unsafe impl Send for PoolHandle {}
24unsafe impl Sync for PoolHandle {}
25
26#[derive(Copy, Clone, Debug)]
27pub struct PoolOptions<'a> {
28    pub memory_type_index: u32,
29    pub flags: PoolCreateFlags,
30    pub block_size: vk::DeviceSize,
31    pub min_block_count: usize,
32    pub max_block_count: usize,
33    pub priority: f32,
34    pub min_allocation_alignment: vk::DeviceSize,
35    pub next: *mut core::ffi::c_void,
36    _marker: PhantomData<&'a ()>,
37}
38
39impl<'a> PoolOptions<'a> {
40    pub fn push_next<T>(mut self, next: &'a mut impl vk::Cast<Target = T>) -> Self
41    where
42        T: vk::ExtendsMemoryAllocateInfo,
43    {
44        self.next = vk::merge(self.next, NonNull::from(next).cast());
45        self
46    }
47}
48
49impl Default for PoolOptions<'_> {
50    fn default() -> Self {
51        Self {
52            memory_type_index: 0,
53            flags: PoolCreateFlags::empty(),
54            block_size: 0,
55            min_block_count: 0,
56            max_block_count: 0,
57            priority: 0.0,
58            min_allocation_alignment: 0,
59            next: core::ptr::null_mut(),
60            _marker: PhantomData,
61        }
62    }
63}
64
65#[derive(Clone, Debug)]
66pub struct Pool {
67    pub(crate) allocator: Arc<Allocator>,
68    pub(crate) handle: PoolHandle,
69}
70
71impl Allocator {
72    pub fn create_pool(self: &Arc<Self>, options: &PoolOptions) -> VkResult<Pool> {
73        let info = VmaPoolCreateInfo {
74            memoryTypeIndex: options.memory_type_index,
75            flags: options.flags.bits(),
76            blockSize: options.block_size,
77            minBlockCount: options.min_block_count,
78            maxBlockCount: options.max_block_count,
79            priority: options.priority,
80            minAllocationAlignment: options.min_allocation_alignment,
81            pMemoryAllocateNext: options.next,
82        };
83
84        let handle = unsafe {
85            let mut pool: VmaPool = mem::zeroed();
86            vmaCreatePool(self.0, &info, &mut pool).result()?;
87            PoolHandle(pool)
88        };
89
90        Ok(Pool {
91            allocator: self.clone(),
92            handle,
93        })
94    }
95
96    pub fn get_default_pool(self: &Arc<Self>) -> Pool {
97        Pool {
98            allocator: self.clone(),
99            handle: PoolHandle::DEFAULT,
100        }
101    }
102}
103
104impl Pool {
105    pub fn name(&self) -> Option<&CStr> {
106        if self.handle.0.is_null() {
107            return None;
108        }
109
110        unsafe {
111            let mut name = core::ptr::null();
112            vmaGetPoolName(self.allocator.0, self.handle.0, &mut name);
113            if !name.is_null() {
114                Some(CStr::from_ptr(name))
115            } else {
116                None
117            }
118        }
119    }
120
121    pub fn set_name(&self, name: Option<&CStr>) {
122        if self.handle.0.is_null() {
123            return;
124        }
125
126        let name = name.map_or(core::ptr::null(), CStr::as_ptr);
127        unsafe { vmaSetPoolName(self.allocator.0, self.handle.0, name) };
128    }
129
130    pub fn get_statistics(&self) -> VkResult<VmaStatistics> {
131        unsafe {
132            let mut statistics: VmaStatistics = mem::zeroed();
133            vmaGetPoolStatistics(self.allocator.0, self.handle.0, &mut statistics);
134            Ok(statistics)
135        }
136    }
137
138    pub fn calculate_statistics(&self) -> VkResult<VmaDetailedStatistics> {
139        unsafe {
140            let mut statistics: VmaDetailedStatistics = mem::zeroed();
141            vmaCalculatePoolStatistics(self.allocator.0, self.handle.0, &mut statistics);
142            Ok(statistics)
143        }
144    }
145
146    pub fn check_corruption(&self) -> VkResult<()> {
147        unsafe { vmaCheckPoolCorruption(self.allocator.0, self.handle.0).result() }
148    }
149}
150
151impl Drop for Pool {
152    fn drop(&mut self) {
153        unsafe { vmaDestroyPool(self.allocator.0, self.handle.0) };
154        self.handle = PoolHandle::DEFAULT;
155    }
156}