bedrock/resources/
memory.rs

1use crate::*;
2use derives::implements;
3
4pub trait DeviceMemory: VkHandle<Handle = VkDeviceMemory> + DeviceChildHandle {
5    /// Query the current commitment for a `DeviceMemory`
6    #[implements]
7    #[inline]
8    fn commitment_bytes(&self) -> VkDeviceSize {
9        let mut b = 0;
10        unsafe {
11            crate::vkfn::get_device_memory_commitment(self.device_handle(), self.native_ptr(), &mut b);
12        }
13
14        b
15    }
16}
17DerefContainerBracketImpl!(for DeviceMemory {});
18GuardsImpl!(for DeviceMemory {});
19
20pub trait DeviceMemoryMut: DeviceMemory + VkHandleMut {
21    /// Map a memory object into application address space
22    /// # Safety
23    /// mapped memory must be unmapped once
24    /// # Failure
25    /// On failure, this command returns
26    ///
27    /// * `VK_ERROR_OUT_OF_HOST_MEMORY`
28    /// * `VK_ERROR_OUT_OF_DEVICE_MEMORY`
29    /// * `VK_ERROR_MEMORY_MAP_FAILED`
30    #[implements]
31    #[inline]
32    unsafe fn map_raw(&mut self, range: core::ops::Range<VkDeviceSize>) -> crate::Result<*mut core::ffi::c_void> {
33        let mut p = core::mem::MaybeUninit::uninit();
34
35        unsafe {
36            crate::vkfn::map_memory(
37                self.device_handle(),
38                self.native_ptr_mut(),
39                range.start,
40                range.end - range.start,
41                0,
42                p.as_mut_ptr(),
43            )
44            .into_result()?;
45        }
46
47        Ok(unsafe { p.assume_init() })
48    }
49
50    /// Map a memory object into application address space
51    /// # Failure
52    /// On failure, this command returns
53    ///
54    /// * `VK_ERROR_OUT_OF_HOST_MEMORY`
55    /// * `VK_ERROR_OUT_OF_DEVICE_MEMORY`
56    /// * `VK_ERROR_MEMORY_MAP_FAILED`
57    #[implements]
58    fn map(&mut self, range: core::ops::Range<usize>) -> crate::Result<MappedMemory<Self>> {
59        let p = unsafe { self.map_raw(range.start as _..range.end as _)? };
60
61        Ok(MappedMemory(p, self))
62    }
63
64    /// Unmap a previously mapped memory object
65    /// # Safety
66    /// Caller must guarantee that there is no `MappedMemoryRange` alives.
67    /// Accessing the mapped memory after this call has undefined behavior
68    #[implements]
69    #[inline]
70    unsafe fn unmap(&mut self) {
71        unsafe { crate::vkfn::unmap_memory(self.device_handle(), self.native_ptr_mut()) }
72    }
73}
74DerefContainerBracketImpl!(for mut DeviceMemoryMut {});
75GuardsImpl!(for mut DeviceMemoryMut {});
76
77#[derive(VkHandle, VkObject)]
78#[VkObject(type = VkDeviceMemory::OBJECT_TYPE)]
79pub struct DeviceMemoryObject<Device: VkHandle<Handle = VkDevice>>(VkDeviceMemory, Device);
80#[implements]
81impl<Device: VkHandle<Handle = VkDevice>> Drop for DeviceMemoryObject<Device> {
82    #[inline(always)]
83    fn drop(&mut self) {
84        unsafe {
85            crate::vkfn::free_memory(self.1.native_ptr(), self.0, core::ptr::null());
86        }
87    }
88}
89unsafe impl<Device: VkHandle<Handle = VkDevice> + Sync> Sync for DeviceMemoryObject<Device> {}
90unsafe impl<Device: VkHandle<Handle = VkDevice> + Send> Send for DeviceMemoryObject<Device> {}
91impl<Device: VkHandle<Handle = VkDevice>> DeviceChildHandle for DeviceMemoryObject<Device> {
92    #[inline(always)]
93    fn device_handle(&self) -> VkDevice {
94        self.1.native_ptr()
95    }
96}
97impl<Device: crate::Device> DeviceChild for DeviceMemoryObject<Device> {
98    type ConcreteDevice = Device;
99
100    #[inline(always)]
101    fn device(&self) -> &Self::ConcreteDevice {
102        &self.1
103    }
104}
105impl<Device: VkHandle<Handle = VkDevice>> DeviceMemory for DeviceMemoryObject<Device> {}
106impl<Device: VkHandle<Handle = VkDevice>> DeviceMemoryMut for DeviceMemoryObject<Device> {}
107impl<Device: VkHandle<Handle = VkDevice>> DeviceMemoryObject<Device> {
108    /// Constructs from raw values
109    /// # Safety
110    /// the resource must be created from the parent
111    pub const unsafe fn manage(handle: VkDeviceMemory, parent: Device) -> Self {
112        Self(handle, parent)
113    }
114
115    /// Purges internal values (Drop will not be called for this resource)
116    pub const fn unmanage(self) -> (VkDeviceMemory, Device) {
117        let v = self.0;
118        let p = unsafe { core::ptr::read(&self.1) };
119        core::mem::forget(self);
120
121        (v, p)
122    }
123}
124impl<Device: VkHandle<Handle = VkDevice> + Clone> DeviceMemoryObject<&'_ Device> {
125    /// Owning parent object by cloning it.
126    #[inline(always)]
127    pub fn clone_parent(self) -> DeviceMemoryObject<Device> {
128        let r = DeviceMemoryObject(self.0, self.1.clone());
129        core::mem::forget(self);
130
131        r
132    }
133}
134impl<Device: crate::Device> DeviceMemoryObject<Device> {
135    /// Create DeviceMemory object with allocating device memory
136    /// # Failure
137    /// On failure, this command returns
138    ///
139    /// * [`VK_ERROR_OUT_OF_HOST_MEMORY`]
140    /// * [`VK_ERROR_OUT_OF_DEVICE_MEMORY`]
141    /// * [`VK_ERROR_INVALID_EXTERNAL_HANDLE`]
142    /// * [`VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS_KHR`]
143    #[implements]
144    #[inline]
145    pub fn new(device: Device, info: &MemoryAllocateInfo) -> crate::Result<Self> {
146        Ok(unsafe { Self::manage(device.allocate_memory(info, None)?, device) })
147    }
148}
149
150/// Structure containing parameters of a memory allocation
151#[repr(transparent)]
152#[derive(Clone)]
153pub struct MemoryAllocateInfo<'d>(
154    VkMemoryAllocateInfo,
155    core::marker::PhantomData<Option<&'d dyn VulkanStructure>>,
156);
157impl<'d> MemoryAllocateInfo<'d> {
158    pub const fn new(size: VkDeviceSize, memory_type_index: u32) -> Self {
159        Self(
160            VkMemoryAllocateInfo {
161                sType: VkMemoryAllocateInfo::TYPE,
162                pNext: core::ptr::null(),
163                allocationSize: size,
164                memoryTypeIndex: memory_type_index,
165            },
166            core::marker::PhantomData,
167        )
168    }
169
170    pub const unsafe fn from_raw(raw: VkMemoryAllocateInfo) -> Self {
171        Self(raw, core::marker::PhantomData)
172    }
173
174    pub const fn into_raw(self) -> VkMemoryAllocateInfo {
175        self.0
176    }
177
178    pub const fn with_next(mut self, next: &'d (impl VulkanStructure + ?Sized)) -> Self {
179        self.0.pNext = next as *const _ as _;
180        self
181    }
182
183    pub const unsafe fn next_sink<T: VulkanStructure>(&mut self) -> &mut *const T {
184        unsafe { core::mem::transmute(&mut self.0.pNext) }
185    }
186}
187
188/// Specify a dedicated memory allocation resource
189#[cfg(feature = "VK_KHR_dedicated_allocation")]
190#[repr(transparent)]
191#[derive(Clone)]
192pub struct MemoryDedicatedAllocateInfo<'d>(
193    VkMemoryDedicatedAllocateInfoKHR,
194    core::marker::PhantomData<(
195        Option<&'d dyn VulkanStructure>,
196        Option<&'d dyn VkHandle<Handle = VkImage>>,
197        Option<&'d dyn VkHandle<Handle = VkBuffer>>,
198    )>,
199);
200#[cfg(feature = "VK_KHR_dedicated_allocation")]
201unsafe impl VulkanStructure for MemoryDedicatedAllocateInfo<'_> {
202    #[inline(always)]
203    fn as_generic(&self) -> &GenericVulkanStructure {
204        unsafe { core::mem::transmute(self) }
205    }
206
207    #[inline(always)]
208    fn as_generic_mut(&mut self) -> &mut GenericVulkanStructure {
209        unsafe { core::mem::transmute(self) }
210    }
211}
212#[cfg(feature = "VK_KHR_dedicated_allocation")]
213impl<'d> MemoryDedicatedAllocateInfo<'d> {
214    #[inline]
215    pub fn for_buffer(buffer: &'d (impl VkHandle<Handle = VkBuffer> + ?Sized)) -> Self {
216        Self(
217            VkMemoryDedicatedAllocateInfoKHR {
218                sType: VkMemoryDedicatedAllocateInfoKHR::TYPE,
219                pNext: core::ptr::null(),
220                image: VkImage::NULL,
221                buffer: buffer.native_ptr(),
222            },
223            core::marker::PhantomData,
224        )
225    }
226
227    #[inline]
228    pub const unsafe fn for_buffer_raw(buffer: VkBuffer) -> Self {
229        Self(
230            VkMemoryDedicatedAllocateInfoKHR {
231                sType: VkMemoryDedicatedAllocateInfoKHR::TYPE,
232                pNext: core::ptr::null(),
233                image: VkImage::NULL,
234                buffer,
235            },
236            core::marker::PhantomData,
237        )
238    }
239
240    #[inline]
241    pub fn for_image(image: &'d (impl VkHandle<Handle = VkImage> + ?Sized)) -> Self {
242        Self(
243            VkMemoryDedicatedAllocateInfoKHR {
244                sType: VkMemoryDedicatedAllocateInfoKHR::TYPE,
245                pNext: core::ptr::null(),
246                image: image.native_ptr(),
247                buffer: VkBuffer::NULL,
248            },
249            core::marker::PhantomData,
250        )
251    }
252
253    #[inline]
254    pub const unsafe fn for_image_raw(image: VkImage) -> Self {
255        Self(
256            VkMemoryDedicatedAllocateInfoKHR {
257                sType: VkMemoryDedicatedAllocateInfoKHR::TYPE,
258                pNext: core::ptr::null(),
259                image,
260                buffer: VkBuffer::NULL,
261            },
262            core::marker::PhantomData,
263        )
264    }
265
266    pub const unsafe fn from_raw(raw: VkMemoryDedicatedAllocateInfoKHR) -> Self {
267        Self(raw, core::marker::PhantomData)
268    }
269
270    pub const fn into_raw(self) -> VkMemoryDedicatedAllocateInfoKHR {
271        self.0
272    }
273
274    pub const fn with_next(mut self, next: &'d (impl VulkanStructure + ?Sized)) -> Self {
275        self.0.pNext = next as *const _ as _;
276        self
277    }
278
279    pub const unsafe fn next_sink<T: VulkanStructure>(&mut self) -> &mut *const T {
280        unsafe { core::mem::transmute(&mut self.0.pNext) }
281    }
282}
283
284/// Structure specifying a mapped memory range.
285pub struct MappedMemoryRange<'a>(
286    VkMappedMemoryRange,
287    core::marker::PhantomData<&'a dyn VkHandle<Handle = VkDeviceMemory>>,
288);
289impl<'a> MappedMemoryRange<'a> {
290    pub fn new(
291        memory: &'a (impl VkHandle<Handle = VkDeviceMemory> + ?Sized),
292        range: core::ops::Range<DeviceSize>,
293    ) -> Self {
294        Self(
295            VkMappedMemoryRange {
296                sType: VkMappedMemoryRange::TYPE,
297                pNext: core::ptr::null(),
298                memory: memory.native_ptr(),
299                offset: range.start,
300                size: range.end - range.start,
301            },
302            core::marker::PhantomData,
303        )
304    }
305
306    pub const unsafe fn new_raw(memory: VkDeviceMemory, offset: DeviceSize, size: DeviceSize) -> Self {
307        Self(
308            VkMappedMemoryRange {
309                sType: VkMappedMemoryRange::TYPE,
310                pNext: core::ptr::null(),
311                memory,
312                offset,
313                size,
314            },
315            core::marker::PhantomData,
316        )
317    }
318
319    pub const unsafe fn from_raw(raw: VkMappedMemoryRange) -> Self {
320        Self(raw, core::marker::PhantomData)
321    }
322
323    pub const fn into_raw(self) -> VkMappedMemoryRange {
324        self.0
325    }
326}
327
328/// Specifies the block of mapped memory in a `DeviceMemory`
329pub struct MappedMemory<'m, DeviceMemory: crate::DeviceMemoryMut + ?Sized + 'm>(
330    *mut core::ffi::c_void,
331    &'m mut DeviceMemory,
332);
333#[allow(clippy::mut_from_ref)]
334impl<'m, DeviceMemory: crate::DeviceMemoryMut + ?Sized + 'm> MappedMemory<'m, DeviceMemory> {
335    /// Returns a pointer to the head of the mapped region
336    pub const fn ptr(&self) -> *mut core::ffi::c_void {
337        self.0
338    }
339
340    /// Get a mutable pointer in mapped memory with byte offsets
341    /// # Safety
342    /// Caller must guarantee that the pointer and its alignment are valid
343    pub const unsafe fn addr_of_mut<T>(&self, offset: usize) -> *mut T {
344        unsafe { self.0.byte_add(offset) as *mut T }
345    }
346
347    /// Get a reference in mapped memory with byte offsets
348    /// # Safety
349    /// Caller must guarantee that the pointer and its alignment are valid
350    pub const unsafe fn get<T>(&self, offset: usize) -> &T {
351        unsafe { &*(self.0.byte_add(offset) as *const T) }
352    }
353
354    /// Get a mutable reference in mapped memory with byte offsets
355    /// # Safety
356    /// Caller must guarantee that the pointer and its alignment are valid
357    pub const unsafe fn get_mut<T>(&self, offset: usize) -> &mut T {
358        unsafe { &mut *(self.0.byte_add(offset) as *mut T) }
359    }
360
361    /// Get a slice in mapped memory with byte offsets
362    /// # Safety
363    /// Caller must guarantee that the pointer and its alignment are valid
364    pub const unsafe fn slice<T>(&self, offset: usize, count: usize) -> &[T] {
365        unsafe { core::slice::from_raw_parts(self.0.byte_add(offset) as *const T, count) }
366    }
367
368    /// Get a mutable slice in mapped memory with byte offsets
369    /// # Safety
370    /// Caller must guarantee that the pointer and its alignment are valid
371    pub const unsafe fn slice_mut<T>(&self, offset: usize, count: usize) -> &mut [T] {
372        unsafe { core::slice::from_raw_parts_mut(self.0.byte_add(offset) as *mut T, count) }
373    }
374
375    /// Clone data from slice at the specified offset in mapped memory.
376    /// # Safety
377    /// Caller must guarantee that the pointer and its alignment are valid
378    #[inline(always)]
379    pub unsafe fn clone_from_slice_at<T: Clone>(&self, offset: usize, src: &[T]) {
380        unsafe { self.slice_mut(offset, src.len()).clone_from_slice(src) };
381    }
382
383    /// Clone data from slice at the specified offset in mapped memory.
384    /// # Safety
385    /// Caller must guarantee that the pointer and its alignment are valid
386    #[inline(always)]
387    pub unsafe fn clone_at<T: Clone>(&self, offset: usize, src: &T) {
388        unsafe { *self.get_mut(offset) = src.clone() };
389    }
390
391    #[implements]
392    /// Unmap region
393    pub fn end(self) {
394        unsafe {
395            self.1.unmap();
396        }
397    }
398}