1mod allocation;
25mod allocator;
26mod block;
27mod chain;
28mod granularity;
29mod host;
30mod linear;
31mod metadata;
32mod policy;
33mod resource;
34mod selector;
35mod synchronized;
36pub use synchronized::{SynchronizedAllocator, SynchronizedVirtualBlock};
37mod tlsf;
38pub mod virtual_block;
39
40pub use allocation::Allocation;
41#[cfg(unix)]
42pub use allocator::get_memory_fd;
43#[cfg(all(windows, feature = "platform-win32"))]
44pub use allocator::get_memory_win32_handle;
45pub use allocator::{
46 Allocator, TrimStats, allocate, allocate_dedicated, allocate_for_buffer, allocate_for_image,
47 allocate_with_options, allocation_info, bind_buffer_memory, bind_image_memory, budget_snapshot,
48 close, create_buffer, create_buffer_with_options, create_dedicated_buffer,
49 create_dedicated_image, create_image, create_image_with_options, destroy_buffer, destroy_image,
50 find_memory_type, find_memory_type_for_buffer_info, find_memory_type_for_image_info, flush, free,
51 invalidate, map, mapped_pointer, query_budget, set_heap_limit, statistics, trim,
52 trim_with_budget, unmap,
53};
54pub use allocator::{
55 CacheRange, DetailedStatistics, MemoryStatistics, allocate_many, allocation_name, allocator_info,
56 copy_from_allocation, copy_to_allocation, create_aliasing_buffer, create_aliasing_image,
57 detailed_pool_statistics, detailed_statistics, flush_many, free_many, invalidate_many,
58 memory_properties, memory_type_properties, physical_device_properties, pool_name,
59 set_allocation_name, set_allocation_user_data, set_pool_name, write_statistics_json,
60};
61pub use allocator::{
62 DefragmentationAlgorithm, DefragmentationContext, DefragmentationInfo, DefragmentationMove,
63 DefragmentationPass, DefragmentationResource, DefragmentationStats, begin_defragmentation,
64 begin_defragmentation_with_break, set_allocation_pinned,
65};
66pub use allocator::{
67 Pool, PoolCreateInfo, PoolStats, create_pool, create_pool_with_chain, destroy_pool,
68 pool_statistics, set_mapping_hysteresis, set_preferred_block_size,
69};
70pub use allocator::{bind_buffer_memory2, bind_image_memory2};
71pub use allocator::{check_corruption, check_pool_corruption, set_debug_memory_settings};
72pub use allocator::{external_memory_types, set_external_memory_types};
73pub use allocator::{
74 heap_budgets, refresh_budget, refresh_budget_with_context, set_current_frame_index,
75};
76pub use chain::AllocationChain;
77mod import;
78pub use import::{ImportMemoryInfo, ImportResource};
79pub use metadata::AllocationAlgorithm;
80pub use policy::{HostAccess, MemoryUsage};
81pub use selector::MemoryTypeSelector;
82pub use virtual_block::{
83 PlacementStrategy, VirtualAllocation, VirtualAllocationInfo, VirtualBlock, VirtualBlockDetails,
84 VirtualBlockStats,
85};
86
87use crate::{self as vk, load::CallError};
88
89#[derive(Debug, PartialEq)]
90pub enum AllocError {
91 NoCompatibleMemoryType,
92 InvalidProperties(&'static str),
93 InvalidRequest(&'static str),
94 InvalidRange,
95 UnknownAllocation,
96 UnknownPool,
97 CorruptionDetected {
98 allocation: u64,
99 offset: u64,
100 },
101 WrongAllocator,
102 AlreadyMapped,
103 NotMapped,
104 NotHostVisible,
105 SerialExhausted,
106 SynchronizationPoisoned,
107 HostAllocationFailed,
108 AllocationLimit,
109 OutOfSpace,
110 AllocationTooLarge {
111 requested: u64,
112 limit: u64,
113 },
114 UnsupportedCapability(&'static str),
115 WrongResource,
116 LiveAllocations,
117 LivePools,
118 Closed,
119 Call(CallError),
120 Output {
121 kind: std::io::ErrorKind,
122 code: Option<i32>,
123 },
124}
125
126impl std::fmt::Display for AllocError {
127 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128 write!(f, "allocation error: {self:?}")
129 }
130}
131
132impl std::error::Error for AllocError {}
133
134impl From<crate::ConstructionError> for AllocError {
135 fn from(error: crate::ConstructionError) -> Self {
136 Self::from(CallError::from(error))
137 }
138}
139
140impl From<CallError> for AllocError {
141 fn from(error: CallError) -> Self {
142 Self::Call(error)
143 }
144}
145
146#[derive(Clone, Copy, Debug, PartialEq, Eq)]
148pub struct MemoryPriority(u32);
149
150impl MemoryPriority {
151 pub fn new(value: f32) -> Result<Self, AllocError> {
155 if !value.is_finite() || !(0.0..=1.0).contains(&value) {
156 return Err(AllocError::InvalidRequest(
157 "memory priority must be finite and in 0..=1",
158 ));
159 }
160 Ok(Self(if value == 0.0 {
161 0.0_f32.to_bits()
162 } else {
163 value.to_bits()
164 }))
165 }
166
167 pub fn get(self) -> f32 {
168 f32::from_bits(self.0)
169 }
170}
171
172impl Default for MemoryPriority {
173 fn default() -> Self {
174 Self(0.5_f32.to_bits())
175 }
176}
177
178#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
181pub struct DebugMemorySettings {
182 pub margin: u64,
184 pub initialize_allocations: bool,
186 pub poison_frees: bool,
188}
189
190impl DebugMemorySettings {
191 #[inline]
193 #[must_use]
194 pub fn new() -> Self {
195 Self::default()
196 }
197
198 #[inline]
200 #[must_use]
201 pub fn set_margin(mut self, value: u64) -> Self {
202 self.margin = value;
203 self
204 }
205
206 #[inline]
208 #[must_use]
209 pub fn set_initialize_allocations(mut self, value: bool) -> Self {
210 self.initialize_allocations = value;
211 self
212 }
213
214 #[inline]
216 #[must_use]
217 pub fn set_poison_frees(mut self, value: bool) -> Self {
218 self.poison_frees = value;
219 self
220 }
221}
222
223#[derive(Clone, Copy, Default)]
226pub struct DeviceMemoryCallbacks {
227 pub allocated: Option<
228 unsafe extern "system" fn(vk::DeviceHandle, vk::DeviceMemory, u64, u32, *mut std::ffi::c_void),
229 >,
230 pub freed: Option<
231 unsafe extern "system" fn(vk::DeviceHandle, vk::DeviceMemory, u64, u32, *mut std::ffi::c_void),
232 >,
233 pub p_user_data: *mut std::ffi::c_void,
234}
235
236impl DeviceMemoryCallbacks {
237 #[inline]
239 #[must_use]
240 pub fn new() -> Self {
241 Self::default()
242 }
243
244 #[inline]
246 #[must_use]
247 pub fn set_allocated(
248 mut self,
249 value: Option<
250 unsafe extern "system" fn(
251 vk::DeviceHandle,
252 vk::DeviceMemory,
253 u64,
254 u32,
255 *mut std::ffi::c_void,
256 ),
257 >,
258 ) -> Self {
259 self.allocated = value;
260 self
261 }
262
263 #[inline]
265 #[must_use]
266 pub fn set_freed(
267 mut self,
268 value: Option<
269 unsafe extern "system" fn(
270 vk::DeviceHandle,
271 vk::DeviceMemory,
272 u64,
273 u32,
274 *mut std::ffi::c_void,
275 ),
276 >,
277 ) -> Self {
278 self.freed = value;
279 self
280 }
281
282 #[inline]
284 #[must_use]
285 pub fn set_p_user_data(mut self, value: *mut std::ffi::c_void) -> Self {
286 self.p_user_data = value;
287 self
288 }
289}
290
291#[derive(Clone, Copy, Debug, PartialEq, Eq)]
293pub struct AllocatorInfo {
294 pub device: vk::DeviceHandle,
295 pub instance: Option<vk::InstanceHandle>,
296 pub physical_device: Option<vk::PhysicalDevice>,
297 pub api_version: Option<u32>,
298}
299
300impl AllocatorInfo {
301 #[inline]
303 #[must_use]
304 pub fn set_device(mut self, value: vk::DeviceHandle) -> Self {
305 self.device = value;
306 self
307 }
308
309 #[inline]
311 #[must_use]
312 pub fn set_instance(mut self, value: Option<vk::InstanceHandle>) -> Self {
313 self.instance = value;
314 self
315 }
316
317 #[inline]
319 #[must_use]
320 pub fn set_physical_device(mut self, value: Option<vk::PhysicalDevice>) -> Self {
321 self.physical_device = value;
322 self
323 }
324
325 #[inline]
327 #[must_use]
328 pub fn set_api_version(mut self, value: Option<u32>) -> Self {
329 self.api_version = value;
330 self
331 }
332}
333
334pub struct AllocRequest {
335 pub size: u64,
336 pub alignment: u64,
337 pub memory_type_bits: u32,
338 pub required_flags: vk::MemoryPropertyFlags,
339 pub preferred_flags: vk::MemoryPropertyFlags,
340}
341
342impl AllocRequest {
343 #[inline]
346 #[must_use]
347 pub fn new(size: u64, alignment: u64, memory_type_bits: u32) -> Self {
348 Self {
349 size,
350 alignment,
351 memory_type_bits,
352 required_flags: vk::MemoryPropertyFlags::empty(),
353 preferred_flags: vk::MemoryPropertyFlags::empty(),
354 }
355 }
356
357 #[inline]
359 #[must_use]
360 pub fn set_size(mut self, value: u64) -> Self {
361 self.size = value;
362 self
363 }
364
365 #[inline]
367 #[must_use]
368 pub fn set_alignment(mut self, value: u64) -> Self {
369 self.alignment = value;
370 self
371 }
372
373 #[inline]
375 #[must_use]
376 pub fn set_memory_type_bits(mut self, value: u32) -> Self {
377 self.memory_type_bits = value;
378 self
379 }
380
381 #[inline]
383 #[must_use]
384 pub fn set_required_flags(mut self, value: vk::MemoryPropertyFlags) -> Self {
385 self.required_flags = value;
386 self
387 }
388
389 #[inline]
391 #[must_use]
392 pub fn set_preferred_flags(mut self, value: vk::MemoryPropertyFlags) -> Self {
393 self.preferred_flags = value;
394 self
395 }
396}
397
398#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
400pub enum AllocationPolicy {
401 #[default]
402 Separate,
403 Automatic,
405 Pooled { block_size: u64 },
408 Adaptive {
411 block_size: u64,
412 min_block_size: u64,
413 },
414}
415
416#[derive(Clone, Copy, Debug)]
419pub struct AllocationCreateInfo<'pool> {
420 pub within_budget: bool,
422 pub dedicated_memory: bool,
424 pub memory_allocate_next: Option<AllocationChain<'pool>>,
427 pub never_allocate: bool,
429 pub can_alias: bool,
431 pub priority: MemoryPriority,
433 pub min_allocation_alignment: u64,
436 pub pool: Option<&'pool Pool>,
448 pub usage: MemoryUsage,
449 pub host_access: HostAccess,
452 pub allow_transfer_instead: bool,
454 pub avoided_flags: vk::MemoryPropertyFlags,
456 pub required_flags: vk::MemoryPropertyFlags,
457 pub preferred_flags: vk::MemoryPropertyFlags,
458 pub memory_type_bits: u32,
460 pub strategy: PlacementStrategy,
463 pub upper_address: bool,
465 pub policy: AllocationPolicy,
466 pub persistent_map: bool,
468}
469
470impl Default for AllocationCreateInfo<'_> {
471 fn default() -> Self {
472 Self {
473 within_budget: false,
474 dedicated_memory: false,
475 memory_allocate_next: None,
476 never_allocate: false,
477 can_alias: false,
478 priority: MemoryPriority::default(),
479 min_allocation_alignment: 0,
480 pool: None,
481 usage: MemoryUsage::Explicit,
482 host_access: HostAccess::None,
483 allow_transfer_instead: false,
484 avoided_flags: vk::MemoryPropertyFlags::empty(),
485 required_flags: vk::MemoryPropertyFlags::empty(),
486 preferred_flags: vk::MemoryPropertyFlags::empty(),
487 memory_type_bits: u32::MAX,
488 strategy: PlacementStrategy::Default,
489 upper_address: false,
490 policy: AllocationPolicy::Separate,
491 persistent_map: false,
492 }
493 }
494}
495
496impl<'pool> AllocationCreateInfo<'pool> {
497 #[inline]
499 #[must_use]
500 pub fn new() -> Self {
501 Self::default()
502 }
503
504 #[inline]
506 #[must_use]
507 pub fn set_within_budget(mut self, value: bool) -> Self {
508 self.within_budget = value;
509 self
510 }
511
512 #[inline]
514 #[must_use]
515 pub fn set_dedicated_memory(mut self, value: bool) -> Self {
516 self.dedicated_memory = value;
517 self
518 }
519
520 #[inline]
538 #[must_use]
539 pub fn set_memory_allocate_next(mut self, value: Option<AllocationChain<'pool>>) -> Self {
540 self.memory_allocate_next = value;
541 self
542 }
543
544 #[inline]
546 #[must_use]
547 pub fn set_never_allocate(mut self, value: bool) -> Self {
548 self.never_allocate = value;
549 self
550 }
551
552 #[inline]
554 #[must_use]
555 pub fn set_can_alias(mut self, value: bool) -> Self {
556 self.can_alias = value;
557 self
558 }
559
560 #[inline]
562 #[must_use]
563 pub fn set_priority(mut self, value: MemoryPriority) -> Self {
564 self.priority = value;
565 self
566 }
567
568 #[inline]
570 #[must_use]
571 pub fn set_min_allocation_alignment(mut self, value: u64) -> Self {
572 self.min_allocation_alignment = value;
573 self
574 }
575
576 #[inline]
578 #[must_use]
579 pub fn set_pool(mut self, value: Option<&'pool Pool>) -> Self {
580 self.pool = value;
581 self
582 }
583
584 #[inline]
586 #[must_use]
587 pub fn set_usage(mut self, value: MemoryUsage) -> Self {
588 self.usage = value;
589 self
590 }
591
592 #[inline]
594 #[must_use]
595 pub fn set_host_access(mut self, value: HostAccess) -> Self {
596 self.host_access = value;
597 self
598 }
599
600 #[inline]
602 #[must_use]
603 pub fn set_allow_transfer_instead(mut self, value: bool) -> Self {
604 self.allow_transfer_instead = value;
605 self
606 }
607
608 #[inline]
610 #[must_use]
611 pub fn set_avoided_flags(mut self, value: vk::MemoryPropertyFlags) -> Self {
612 self.avoided_flags = value;
613 self
614 }
615
616 #[inline]
618 #[must_use]
619 pub fn set_required_flags(mut self, value: vk::MemoryPropertyFlags) -> Self {
620 self.required_flags = value;
621 self
622 }
623
624 #[inline]
626 #[must_use]
627 pub fn set_preferred_flags(mut self, value: vk::MemoryPropertyFlags) -> Self {
628 self.preferred_flags = value;
629 self
630 }
631
632 #[inline]
634 #[must_use]
635 pub fn set_memory_type_bits(mut self, value: u32) -> Self {
636 self.memory_type_bits = value;
637 self
638 }
639
640 #[inline]
642 #[must_use]
643 pub fn set_strategy(mut self, value: PlacementStrategy) -> Self {
644 self.strategy = value;
645 self
646 }
647
648 #[inline]
650 #[must_use]
651 pub fn set_upper_address(mut self, value: bool) -> Self {
652 self.upper_address = value;
653 self
654 }
655
656 #[inline]
658 #[must_use]
659 pub fn set_policy(mut self, value: AllocationPolicy) -> Self {
660 self.policy = value;
661 self
662 }
663
664 #[inline]
666 #[must_use]
667 pub fn set_persistent_map(mut self, value: bool) -> Self {
668 self.persistent_map = value;
669 self
670 }
671}
672
673#[derive(Clone, Copy, Debug, PartialEq, Eq)]
680pub struct AllocationInfo {
681 pub device_memory: vk::DeviceMemory,
682 pub offset: u64,
683 pub size: u64,
684 pub reserved_size: u64,
686 pub memory_type_index: u32,
687 pub heap_index: u32,
688 pub memory_properties: vk::MemoryPropertyFlags,
690 pub mapped_pointer: Option<*mut std::ffi::c_void>,
693 pub map_count: u32,
695 pub native_size: u64,
697 pub is_separate: bool,
699 pub user_data: usize,
701}
702
703impl AllocationInfo {
704 #[inline]
706 #[must_use]
707 pub fn set_device_memory(mut self, value: vk::DeviceMemory) -> Self {
708 self.device_memory = value;
709 self
710 }
711
712 #[inline]
714 #[must_use]
715 pub fn set_offset(mut self, value: u64) -> Self {
716 self.offset = value;
717 self
718 }
719
720 #[inline]
722 #[must_use]
723 pub fn set_size(mut self, value: u64) -> Self {
724 self.size = value;
725 self
726 }
727
728 #[inline]
730 #[must_use]
731 pub fn set_reserved_size(mut self, value: u64) -> Self {
732 self.reserved_size = value;
733 self
734 }
735
736 #[inline]
738 #[must_use]
739 pub fn set_memory_type_index(mut self, value: u32) -> Self {
740 self.memory_type_index = value;
741 self
742 }
743
744 #[inline]
746 #[must_use]
747 pub fn set_heap_index(mut self, value: u32) -> Self {
748 self.heap_index = value;
749 self
750 }
751
752 #[inline]
754 #[must_use]
755 pub fn set_memory_properties(mut self, value: vk::MemoryPropertyFlags) -> Self {
756 self.memory_properties = value;
757 self
758 }
759
760 #[inline]
762 #[must_use]
763 pub fn set_mapped_pointer(mut self, value: Option<*mut std::ffi::c_void>) -> Self {
764 self.mapped_pointer = value;
765 self
766 }
767
768 #[inline]
770 #[must_use]
771 pub fn set_map_count(mut self, value: u32) -> Self {
772 self.map_count = value;
773 self
774 }
775
776 #[inline]
778 #[must_use]
779 pub fn set_native_size(mut self, value: u64) -> Self {
780 self.native_size = value;
781 self
782 }
783
784 #[inline]
786 #[must_use]
787 pub fn set_is_separate(mut self, value: bool) -> Self {
788 self.is_separate = value;
789 self
790 }
791
792 #[inline]
794 #[must_use]
795 pub fn set_user_data(mut self, value: usize) -> Self {
796 self.user_data = value;
797 self
798 }
799}
800
801#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
803pub struct AllocatorStats {
804 pub allocation_count: usize,
805 pub native_allocation_count: usize,
806 pub pooled_block_count: usize,
807 pub allocation_bytes: u64,
809 pub reserved_bytes: u64,
811 pub native_bytes: u64,
812 pub mapped_native_count: usize,
813}
814
815impl AllocatorStats {
816 #[inline]
818 #[must_use]
819 pub fn new() -> Self {
820 Self::default()
821 }
822
823 #[inline]
825 #[must_use]
826 pub fn set_allocation_count(mut self, value: usize) -> Self {
827 self.allocation_count = value;
828 self
829 }
830
831 #[inline]
833 #[must_use]
834 pub fn set_native_allocation_count(mut self, value: usize) -> Self {
835 self.native_allocation_count = value;
836 self
837 }
838
839 #[inline]
841 #[must_use]
842 pub fn set_pooled_block_count(mut self, value: usize) -> Self {
843 self.pooled_block_count = value;
844 self
845 }
846
847 #[inline]
849 #[must_use]
850 pub fn set_allocation_bytes(mut self, value: u64) -> Self {
851 self.allocation_bytes = value;
852 self
853 }
854
855 #[inline]
857 #[must_use]
858 pub fn set_reserved_bytes(mut self, value: u64) -> Self {
859 self.reserved_bytes = value;
860 self
861 }
862
863 #[inline]
865 #[must_use]
866 pub fn set_native_bytes(mut self, value: u64) -> Self {
867 self.native_bytes = value;
868 self
869 }
870
871 #[inline]
873 #[must_use]
874 pub fn set_mapped_native_count(mut self, value: usize) -> Self {
875 self.mapped_native_count = value;
876 self
877 }
878}
879
880#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
882pub enum BudgetSource {
883 #[default]
884 Local,
885 Extension,
886}
887
888#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
890pub struct HeapBudget {
891 pub size: u64,
892 pub limit: u64,
893 pub budget: u64,
894 pub usage: u64,
895 pub native_bytes: u64,
896}
897
898impl HeapBudget {
899 #[inline]
901 #[must_use]
902 pub fn new() -> Self {
903 Self::default()
904 }
905
906 #[inline]
908 #[must_use]
909 pub fn set_size(mut self, value: u64) -> Self {
910 self.size = value;
911 self
912 }
913
914 #[inline]
916 #[must_use]
917 pub fn set_limit(mut self, value: u64) -> Self {
918 self.limit = value;
919 self
920 }
921
922 #[inline]
924 #[must_use]
925 pub fn set_budget(mut self, value: u64) -> Self {
926 self.budget = value;
927 self
928 }
929
930 #[inline]
932 #[must_use]
933 pub fn set_usage(mut self, value: u64) -> Self {
934 self.usage = value;
935 self
936 }
937
938 #[inline]
940 #[must_use]
941 pub fn set_native_bytes(mut self, value: u64) -> Self {
942 self.native_bytes = value;
943 self
944 }
945}
946
947#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
948pub struct BudgetSnapshot {
949 pub source: BudgetSource,
950 pub heap_count: u32,
951 pub heaps: [HeapBudget; 16],
952}
953
954impl BudgetSnapshot {
955 #[inline]
957 #[must_use]
958 pub fn new() -> Self {
959 Self::default()
960 }
961
962 #[inline]
964 #[must_use]
965 pub fn set_source(mut self, value: BudgetSource) -> Self {
966 self.source = value;
967 self
968 }
969
970 #[inline]
972 #[must_use]
973 pub fn set_heap_count(mut self, value: u32) -> Self {
974 self.heap_count = value;
975 self
976 }
977
978 #[inline]
980 #[must_use]
981 pub fn set_heaps(mut self, value: [HeapBudget; 16]) -> Self {
982 self.heaps = value;
983 self
984 }
985}
986
987#[cfg(test)]
988#[path = "../../test/rs/mem/test_host_allocator.rs"]
989pub(crate) mod test_host_allocator;