| //! This crate provides a fully written in Rust memory allocator for Vulkan and DirectX 12. |
| //! |
| //! ## [Windows-rs] and [winapi] |
| //! |
| //! `gpu-allocator` recently migrated from [winapi] to [windows-rs] but still provides convenient helpers to convert to and from [winapi] types, enabled when compiling with the `public-winapi` crate feature. |
| //! |
| //! [Windows-rs]: https://github.com/microsoft/windows-rs |
| //! [winapi]: https://github.com/retep998/winapi-rs |
| //! |
| //! ## Setting up the Vulkan memory allocator |
| //! |
| //! ```no_run |
| //! # #[cfg(feature = "vulkan")] |
| //! # fn main() { |
| //! use gpu_allocator::vulkan::*; |
| //! # use ash::vk; |
| //! # let device = todo!(); |
| //! # let instance = todo!(); |
| //! # let physical_device = todo!(); |
| //! |
| //! let mut allocator = Allocator::new(&AllocatorCreateDesc { |
| //! instance, |
| //! device, |
| //! physical_device, |
| //! debug_settings: Default::default(), |
| //! buffer_device_address: true, // Ideally, check the BufferDeviceAddressFeatures struct. |
| //! }); |
| //! # } |
| //! # #[cfg(not(feature = "vulkan"))] |
| //! # fn main() {} |
| //! ``` |
| //! |
| //! ## Simple Vulkan allocation example |
| //! |
| //! ```no_run |
| //! # #[cfg(feature = "vulkan")] |
| //! # fn main() { |
| //! use gpu_allocator::vulkan::*; |
| //! use gpu_allocator::MemoryLocation; |
| //! # use ash::vk; |
| //! # let device = todo!(); |
| //! # let instance = todo!(); |
| //! # let physical_device = todo!(); |
| //! |
| //! # let mut allocator = Allocator::new(&AllocatorCreateDesc { |
| //! # instance, |
| //! # device, |
| //! # physical_device, |
| //! # debug_settings: Default::default(), |
| //! # buffer_device_address: true, // Ideally, check the BufferDeviceAddressFeatures struct. |
| //! # }).unwrap(); |
| //! |
| //! // Setup vulkan info |
| //! let vk_info = vk::BufferCreateInfo::builder() |
| //! .size(512) |
| //! .usage(vk::BufferUsageFlags::STORAGE_BUFFER); |
| //! |
| //! let buffer = unsafe { device.create_buffer(&vk_info, None) }.unwrap(); |
| //! let requirements = unsafe { device.get_buffer_memory_requirements(buffer) }; |
| //! |
| //! let allocation = allocator |
| //! .allocate(&AllocationCreateDesc { |
| //! name: "Example allocation", |
| //! requirements, |
| //! location: MemoryLocation::CpuToGpu, |
| //! linear: true, // Buffers are always linear |
| //! }).unwrap(); |
| //! |
| //! // Bind memory to the buffer |
| //! unsafe { device.bind_buffer_memory(buffer, allocation.memory(), allocation.offset()).unwrap() }; |
| //! |
| //! // Cleanup |
| //! allocator.free(allocation).unwrap(); |
| //! unsafe { device.destroy_buffer(buffer, None) }; |
| //! # } |
| //! # #[cfg(not(feature = "vulkan"))] |
| //! # fn main() {} |
| //! ``` |
| //! |
| //! ## Setting up the D3D12 memory allocator |
| //! |
| //! ```no_run |
| //! # #[cfg(feature = "d3d12")] |
| //! # fn main() { |
| //! use gpu_allocator::d3d12::*; |
| //! # let device = todo!(); |
| //! |
| //! let mut allocator = Allocator::new(&AllocatorCreateDesc { |
| //! device, |
| //! debug_settings: Default::default(), |
| //! }); |
| //! # } |
| //! # #[cfg(not(feature = "d3d12"))] |
| //! # fn main() {} |
| //! ``` |
| //! |
| //! ## Simple d3d12 allocation example |
| //! |
| //! ```no_run |
| //! # #[cfg(feature = "d3d12")] |
| //! # fn main() -> windows::core::Result<()> { |
| //! use gpu_allocator::d3d12::*; |
| //! use gpu_allocator::MemoryLocation; |
| //! # use windows::Win32::Graphics::{Dxgi, Direct3D12}; |
| //! # let device = todo!(); |
| //! |
| //! # let mut allocator = Allocator::new(&AllocatorCreateDesc { |
| //! # device: device, |
| //! # debug_settings: Default::default(), |
| //! # }).unwrap(); |
| //! |
| //! let buffer_desc = Direct3D12::D3D12_RESOURCE_DESC { |
| //! Dimension: Direct3D12::D3D12_RESOURCE_DIMENSION_BUFFER, |
| //! Alignment: 0, |
| //! Width: 512, |
| //! Height: 1, |
| //! DepthOrArraySize: 1, |
| //! MipLevels: 1, |
| //! Format: Dxgi::Common::DXGI_FORMAT_UNKNOWN, |
| //! SampleDesc: Dxgi::Common::DXGI_SAMPLE_DESC { |
| //! Count: 1, |
| //! Quality: 0, |
| //! }, |
| //! Layout: Direct3D12::D3D12_TEXTURE_LAYOUT_ROW_MAJOR, |
| //! Flags: Direct3D12::D3D12_RESOURCE_FLAG_NONE, |
| //! }; |
| //! let allocation_desc = AllocationCreateDesc::from_d3d12_resource_desc( |
| //! &allocator.device(), |
| //! &buffer_desc, |
| //! "Example allocation", |
| //! MemoryLocation::GpuOnly, |
| //! ); |
| //! let allocation = allocator.allocate(&allocation_desc).unwrap(); |
| //! let mut resource: Option<Direct3D12::ID3D12Resource> = None; |
| //! let hr = unsafe { |
| //! device.CreatePlacedResource( |
| //! allocation.heap(), |
| //! allocation.offset(), |
| //! &buffer_desc, |
| //! Direct3D12::D3D12_RESOURCE_STATE_COMMON, |
| //! std::ptr::null(), |
| //! &mut resource, |
| //! ) |
| //! }?; |
| //! |
| //! // Cleanup |
| //! drop(resource); |
| //! allocator.free(allocation).unwrap(); |
| //! # Ok(()) |
| //! # } |
| //! # #[cfg(not(feature = "d3d12"))] |
| //! # fn main() {} |
| //! ``` |
| |
| mod result; |
| pub use result::*; |
| |
| pub(crate) mod allocator; |
| |
| #[cfg(feature = "visualizer")] |
| pub mod visualizer; |
| |
| #[cfg(feature = "vulkan")] |
| pub mod vulkan; |
| |
| #[cfg(all(windows, feature = "d3d12"))] |
| pub mod d3d12; |
| |
| #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
| pub enum MemoryLocation { |
| /// The allocated resource is stored at an unknown memory location; let the driver decide what's the best location |
| Unknown, |
| /// Store the allocation in GPU only accessible memory - typically this is the faster GPU resource and this should be |
| /// where most of the allocations live. |
| GpuOnly, |
| /// Memory useful for uploading data to the GPU and potentially for constant buffers |
| CpuToGpu, |
| /// Memory useful for CPU readback of data |
| GpuToCpu, |
| } |
| |
| #[derive(Copy, Clone, Debug)] |
| pub struct AllocatorDebugSettings { |
| /// Logs out debugging information about the various heaps the current device has on startup |
| pub log_memory_information: bool, |
| /// Logs out all memory leaks on shutdown with log level Warn |
| pub log_leaks_on_shutdown: bool, |
| /// Stores a copy of the full backtrace for every allocation made, this makes it easier to debug leaks |
| /// or other memory allocations, but storing stack traces has a RAM overhead so should be disabled |
| /// in shipping applications. |
| pub store_stack_traces: bool, |
| /// Log out every allocation as it's being made with log level Debug, rather spammy so off by default |
| pub log_allocations: bool, |
| /// Log out every free that is being called with log level Debug, rather spammy so off by default |
| pub log_frees: bool, |
| /// Log out stack traces when either `log_allocations` or `log_frees` is enabled. |
| pub log_stack_traces: bool, |
| } |
| |
| impl Default for AllocatorDebugSettings { |
| fn default() -> Self { |
| Self { |
| log_memory_information: false, |
| log_leaks_on_shutdown: true, |
| store_stack_traces: false, |
| log_allocations: false, |
| log_frees: false, |
| log_stack_traces: false, |
| } |
| } |
| } |