Sort a buffer of keys on the GPU, carrying a payload such as indices along with them.
kit.sorter
module
sorter.create(root, keys, options?)→ Sorter
rootborrows
the root
keystakes
the buffer to sort, with storage usage
Sorterreturns
a sorter you destroy
types
KeySorter
Optionscreate · 6 fields
values?
Storage<V>= no payload
Holds a payload, such as indices into your own data, that moves with its key.
out?
{ keys: Storage<K>; values?: Storage<V> }= sorting keys and values in place
Receives the sorted keys and payload, and leaves keys and values as they were.
direction?
'ascending' | 'descending'= 'ascending'
Puts the largest key first with 'descending'.
range?
[min: number, max: number]= the whole range of the key's type
Clamps each key into [min, max].
keyBits?
number= what range needs, or 32
Sorts by this many low bits of the key that range or key makes, eight a pass.
key?
(key: number) => number= the key's own order
Maps a key to a u32 whose order is the sort order, in place of the map for the key's type.
records
sort→compute
sort in a compute pass after whatever writes the keys.
owns
buffers ·pipelines ·bind groups
Counts per 2 048 keys, a copy of the keys and payload to sort through, and the scan of the counts.
lifecycle
✓initAsync()✓destroy()✓[Symbol.dispose]
Tap a key, or use the arrow keys, to follow it and its payload letter through the passes. Each pass orders the keys by one digit, lowest first, and keeps keys with the same digit in the order the last pass left them, so the two 42s never swap. The sorter takes eight bits a pass where the figure takes one decimal digit.
Blended splats and particles draw back to front, so their order changes whenever the camera moves. A list drawn by depth, or rows grouped by a cell or a material, needs the same thing: keys a kernel wrote, sorted, with the index of each key’s row beside it. sorter.create sorts a buffer of keys in a compute pass of your frame, and moves a payload buffer with them. Keys that compare equal keep their order.
Creates a stable radix sort of a buffer of keys, eight bits a pass, which carries a payload
along. Keys that compare equal keep their order, so a sort repeats exactly. Its cost follows the
buffer's length and keyBits, not the keys' order. An f32 sort ranks -0 and +0 equal.
@owns ― buffers, pipelines, bind groups: counts per 2 048 keys, a copy of the keys and payload to
sort through, and the scan of the counts
@records ― sort in a compute pass after whatever writes the keys
@param ― keys the buffer to sort, with storage usage
Holds a payload, such as indices into your own data, that moves with its key. It has as many
elements as keys. With out, it requires out.values. Default no payload.
Clamps each key into [min, max]. Integer keys sort from min, in the bits max - min
needs; f32 keys sort in 2^keyBits even steps, where keys in one step keep their order.
Default the whole range of the key's type.
range:[0,1],
Options<K extends Key = Key,V extends d.AnyWgslData= AnyWgslData>.keyBits?: number |undefined
Sorts by this many low bits of the key that range or key makes, eight a pass. Below 32 on
i32 and f32 keys requires range or key. Default what range needs, or 32.
Records a frame into one encoder and submits once, with a clock. Borrows the root. The
synchronous recorder borrows each frame's encoder.
@submits ― always once a frame after your recorder returns, and again at each frame.submit()
@param ― record your frame, recorded into each frame's encoder
@returns ― a loop you run with each frame's time and destroy
create(
constroot:TgpuRoot
root,(
frame:frames.Frame
frame)=>{
const
constcompute:TgpuComputePass
compute=
frame:frames.Frame
frame.
Frame.encoder: TgpuCommandEncoder
Records commands for submission after the recorder returns. submit() replaces this encoder.
Read it at each call instead of keeping it, and let the frame submit it.
values moves with the keys, element for element. It is usually each key’s index, which a later kernel or draw reads its row through. The sort runs in place by default. With out, it writes the sorted keys and payload to other buffers and leaves keys and values as they were; this also saves the copy back that an odd number of passes ends with in place.
sort(pass) records a count, a scan and a scatter per eight bits, and sets its own pipelines and bind groups. Record it in a compute pass after the kernel that writes the keys.