1use 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}