1use std::marker::PhantomData;
10use std::ptr::NonNull;
11
12use crate::error::{Error, ErrorAndSelf, Result, ResultAndSelf};
13use crate::subobject::{Owner, Subobject};
14use crate::types::*;
15use crate::vk::Device;
16
17#[derive(Debug)]
18pub struct MemoryLifetime {
19 handle: Handle<VkDeviceMemory>,
20 device: Arc<Device>,
21}
22
23#[doc = crate::spec_link!("device memory", "11", "memory-device")]
25#[derive(Debug)]
26pub struct DeviceMemory {
27 inner: Owner<MemoryLifetime>,
28 allocation_size: u64,
29 memory_type_index: u32,
30}
31
32impl DeviceMemory {
33 #[doc = crate::man_link!(vkAllocateMemory)]
36 pub fn new(
37 device: &Arc<Device>, allocation_size: u64, memory_type_index: u32,
38 ) -> Result<Self> {
39 let mem_types = device.physical_device().memory_properties();
40 if memory_type_index >= mem_types.memory_types.len() {
41 return Err(Error::OutOfBounds);
42 }
43 device.increment_memory_alloc_count()?;
44 let mut handle = None;
45 let result = unsafe {
46 (device.fun.allocate_memory)(
47 device.handle(),
48 &MemoryAllocateInfo {
49 stype: Default::default(),
50 next: Default::default(),
51 allocation_size,
52 memory_type_index,
53 },
54 None,
55 &mut handle,
56 )
57 };
58 if result.is_err() {
59 device.decrement_memory_alloc_count();
60 result?;
61 }
62 Ok(Self {
63 allocation_size,
64 memory_type_index,
65 inner: Owner::new(MemoryLifetime {
66 handle: handle.unwrap(),
67 device: device.clone(),
68 }),
69 })
70 }
71
72 pub fn handle(&self) -> Ref<VkDeviceMemory> {
74 self.inner.handle.borrow()
75 }
76 pub fn mut_handle(&mut self) -> Mut<VkDeviceMemory> {
78 self.inner.handle.borrow_mut()
79 }
80 pub fn device(&self) -> &Arc<Device> {
82 &self.inner.device
83 }
84 pub(crate) fn resource(&self) -> Subobject<MemoryLifetime> {
86 Subobject::new(&self.inner)
87 }
88 pub fn check(&self, offset: u64, requirements: MemoryRequirements) -> bool {
90 let (end, overflow) = offset.overflowing_add(requirements.size);
91 (1 << self.memory_type_index) & requirements.memory_type_bits != 0
92 && offset & (requirements.alignment - 1) == 0
93 && !overflow
94 && end <= self.allocation_size
95 }
96}
97
98impl Drop for MemoryLifetime {
99 fn drop(&mut self) {
100 unsafe {
101 (self.device.fun.free_memory)(
102 self.device.handle(),
103 self.handle.borrow_mut(),
104 None,
105 )
106 }
107 self.device.decrement_memory_alloc_count();
108 }
109}
110
111pub struct MappedMemory {
113 memory: DeviceMemory,
114 size: usize,
115 ptr: NonNull<u8>,
116}
117
118pub struct MemoryRead<'a> {
121 ptr: NonNull<u8>,
122 end: *const u8,
123 _lt: PhantomData<&'a ()>,
124}
125pub struct MemoryWrite<'a> {
128 ptr: NonNull<u8>,
129 end: *const u8,
130 _lt: PhantomData<&'a ()>,
131}
132
133#[allow(clippy::len_without_is_empty)]
134impl DeviceMemory {
135 pub fn map(
138 mut self, offset: u64, size: usize,
139 ) -> ResultAndSelf<MappedMemory, Self> {
140 let (end, overflow) = offset.overflowing_add(size as u64);
141 if overflow || end > self.allocation_size || size > isize::MAX as usize
142 {
143 return Err(ErrorAndSelf(Error::OutOfBounds, self));
144 }
145 let inner = &mut *self.inner;
146 let mut ptr = std::ptr::null_mut();
147 unsafe {
148 if let Err(err) = (inner.device.fun.map_memory)(
149 inner.device.handle(),
150 inner.handle.borrow_mut(),
151 offset,
152 size as u64,
153 Default::default(),
154 &mut ptr,
155 ) {
156 return Err(ErrorAndSelf(err.into(), self));
157 }
158 }
159 Ok(MappedMemory { memory: self, size, ptr: NonNull::new(ptr).unwrap() })
160 }
161 pub fn len(&self) -> u64 {
163 self.allocation_size
164 }
165}
166
167impl Drop for MappedMemory {
168 fn drop(&mut self) {
169 self.unmap_impl()
170 }
171}
172
173impl MappedMemory {
174 fn unmap_impl(&mut self) {
175 let inner = &mut *self.memory.inner;
176 unsafe {
177 (inner.device.fun.unmap_memory)(
178 inner.device.handle(),
179 inner.handle.borrow_mut(),
180 )
181 }
182 }
183
184 pub fn unmap(mut self) -> DeviceMemory {
186 self.unmap_impl();
187 let no_drop = std::mem::ManuallyDrop::new(self);
188 unsafe { std::ptr::addr_of!(no_drop.memory).read() }
189 }
190
191 pub fn memory(&self) -> &DeviceMemory {
193 &self.memory
194 }
195
196 #[inline]
199 pub fn read_at(&self, offset: usize) -> MemoryRead {
200 unsafe {
201 let ptr = self.ptr.as_ptr().add(offset.min(self.size));
202 MemoryRead {
203 ptr: NonNull::new_unchecked(ptr),
204 end: self.ptr.as_ptr().add(self.size),
205 _lt: PhantomData,
206 }
207 }
208 }
209
210 #[inline]
213 pub fn write_at(&mut self, offset: usize) -> MemoryWrite {
214 unsafe {
215 let ptr = self.ptr.as_ptr().add(offset.min(self.size));
216 MemoryWrite {
217 ptr: NonNull::new_unchecked(ptr),
218 end: self.ptr.as_ptr().add(self.size),
219 _lt: PhantomData,
220 }
221 }
222 }
223}
224
225impl<'a> std::io::Read for MemoryRead<'a> {
226 #[inline]
227 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
228 unsafe {
229 let size = self.end.offset_from(self.ptr.as_ptr()) as usize;
230 let count = size.min(buf.len());
231 std::ptr::copy_nonoverlapping(
232 self.ptr.as_ptr(),
233 buf.as_mut_ptr(),
234 count,
235 );
236 self.ptr = NonNull::new_unchecked(self.ptr.as_ptr().add(count));
237 Ok(count)
238 }
239 }
240 #[inline]
241 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> std::io::Result<usize> {
242 unsafe {
243 let size = self.end.offset_from(self.ptr.as_ptr()) as usize;
244 buf.reserve_exact(size);
245 std::ptr::copy_nonoverlapping(
246 self.ptr.as_ptr(),
247 buf.spare_capacity_mut().as_mut_ptr() as *mut u8,
248 size,
249 );
250 buf.set_len(buf.len() + size);
251 Ok(size)
252 }
253 }
254}
255
256impl<'a> std::io::Write for MemoryWrite<'a> {
257 #[inline]
258 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
259 unsafe {
260 let size = self.end.offset_from(self.ptr.as_ptr()) as usize;
261 let count = size.min(buf.len());
262 std::ptr::copy_nonoverlapping(
263 buf.as_ptr(),
264 self.ptr.as_ptr(),
265 count,
266 );
267 self.ptr = NonNull::new_unchecked(self.ptr.as_ptr().add(count));
268 Ok(count)
269 }
270 }
271 fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
274 if self.write(buf)? == buf.len() {
275 Ok(())
276 } else {
277 Err(std::io::ErrorKind::WriteZero.into())
278 }
279 }
280
281 #[inline]
283 fn flush(&mut self) -> std::io::Result<()> {
284 Ok(())
285 }
286}
287
288unsafe impl Send for MappedMemory {}
290unsafe impl Sync for MappedMemory {}
291impl std::panic::UnwindSafe for MappedMemory {}
292impl std::panic::RefUnwindSafe for MappedMemory {}
293unsafe impl<'a> Send for MemoryRead<'a> {}
294unsafe impl<'a> Sync for MemoryRead<'a> {}
295impl<'a> std::panic::UnwindSafe for MemoryRead<'a> {}
296impl<'a> std::panic::RefUnwindSafe for MemoryRead<'a> {}
297unsafe impl<'a> Send for MemoryWrite<'a> {}
298unsafe impl<'a> Sync for MemoryWrite<'a> {}
299impl<'a> std::panic::UnwindSafe for MemoryWrite<'a> {}
300impl<'a> std::panic::RefUnwindSafe for MemoryWrite<'a> {}