wgpu_hal/vulkan/
memory.rs1use alloc::vec::Vec;
7use core::ops::Deref;
8
9use ash::vk;
10use wgpu_sync::Mutex;
11
12#[derive(Debug, Clone, Copy)]
13pub(super) enum MemoryPool {
14 General,
15 Transient,
16}
17
18impl MemoryPool {
19 pub(super) fn from_memory_flags(flags: crate::MemoryFlags) -> Self {
20 if flags.contains(crate::MemoryFlags::TRANSIENT) {
21 Self::Transient
22 } else {
23 Self::General
24 }
25 }
26}
27
28#[derive(Debug)]
30pub struct MemoryAllocation {
31 pool: MemoryPool,
32 inner: gpu_allocator::vulkan::Allocation,
33}
34
35impl Deref for MemoryAllocation {
36 type Target = gpu_allocator::vulkan::Allocation;
37
38 fn deref(&self) -> &Self::Target {
39 &self.inner
40 }
41}
42
43pub(super) struct MemoryAllocators {
44 general: Mutex<gpu_allocator::vulkan::Allocator>,
45 transient: Mutex<gpu_allocator::vulkan::Allocator>,
46}
47
48impl MemoryAllocators {
49 pub(super) fn new(
50 instance: ash::Instance,
51 device: ash::Device,
52 physical_device: vk::PhysicalDevice,
53 buffer_device_address: bool,
54 allocation_sizes: crate::AllocationSizes,
55 ) -> Result<Self, gpu_allocator::AllocationError> {
56 let mut desc = gpu_allocator::vulkan::AllocatorCreateDesc {
57 instance,
58 device,
59 physical_device,
60 debug_settings: Default::default(),
61 buffer_device_address,
62 allocation_sizes: allocation_sizes.into(),
63 };
64 let general = gpu_allocator::vulkan::Allocator::new(&desc)?;
65 desc.allocation_sizes = allocation_sizes.transient().into();
66 let transient = gpu_allocator::vulkan::Allocator::new(&desc)?;
67 Ok(Self {
68 general: Mutex::new(general),
69 transient: Mutex::new(transient),
70 })
71 }
72
73 fn allocator(&self, pool: MemoryPool) -> &Mutex<gpu_allocator::vulkan::Allocator> {
74 match pool {
75 MemoryPool::General => &self.general,
76 MemoryPool::Transient => &self.transient,
77 }
78 }
79
80 pub(super) fn allocate(
81 &self,
82 pool: MemoryPool,
83 desc: &gpu_allocator::vulkan::AllocationCreateDesc<'_>,
84 ) -> Result<MemoryAllocation, gpu_allocator::AllocationError> {
85 let inner = self.allocator(pool).lock().allocate(desc)?;
86 Ok(MemoryAllocation { pool, inner })
87 }
88
89 pub(super) fn free(
90 &self,
91 allocation: MemoryAllocation,
92 ) -> Result<(), gpu_allocator::AllocationError> {
93 self.allocator(allocation.pool)
94 .lock()
95 .free(allocation.inner)
96 }
97
98 pub(super) fn generate_report(&self) -> wgt::AllocatorReport {
99 let mut allocations = Vec::new();
100 let mut blocks = Vec::new();
101 let mut total_allocated_bytes = 0;
102 let mut total_reserved_bytes = 0;
103
104 for allocator in [&self.general, &self.transient] {
105 let report = allocator.lock().generate_report();
106
107 let allocation_base = allocations.len();
109 allocations.extend(
110 report
111 .allocations
112 .into_iter()
113 .map(|alloc| wgt::AllocationReport {
114 name: alloc.name,
115 offset: alloc.offset,
116 size: alloc.size,
117 }),
118 );
119 blocks.extend(
120 report
121 .blocks
122 .into_iter()
123 .map(|block| wgt::MemoryBlockReport {
124 size: block.size,
125 allocations: (block.allocations.start + allocation_base)
126 ..(block.allocations.end + allocation_base),
127 }),
128 );
129 total_allocated_bytes += report.total_allocated_bytes;
130 total_reserved_bytes += report.total_capacity_bytes;
131 }
132
133 wgt::AllocatorReport {
134 allocations,
135 blocks,
136 total_allocated_bytes,
137 total_reserved_bytes,
138 }
139 }
140}