Expand description
A fast, hard-real-time sub-allocator over one contiguous range.
An Allocator owns a single block of size units — units being whatever
the caller needs, such as bytes, vertices or indices — and hands out
contiguous sub-ranges of it. It knows nothing about the resource behind the
range, which is what makes it usable for packing many small ranges into one
GPU buffer: allocate the range, then write the data at offset * unit_size.
The algorithm is the two-level segregated fit used by Sebastian Aaltonen’s
OffsetAllocator: free ranges (“nodes”) are filed into 256 bins whose
boundaries follow an 8-bit float distribution (a 3-bit mantissa and a 5-bit
exponent), so that the relative overhead of rounding to a bin stays under
12.5% for every size class. Two bitfields — one per top-level bin, one per
leaf bin — make the search for the next fitting bin two trailing_zeros
instructions, so Allocator::allocate and Allocator::free are O(1)
and never allocate.
Every allocation starts at a multiple of the alignment fixed at construction, which is what a GPU buffer sub-allocation needs: the size charged for an allocation is the requested size rounded up to that alignment.
§Known limitation
A free range is filed under the bin of its rounded-down size, while an
allocation searches from the bin of its rounded-up size. A range whose
size is not exactly representable by a bin is therefore never found by an
allocation of exactly that size, even though it would fit — so
Allocator::new(size).allocate(size) fails for most size values. Size the
allocator with min_allocator_size (and, for aligned allocators, pass the
same alignment) to make the initial free range representable:
use unlit_wgpu::offset_allocator::{Allocator, min_allocator_size};
use core::num::NonZeroU32;
let mut allocator = Allocator::new(min_allocator_size(1000, NonZeroU32::MIN));
assert!(allocator.allocate(1000).is_some());Re-exports§
use core::fmt::Debug;🔒use core::fmt::Debug;🔒use core::fmt::Formatter;🔒use core::fmt::Result as FmtResult;🔒use core::num::NonZeroU32;🔒
Modules§
- small_
float 🔒 - The 8-bit float size distribution the bins follow.
Structs§
- Allocation
- A single allocation, handed out by
Allocator::allocate. - Allocator
- An allocator that manages a single contiguous chunk of space and hands out portions of it as requested.
- Node 🔒
- A range of the managed chunk: either an allocation or the free space around one.
- Node
Index 🔒 - The index of a
Node. - Storage
Report - Provides a summary of the state of the allocator, including space remaining.
Constants§
- BINS_
PER_ 🔒LEAF - The number of leaf bins per top-level bin.
- DEFAULT_
MAX_ 🔒NODES - The number of nodes an allocator tracks unless the caller says otherwise.
- LEAF_
BINS_ 🔒INDEX_ MASK - The mask of the leaf bin index within a leaf bin index.
- NUM_
LEAF_ 🔒BINS - The number of leaf bins, i.e. of distinct size classes.
- NUM_
TOP_ 🔒BINS - The number of top-level bins.
- TOP_
BINS_ 🔒INDEX_ SHIFT - The bit position of a top-level bin index within a leaf bin index.
Functions§
- align_
up 🔒 - Rounds
sizeup to the next multiple ofalignment. - find_
lowest_ 🔒bit_ set_ after - Returns the index of the lowest set bit of
bit_maskat or afterstart_bit_index, orNoneif there is none. - min_
allocator_ size - The smallest allocator size that can hold an allocation of
sizeunits at the givenalignment.