use { crate::types::{MemoryHeap, MemoryType}, alloc::borrow::Cow, core::ptr::NonNull, }; /// Memory exhausted error. #[derive(Debug)] pub enum OutOfMemory { /// Device memory exhausted. OutOfDeviceMemory, /// Host memory exhausted. OutOfHostMemory, } /// Memory mapped error. #[derive(Debug)] pub enum DeviceMapError { /// Device memory exhausted. OutOfDeviceMemory, /// Host memory exhausted. OutOfHostMemory, /// Map failed due to implementation specific error. MapFailed, } /// Specifies range of the mapped memory region. #[derive(Debug)] pub struct MappedMemoryRange<'a, M> { /// Memory object reference. pub memory: &'a M, /// Offset in bytes from start of the memory object. pub offset: u64, /// Size in bytes of the memory range. pub size: u64, } /// Properties of the device that will be used for allocating memory objects. /// /// See `gpu-alloc-` crate to learn how to obtain one for backend of choice. #[derive(Debug)] pub struct DeviceProperties<'a> { /// Array of memory types provided by the device. pub memory_types: Cow<'a, [MemoryType]>, /// Array of memory heaps provided by the device. pub memory_heaps: Cow<'a, [MemoryHeap]>, /// Maximum number of valid memory allocations that can exist simultaneously within the device. pub max_memory_allocation_count: u32, /// Maximum size for single allocation supported by the device. pub max_memory_allocation_size: u64, /// Atom size for host mappable non-coherent memory. pub non_coherent_atom_size: u64, /// Specifies if feature required to fetch device address is enabled. pub buffer_device_address: bool, } bitflags::bitflags! { /// Allocation flags #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct AllocationFlags : u8 { /// Specifies that the memory can be used for buffers created /// with flag that allows fetching device address. const DEVICE_ADDRESS = 0x1; } } /// Abstract device that can be used to allocate memory objects. pub trait MemoryDevice { /// Allocates new memory object from device. /// This function may be expensive and even limit maximum number of memory /// objects allocated. /// Which is the reason for sub-allocation this crate provides. /// /// # Safety /// /// `memory_type` must be valid index for memory type associated with this device. /// Retreiving this information is implementation specific. /// /// `flags` must be supported by the device. unsafe fn allocate_memory( &self, size: u64, memory_type: u32, flags: AllocationFlags, ) -> Result; /// Deallocate memory object. /// /// # Safety /// /// Memory object must have been allocated from this device.\ /// All clones of specified memory handle must be dropped before calling this function. unsafe fn deallocate_memory(&self, memory: M); /// Map region of device memory to host memory space. /// /// # Safety /// /// * Memory object must have been allocated from this device. /// * Memory object must not be already mapped. /// * Memory must be allocated from type with `HOST_VISIBLE` property. /// * `offset + size` must not overflow. /// * `offset + size` must not be larger than memory object size specified when /// memory object was allocated from this device. unsafe fn map_memory( &self, memory: &mut M, offset: u64, size: u64, ) -> Result, DeviceMapError>; /// Unmap previously mapped memory region. /// /// # Safety /// /// * Memory object must have been allocated from this device. /// * Memory object must be mapped unsafe fn unmap_memory(&self, memory: &mut M); /// Invalidates ranges of memory mapped regions. /// /// # Safety /// /// * Memory objects must have been allocated from this device. /// * `offset` and `size` in each element of `ranges` must specify /// subregion of currently mapped memory region /// * if `memory` in some element of `ranges` does not contain `HOST_COHERENT` property /// then `offset` and `size` of that element must be multiple of `non_coherent_atom_size`. unsafe fn invalidate_memory_ranges( &self, ranges: &[MappedMemoryRange<'_, M>], ) -> Result<(), OutOfMemory>; /// Flushes ranges of memory mapped regions. /// /// # Safety /// /// * Memory objects must have been allocated from this device. /// * `offset` and `size` in each element of `ranges` must specify /// subregion of currently mapped memory region /// * if `memory` in some element of `ranges` does not contain `HOST_COHERENT` property /// then `offset` and `size` of that element must be multiple of `non_coherent_atom_size`. unsafe fn flush_memory_ranges( &self, ranges: &[MappedMemoryRange<'_, M>], ) -> Result<(), OutOfMemory>; }