Skip to content

Commit

Permalink
Replace Suballocator::cleanup with Suballocator::reset (#2585)
Browse files Browse the repository at this point in the history
  • Loading branch information
marc0246 authored Oct 22, 2024
1 parent a0d45e7 commit 00fd847
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 35 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ raw-window-metal = "1.0"
serde = "1.0"
serde_json = "1.0"
shaderc = "0.8.3"
slabbin = "1.0"
slabbin = "1.1"
smallvec = "1.8"
syn = "2.0"
thread_local = "1.1"
Expand Down
2 changes: 1 addition & 1 deletion vulkano/src/memory/allocator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1632,7 +1632,7 @@ impl<S: Suballocator> DeviceMemoryBlock<S> {

// For bump allocators, reset the free-start once there are no remaining allocations.
if self.allocation_count == 0 {
self.suballocator.cleanup();
self.suballocator.reset();
}
}

Expand Down
20 changes: 13 additions & 7 deletions vulkano/src/memory/allocator/suballocator/buddy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ use std::cmp;
/// [`BumpAllocator`]: super::BumpAllocator
#[derive(Debug)]
pub struct BuddyAllocator {
region_offset: DeviceSize,
region: Region,
// Total memory remaining in the region.
free_size: DeviceSize,
// Every order has its own free-list for convenience, so that we don't have to traverse a tree.
Expand Down Expand Up @@ -105,7 +105,7 @@ unsafe impl Suballocator for BuddyAllocator {
free_list[max_order].push(region.offset());

BuddyAllocator {
region_offset: region.offset(),
region,
free_size: region.size(),
free_list,
}
Expand Down Expand Up @@ -136,7 +136,7 @@ unsafe impl Suballocator for BuddyAllocator {
let mut alignment = layout.alignment();

if buffer_image_granularity != DeviceAlignment::MIN {
debug_assert!(is_aligned(self.region_offset, buffer_image_granularity));
debug_assert!(is_aligned(self.region.offset(), buffer_image_granularity));

if allocation_type == AllocationType::Unknown
|| allocation_type == AllocationType::NonLinear
Expand Down Expand Up @@ -224,7 +224,7 @@ unsafe impl Suballocator for BuddyAllocator {

// This can't overflow because the offsets in the free-list are confined to the range
// [region.offset, region.offset + region.size).
let buddy_offset = ((offset - self.region_offset) ^ size) + self.region_offset;
let buddy_offset = ((offset - self.region.offset()) ^ size) + self.region.offset();

match free_list.binary_search(&buddy_offset) {
// If the buddy is in the free-list, we can coalesce.
Expand All @@ -250,6 +250,15 @@ unsafe impl Suballocator for BuddyAllocator {
}
}

fn reset(&mut self) {
self.free_size = self.region.size();
self.free_list.iter_mut().for_each(Vec::clear);

let max_order =
(self.region.size() / BuddyAllocator::MIN_NODE_SIZE).trailing_zeros() as usize;
self.free_list[max_order].push(self.region.offset());
}

/// Returns the total amount of free space left in the [region] that is available to the
/// allocator, which means that [internal fragmentation] is excluded.
///
Expand All @@ -260,9 +269,6 @@ unsafe impl Suballocator for BuddyAllocator {
self.free_size
}

#[inline]
fn cleanup(&mut self) {}

#[inline]
fn suballocations(&self) -> Self::Suballocations<'_> {
todo!()
Expand Down
21 changes: 8 additions & 13 deletions vulkano/src/memory/allocator/suballocator/bump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,6 @@ pub struct BumpAllocator {
}

impl BumpAllocator {
/// Resets the free-start back to the beginning of the [region].
///
/// [region]: Suballocator#regions
#[inline]
pub fn reset(&mut self) {
self.free_start = 0;
self.prev_allocation_type = AllocationType::Unknown;
}

fn suballocation_node(&self, part: usize) -> SuballocationNode {
if part == 0 {
SuballocationNode {
Expand Down Expand Up @@ -153,14 +144,18 @@ unsafe impl Suballocator for BumpAllocator {
// such complex, very wow
}

/// Resets the free-start back to the beginning of the [region].
///
/// [region]: Suballocator#regions
#[inline]
fn free_size(&self) -> DeviceSize {
self.region.size() - self.free_start
fn reset(&mut self) {
self.free_start = 0;
self.prev_allocation_type = AllocationType::Unknown;
}

#[inline]
fn cleanup(&mut self) {
self.reset();
fn free_size(&self) -> DeviceSize {
self.region.size() - self.free_start
}

#[inline]
Expand Down
29 changes: 23 additions & 6 deletions vulkano/src/memory/allocator/suballocator/free_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ use std::{cmp, iter::FusedIterator, marker::PhantomData, ptr::NonNull};
/// [alignment requirements]: super#alignment
#[derive(Debug)]
pub struct FreeListAllocator {
region_offset: DeviceSize,
region: Region,
// Total memory remaining in the region.
free_size: DeviceSize,
suballocations: SuballocationList,
Expand Down Expand Up @@ -98,7 +98,7 @@ unsafe impl Suballocator for FreeListAllocator {
};

FreeListAllocator {
region_offset: region.offset(),
region,
free_size: region.size(),
suballocations,
}
Expand Down Expand Up @@ -164,7 +164,7 @@ unsafe impl Suballocator for FreeListAllocator {
let mut offset = align_up(node.offset, alignment);

if buffer_image_granularity != DeviceAlignment::MIN {
debug_assert!(is_aligned(self.region_offset, buffer_image_granularity));
debug_assert!(is_aligned(self.region.offset(), buffer_image_granularity));

if let Some(prev_ptr) = node.prev {
let prev = unsafe { *prev_ptr.as_ptr() };
Expand Down Expand Up @@ -250,14 +250,31 @@ unsafe impl Suballocator for FreeListAllocator {
unsafe { self.suballocations.deallocate(node_ptr) };
}

fn reset(&mut self) {
self.free_size = self.region.size();
self.suballocations.free_list.clear();
unsafe { self.suballocations.node_allocator.reset() };

let root_ptr = self.suballocations.node_allocator.allocate();
let root = SuballocationListNode {
prev: None,
next: None,
offset: self.region.offset(),
size: self.region.size(),
allocation_type: SuballocationType::Free,
};
unsafe { root_ptr.as_ptr().write(root) };

self.suballocations.head = root_ptr;
self.suballocations.tail = root_ptr;
self.suballocations.len = 1;
}

#[inline]
fn free_size(&self) -> DeviceSize {
self.free_size
}

#[inline]
fn cleanup(&mut self) {}

#[inline]
fn suballocations(&self) -> Self::Suballocations<'_> {
self.suballocations.iter()
Expand Down
8 changes: 3 additions & 5 deletions vulkano/src/memory/allocator/suballocator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,16 +138,14 @@ pub unsafe trait Suballocator {
/// - `suballocation` must refer to a **currently allocated** suballocation of `self`.
unsafe fn deallocate(&mut self, suballocation: Suballocation);

/// Resets the suballocator, deallocating all currently allocated suballocations at once.
fn reset(&mut self);

/// Returns the total amount of free space that is left in the [region].
///
/// [region]: Self#regions
fn free_size(&self) -> DeviceSize;

/// Tries to free some space, if applicable.
///
/// There must be no current allocations as they might get freed.
fn cleanup(&mut self);

/// Returns an iterator over the current suballocations.
fn suballocations(&self) -> Self::Suballocations<'_>
where
Expand Down

0 comments on commit 00fd847

Please sign in to comment.