[−][src]Struct nobs_vkmem::Allocator
Allocator for buffer and image resources
Manages device memory for a single device. The actual memory is managed for each memory type separately by a page table. Pages are allocated lazyly, as soon as memory is needed. The pagesizes may be specified in the AllocatorSizes.
When the Allocator is dropped, all buffers and allocated device momory is freed.
Example
The Allocator is created from a device handle and it's associated physical device. Buffers and images can be easyly created with the Buffer and Image builder. Host accessible buffers can be conveniently accessed with get_mapped / get_mapped_region and Mapped. Allocated resources may be freed with destroy(_many). Memory of pages that have no bore resource binding can be freed with free_unused again.
extern crate nobs_vk as vk; extern crate nobs_vkmem as vkmem; struct Ub { a: u32, b: u32, c: u32, } // create an allocator with default page size // (128MiB for device local / 8MB for host visible memory) let mut allocator = vkmem::Allocator::new(pdevice.handle, device.handle); // declare handles let mut buf_ub = vk::NULL_HANDLE; let mut buf_out = vk::NULL_HANDLE; let mut img = vk::NULL_HANDLE; let mut bb = vk::NULL_HANDLE; // configure create infos vkmem::Buffer::new(&mut buf_ub) .size(std::mem::size_of::<Ub>() as vk::DeviceSize) .usage(vk::BUFFER_USAGE_TRANSFER_DST_BIT | vk::BUFFER_USAGE_UNIFORM_BUFFER_BIT) .devicelocal(false) .new_buffer(&mut buf_out) .size(123 * std::mem::size_of::<u32>() as vk::DeviceSize) .usage(vk::BUFFER_USAGE_TRANSFER_DST_BIT | vk::BUFFER_USAGE_STORAGE_BUFFER_BIT) .devicelocal(false) .new_image(&mut img) .image_type(vk::IMAGE_TYPE_2D) .size(123, 123, 1) .usage(vk::IMAGE_USAGE_SAMPLED_BIT) .devicelocal(true) .new_buffer(&mut bb) .size(123 * std::mem::size_of::<u32>() as vk::DeviceSize) .usage(vk::BUFFER_USAGE_TRANSFER_DST_BIT | vk::BUFFER_USAGE_STORAGE_BUFFER_BIT) .devicelocal(true) // this will create the image/buffers and bind them to memory .bind(&mut allocator, vkmem::BindType::Scatter) .unwrap(); // Mapped gives a convenient view on the memory // get_mapped mapps the whole block of memory to which the resources was bound // get_mapped_region lets us define a byte offset respective to the beginning of the resource and a size in bytes { let mapped = allocator.get_mapped(buf_ub).unwrap(); let ubb = Ub { a: 123, b: 4, c: 5 }; mapped.host_to_device(&ubb); } { let mapped = allocator.get_mapped(buf_ub).unwrap(); let mut ubb = Ub { a: 0, b: 0, c: 0 }; mapped.device_to_host(&mut ubb); } { let mapped = allocator.get_mapped_region(buf_out, 4, 100).unwrap(); let v = mapped.as_slice::<u32>(); } // we can print stats in a yaml format for the currently allocated pages println!("{}", allocator.print_stats()); // buffers and images can be destroyed allocator.destroy(img); allocator.destroy_many(&[buf_ub, buf_out]); // destroying does NOT free memory // if we want to free memory we can do this only if a whole page is not used any more // in this case we can free the memory again allocator.free_unused(); // dropping the allocator automatically destroys bound resources and frees all memory
Methods
impl Allocator
[src]
pub fn get_min_pagesize(pdevice: PhysicalDevice) -> DeviceSize
[src]
Gets the smallest pagesize for the specified physical device
The minimum page size is defined through the bufferImageGranularity
of the physical device properties
Arguments
pdevice
- physical device handle
Returns
The minimum pagesize in bytes.
pub fn get_memtype(
pdevice: PhysicalDevice,
requirements: &MemoryRequirements,
properties: MemoryPropertyFlags
) -> Option<u32>
[src]
pdevice: PhysicalDevice,
requirements: &MemoryRequirements,
properties: MemoryPropertyFlags
) -> Option<u32>
Get the memtype for a combination of memory requirements and properties
Arguments
pdevice
- physical device handlerequirements
- memory reqirements retrieved withvk::GetBufferMemoryRequirements
orvk::GetBufferMemoryRequirements
properties
- combination ofvk::MemoryPropertyFlagBits
Returns
Some(memtype)
- wherememtype
is the memory type indexNone
- if there no such a combination of memory requirements and properties exists on the physical device
pub fn new(pdevice: PhysicalDevice, device: Device) -> Allocator
[src]
Creates an Allocator
The Allocator will use the default AllocatorSizes, with 128MiB / 8MiB pagesizes for device local / host accessible memory.
Arguments
pdevice
- physical device handledevice
- device handle
pub fn with_sizes(device: Device, sizes: AllocatorSizes) -> Allocator
[src]
Creates an Allocator from AllocatorSizes
The AllocatorSizes will consumed by the consturctor. This allows additional configuration of the pagesizes for every memory type.
Arguments
device
- device handlesizes
- AllocatorSizes with the physical device handle and pagesize definitions
Example
Creates an Allocator with 32MiB large pages for host accassable memory
let mut sizes = vkmem::AllocatorSizes::new(pdevice.handle, device.handle); if let Some(memtype) = sizes.get_buffer_memtype(vk::MEMORY_PROPERTY_HOST_VISIBLE_BIT | vk::MEMORY_PROPERTY_HOST_COHERENT_BIT) { sizes.set_pagesize(memtype, 1 << 25); } let mut allocator = vkmem::Allocator::with_sizes(pdevice.handle, sizes);
pub fn bind(
&mut self,
bindinfos: &[BindInfo],
bindtype: BindType
) -> Result<(), Error>
[src]
&mut self,
bindinfos: &[BindInfo],
bindtype: BindType
) -> Result<(), Error>
Bind resources to device memory
This will automatically allocate memory, if necessary.
Resources that are used together shoulb be bound in the same call to this function, since it tries to minimize the number of continuous memory blocks on which the resources are bound. Predominatly this is important after resources have been deleted and free blocks of memory are distributed over multiple pages.
We can specify a rough strategy of how resources are bound with the bindtype
parameter. See BindType for the different strategies
The Allocator takes ownorship ower the resource handles.
Note that it is not neccesary that all BindInfos need to specify resources that are allocated on the same memory type. The Allocator will detangle the BindInfos automatically and generate one binding for every group of resources on the same memory type.
Arguments
bindinfos
- Array of BindInfo that specifies the resources to be boundbindtype
- Allocation strategy
Returns
Error if the allocator failed to bind one or more resources:
Error::AllocError
- if a new page could not be allocatedError::OutOfMemory
- if not enough memory is available to bind all resourcesError::OversizedBlock
- if a single resourcse is larger than it's associated pagesize, or ifbindtype
isBindType::Block
and the combined size of all resources is larger than their associated pagesizeError::InvalidMemoryType
- if for one or more resources no memory type is found that satisfies the memory requirements and propertiesError::BindMemoryFailed
- if one or more resources could not be bound to device memoryError::AlreadyBound
- if one or more resources are already bound to device memory
Example
Shows how buffers and images can be bound to the allocator. Prior to bind the resources have to be created with either vk::CreateBuffer
or vk::CreateImage
.
The BindInfo can be generated manually (as in the example), see Buffer and Image for convenient configuration and binding of buffers and images
let mut allocator = vkmem::Allocator::new(pdevice.handle, device.handle); let buf = vk::NULL_HANDLE; let img = vk::NULL_HANDLE; // ... create buffers/images let buf = vkmem::Handle::Buffer(buf); let img = vkmem::Handle::Image(img); let host_access_flags = vk::MEMORY_PROPERTY_HOST_VISIBLE_BIT | vk::MEMORY_PROPERTY_HOST_COHERENT_BIT; let device_local_flags = vk::MEMORY_PROPERTY_DEVICE_LOCAL_BIT; allocator.bind( &[ vkmem::BindInfo::with_size(buf, 12, host_access_flags), vkmem::BindInfo::new(img, device_local_flags), ], vkmem::BindType::Scatter, ).expect("binding buffers failed");
pub fn destroy(&mut self, handle: u64)
[src]
Destroys a resource, that has been bound to this allocator
see destroy_many
pub fn destroy_many(&mut self, handles: &[u64])
[src]
Destroys resources, that have been bound to this allocator
Destroys the buffer or image and makes their associated memory available again.
Freeing the memory is relatively expensive compared to allocation, which is why it should be preferred to use destroy_many
over just destroy
.
When multiple resources are destroyed in bulk, merging blocks of free memory and padding together with the freed allocation has to be done only once.
Note that memory bindings of not destroyed resources can not be rearranged, since vulkan does not allow rebinding a buffer/image to a different location.
Example
let mut allocator = vkmem::Allocator::new(pdevice.handle, device.handle); let mut buf = vk::NULL_HANDLE; let mut img = vk::NULL_HANDLE; //... create, bind, use ... allocator.destroy_many(&[buf, img]);
pub fn free_unused(&mut self)
[src]
Frees memory of unused pages
pub fn get_physical_device(&self) -> PhysicalDevice
[src]
Gets the physical device handle
pub fn get_device(&self) -> Device
[src]
Gets the device handle
pub fn get_mapped(&self, handle: u64) -> Option<Mapped>
[src]
Gets a Mapped of the spicified resource handle
Example
Creates a uniform buffer, stores some values in it and reads them back
let mut allocator = vkmem::Allocator::new(pdevice.handle, device.handle); #[derive(Debug)] struct Ub { a: u32, b: u32, c: u32 } let mut buf_ub = vk::NULL_HANDLE; vkmem::Buffer::new(&mut buf_ub) .size(std::mem::size_of::<Ub>() as vk::DeviceSize) .usage(vk::BUFFER_USAGE_TRANSFER_DST_BIT | vk::BUFFER_USAGE_UNIFORM_BUFFER_BIT) .devicelocal(false) .bind(&mut allocator, vkmem::BindType::Scatter) .unwrap(); { let mapped = allocator.get_mapped(buf_ub).unwrap(); let ubb = Ub { a: 123, b: 4, c: 5 }; mapped.host_to_device(&ubb); } { let mapped = allocator.get_mapped(buf_ub).unwrap(); let mut ubb = Ub { a: 0, b: 0, c: 0 }; mapped.device_to_host(&mut ubb); assert_eq!(ubb.a, 123); assert_eq!(ubb.b, 4); assert_eq!(ubb.c, 5); }
pub fn get_mapped_region(
&self,
handle: u64,
offset: DeviceSize,
size: DeviceSize
) -> Option<Mapped>
[src]
&self,
handle: u64,
offset: DeviceSize,
size: DeviceSize
) -> Option<Mapped>
Gets a Mapped of the spicified resource handle with an offset and size in bytes
Example
Creates a u32
shader storage buffer, mappes it with offset and writes and reads values
let mut allocator = vkmem::Allocator::new(pdevice.handle, device.handle); let mut buf = vk::NULL_HANDLE; vkmem::Buffer::new(&mut buf) .size(123 * std::mem::size_of::<u32>() as vk::DeviceSize) .usage(vk::BUFFER_USAGE_TRANSFER_DST_BIT | vk::BUFFER_USAGE_STORAGE_BUFFER_BIT) .devicelocal(false) .bind(&mut allocator, vkmem::BindType::Scatter) .unwrap(); { let mut mapped = allocator.get_mapped_region(buf, 4, 100).unwrap(); let v = mapped.as_slice_mut::<u32>(); v[0] = 123; v[1] = 4; v[2] = 5; } { let mapped = allocator.get_mapped_region(buf, 4, 100).unwrap(); let v = mapped.as_slice::<u32>(); assert_eq!(v[0], 123); assert_eq!(v[1], 4); assert_eq!(v[2], 5); }
pub fn print_stats(&self) -> String
[src]
Print staticstics for the Allocator in yaml format
Trait Implementations
Auto Trait Implementations
Blanket Implementations
impl<T, U> Into for T where
U: From<T>,
[src]
U: From<T>,
impl<T> From for T
[src]
impl<T, U> TryFrom for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = !
try_from
)The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T> Borrow for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> BorrowMut for T where
T: ?Sized,
[src]
T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
[src]
impl<T, U> TryInto for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,