Skip to main content

bedrock/resources/
memory.rs

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