Skip to main content

Module array_pool

Module array_pool 

Source
Expand description

A pool that packs many variable-size slices into one array.

The arrays a frame reads are frame-wide: one Array per kind serves every draw, and a draw names its slice inside it rather than binding a resource of its own. That works when the slices are of a fixed size — the metadata entries are — but a mesh’s morph displacements are as long as the mesh has vertices, so its slice has to be sub-allocated rather than indexed.

An ArrayPool is that: an Array plus an Allocator over its elements, handing out ArrayRanges. It keeps a CPU mirror of the array’s bytes, so writing a slice and publishing the array are separate steps — ArrayPool::write fills the mirror, ArrayPool::upload copies it to the resource. That is what lets several meshes’ slices be written into the one array before a single upload reaches the GPU.

§Element granularity

Ranges are counted in elements, the unit the array’s ArrayHandle indexes by, so a range’s element offset is exactly what a shader adds to its own base index. Elements are the smallest unit the pool deals in, so an allocator over them needs no alignment beyond one element.

§Growing

The pool doubles rather than re-packs: an Array cannot be resized, so growing replaces the resource and every range keeps its element offset. The CPU mirror carries the live data across, which is why the caller has to upload after an allocation that grew the pool.

§Example

use unlit_wgpu::array_pool::ArrayPool;

let (device, _queue) = wgpu::Device::noop(&wgpu::DeviceDescriptor::default());
// Elements of four bytes: one `f32` each.
let mut pool = ArrayPool::new(&device, "example::arrays", 4, 16, None);

let range = pool.allocate(&device, 3).expect("the pool has room");
pool.write(range, &[1.0f32.to_le_bytes(), 2.0f32.to_le_bytes(), 3.0f32.to_le_bytes()]
    .concat());

let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
    label: Some("example"),
});
pool.upload(&device, &mut encoder);
pool.release(range.allocation);

Re-exports§

use crate::offset_allocator::Allocation; 🔒
use crate::offset_allocator::Allocator; 🔒
use crate::offset_allocator::min_allocator_size; 🔒
use crate::texel_array::Array; 🔒
use crate::texel_array::ArrayHandle; 🔒
use core::num::NonZeroU32; 🔒

Structs§

ArrayPool
One array sub-allocated into element ranges, with a CPU mirror of its bytes.
ArrayRange
A range of elements inside an ArrayPool’s array.

Constants§

DEFAULT_MAX_RANGES 🔒
How many ranges a pool tracks unless the caller says otherwise.
ELEMENT_ALIGNMENT 🔒
The alignment elements are handed out at.
MIN_ELEMENTS 🔒
The smallest pool size, so the first grow has something to grow from.

Functions§

growth_step 🔒
The element count to grow current to so it covers end.