No description provided yet.
Interface
What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.
conforms to
zero/source-extract/v2proc.device — the passes every op composes to work over elements on the device: counts that live in a buffer, prefix sums, compaction, gathers bounded by a device count, a free list of slots, and appends clamped to what the run can hold. Nothing here runs a loop over elements in Luau. Each call records dispatches; the element counts they work to are words in device buffers, written by one pass and read by the next, so no pass waits on the CPU to learn how many elements there are. Runs are sized to a CAPACITY the CPU knows; the count says how much of the run is live, and every kernel dispatched over the capacity leaves the rest alone. A count is a one-word run read as a u32. An index is carried in an f32 run, as every index in the substrate is, exact up to 2^24.
bufferName(col: any, what: string, binding: number) → string
| arg | type | description |
|---|---|---|
| col | any | |
| what | string | |
| binding | number |
writesOf(name: string, bindings: { any }) → void
Remember which of a program's storage bindings it writes - every one whose access is not "read" - so `wrote` can say so of the runs a dispatch of it binds.
| arg | type | description |
|---|---|---|
| name | string | The program's key. |
| bindings | { any } | The storage bindings it was compiled with, in order. |
examples
proc.device.writesOf("sim_integrate", bindings)wrote(name: string, cols: { any }) → void
Note that a dispatch of the program `name` over `cols` wrote the runs its writable bindings name, so a read of any of them taken before goes.
| arg | type | description |
|---|---|---|
| name | string | The program's key. |
| cols | { any } | The Columns the dispatch bound, in binding order. |
examples
proc.device.wrote("sim_integrate", { P, v, accel })wroteRun(col: any) → void
Note that a dispatch wrote the run `col`, so a read of it taken before goes — and, while `record` is recording, that replaying the recording writes it too.
| arg | type | description |
|---|---|---|
| col | any | The Column a dispatch wrote. |
examples
proc.device.wroteRun(state:column("point", "P"))record(name: string, fn: (any) →
Run `fn`, its dispatches queued as they always are, and keep them as a list the device replays with one call. `list:run(values)` queues the same dispatches over the same runs again, each slotted param taking its value from `values`, and notes every run they write as written; `list:release()` lets it go. `fn` is handed a recorder whose `slotLast({ [param] = slot })` names which params of the dispatch it just made a run gives; every other value stays as recorded. `write(col, values, slots)` writes `values` into the run `col` now and records the write, the value at each place `slots` names (from 1) taken from that slot on a run. `guard(slot, body)` runs `body` and leaves every dispatch it made out of a run that gives `slot` as 0. A recording binds runs by name, so it stands for as long as every run `fn` bound does, and one made over runs that are later let go of is recorded again.
| arg | type | description |
|---|---|---|
| name | string | What the list is for, which its key starts with. |
| fn | (any | The work to record, given the recorder. |
examples
local list = proc.device.record("sim_step", function(rec) dispatchStep(dt); rec:slotLast({ dt = "dt" }) end)slotLast(_self: any, slots: { [string]: string }) → void
| arg | type | description |
|---|---|---|
| _self | any | |
| slots | { [string]: string } |
write(_self: any, col: any, values: { number }, slots: { [number]: string }?) → void
| arg | type | description |
|---|---|---|
| _self | any | |
| col | any | |
| values | { number } | |
| slots | { [number]: string }? |
guard(_self: any, slot: string, body: () → void
| arg | type | description |
|---|---|---|
| _self | any | |
| slot | string | |
| body | ( |
writeCounterOf(list: any) → any
The write counter the runs a list writes share, made the first time the list runs.
| arg | type | description |
|---|---|---|
| list | any |
run(self: any, values: { [string]: number }?) → boolean
Queue the list's dispatches again, each slotted param taking its value from `values`, and note the runs they write as written: one note of the write counter they share.
| arg | type | description |
|---|---|---|
| self | any | |
| values | { [string]: number }? | The value of each slot, by name. |
release(self: any) → void
Let the list go, and every chain it is part of with it.
| arg | type | description |
|---|---|---|
| self | any |
renamedEntry(entry: any, rename: (string) → void
An entry as a chain holds it, every slot it names and the slot that leaves it out renamed through `rename`.
| arg | type | description |
|---|---|---|
| entry | any | |
| rename | (string |
chain(name: string, lists: { any }) → any
One list queueing the entries of each of `lists` in turn, in one call: what running each of them queues. The slots of each list are its own in the chain, so one list chained twice takes a value for each place: `chain.slotsOf[i][slot]` is what slot `slot` of the `i`-th list is named in the chain, and a run gives each its value under that name; a slot given no value keeps the value its list recorded. It notes every run they write as written, and goes when the first of them is let go of.
| arg | type | description |
|---|---|---|
| name | string | What the chain is for, which its key starts with. |
| lists | { any } | The lists, in the order they run; a list may stand in it more than once. |
examples
local chain = proc.device.chain("present", { first, second })rename(slot: string) → string
| arg | type | description |
|---|---|---|
| slot | string |
kernelOnce(make: (any?, any?) →
A kernel builder that generates and compiles its kernel once per set of arguments: `make(a, b)` builds the kernel's source, compiles it and with that name without generating the source again. A build that raises keeps nothing, so the next call builds again. kernel's name.
| arg | type | description |
|---|---|---|
| make | (any?, any? | The builder, taking up to two arguments and returning the |
examples
local gatherKernel = proc.device.kernelOnce(function(lanes) return build(lanes) end)
program(name: string, source: string, bindings: { any }, params: { any }?) → void
| arg | type | description |
|---|---|---|
| name | string | |
| source | string | |
| bindings | { any } | |
| params | { any }? |
asNumbers(col: any, what: string, binding: number) → any
`col` as a run of f32 words, for a binding that reads numbers: an index or a count a column of Int holds as i32 words is converted on the device. The converted run is kept on `col` for the version it was made from and goes with `col`; a recording converts again, so replaying it reads what `col` holds then.
| arg | type | description |
|---|---|---|
| col | any | |
| what | string | |
| binding | number |
run(name: string, cols: { any }, groups: number, out: any?, what: string, values: { [string]: number }?) → void
Queue `name` over the named runs, and let `out` hold every input until the device has read it: a dispatch reports only that it was queued.
| arg | type | description |
|---|---|---|
| name | string | |
| cols | { any } | |
| groups | number | |
| out | any? | |
| what | string | |
| values | { [string]: number }? |
blocks(n: number) → number
| arg | type | description |
|---|---|---|
| n | number |
grid(count: number, width: number) →
The workgroup grid a dispatch over `count` elements takes, `width` elements to a group: one row while the groups fit the 65,535 a device takes on one dimension, and rows of 65,535 past it. A kernel dispatched on it reads its element as `gid.x + gid.y * nwg.x * width`, with `nwg` the `@builtin(num_workgroups)`, and returns for an element at or past `count`.
| arg | type | description |
|---|---|---|
| count | number | Elements the dispatch covers. |
| width | number | Elements one workgroup covers: the kernel's `@workgroup_size`. |
examples
compute.program.dispatch(name, { buffers = names, workgroups = device.grid(n, 64) })count(value: number?) → any
A count held on the device: one word, read by kernels as a u32.
| arg | type | description |
|---|---|---|
| value | number? | The count it starts at. Default 0. |
examples
local live = proc.device.count(0)
readCount(count: any) → number
What a device count holds, read back to the CPU. A readback: it waits for the device and is for inspection and tests, never for sizing work.
| arg | type | description |
|---|---|---|
| count | any | A count from this module. |
examples
print(proc.device.readCount(live))
scan(values: any, count: any, capacity: number, mode: string?) →
The exclusive prefix sum of a run, on the device: each element's offset is the sum of the values before it, and the total is a device count. The run is scanned over `capacity`; elements at and past `count` add nothing. `mode` reads each value as a count ("counts", rounded), as a flag ("flags", any non-zero value is 1) or as a u32 word ("words", what an atomic count writes).
| arg | type | description |
|---|---|---|
| values | any | An f32 Column holding at least `capacity` elements. |
| count | any | A device count of the live elements, or a number. |
| capacity | number | How many elements the run is scanned over. |
| mode | string? | "counts" (default), "flags" or "words". |
examples
local offsets, total = proc.device.scan(births, live, 4096)
inverseOf(indices: any) → any
The map from every element to its place among the kept ones (-1 for one not kept) that the compaction writing `indices` keeps beside them, or nil when it keeps none. Written by the same pass as the indices, so it holds for them whenever they stand.
| arg | type | description |
|---|---|---|
| indices | any | An index run a compaction wrote. |
examples
local inv = proc.device.inverseOf(slots)
compact(keep: any, count: any, capacity: number) →
The indices of the elements a flag run keeps, in their order, and how many there are — on the device. A filter, a split, the live particles of a solver and the members of any set are this.
| arg | type | description |
|---|---|---|
| keep | any | An f32 Column: non-zero keeps the element. |
| count | any | A device count of the elements to consider, or a number. |
| capacity | number | How many elements the run holds at most. |
examples
local live, n = proc.device.compact(alive, slots, 4096)
workFor(work: any, capacity: number, count: any) → any
A work table sized for `capacity` elements — every run it held for another size let go of — and the count a number of live elements stands in.
| arg | type | description |
|---|---|---|
| work | any | |
| capacity | number | |
| count | any |
scanInto(work: any, values: any, count: any, capacity: number, mode: string?) →
What `M.scan` answers, written into runs `work` keeps from one call to the next: a pass that scans on every present makes its runs once. The offsets and the total are `work`'s own, rewritten by the next call. runs go.
| arg | type | description |
|---|---|---|
| work | any | A table the caller keeps, `{}` at first; `releaseWork` lets its |
| values | any | As `M.scan`'s. |
| count | any | As `M.scan`'s. |
| capacity | number | As `M.scan`'s. |
| mode | string? | As `M.scan`'s. |
examples
local offsets, total = proc.device.scanInto(book.scan, births, live, 4096)
compactInto(work: any, keep: any, count: any, capacity: number, inverse: boolean?) →
What `M.compact` answers, written into runs `work` keeps from one call to the next — the live elements of a solver on every present, with nothing made for them after the first. runs go. its place among them (`M.inverseOf`).
| arg | type | description |
|---|---|---|
| work | any | A table the caller keeps, `{}` at first; `releaseWork` lets its |
| keep | any | As `M.compact`'s. |
| count | any | As `M.compact`'s. |
| capacity | number | As `M.compact`'s. |
| inverse | boolean? | Whether to keep beside the indices the map from every element to |
examples
local live, n = proc.device.compactInto(book.live, alive, 4096, 4096)
releaseWork(work: any) → void
Let go of the runs a `scanInto` or `compactInto` work table holds.
| arg | type | description |
|---|---|---|
| work | any | The table. |
examples
proc.device.releaseWork(book.live)
valueParams(value: { number }?, lanes: number) → void
| arg | type | description |
|---|---|---|
| value | { number }? | |
| lanes | number |
wordOf(element: string, expr: string) → string
The number `expr` (an f32 expression) as the word a run of `element` holds: an `Int` run holds i32 words and a `UInt` run u32 words, so a value written into one is converted to the integer it names.
| arg | type | description |
|---|---|---|
| element | string | |
| expr | string |
letterOf(element: string) → string
The first letter of a word form, `f`, `i` or `u`, which a kernel's key carries for the run it writes.
| arg | type | description |
|---|---|---|
| element | string | `"f32"`, `"i32"` or `"u32"`. |
examples
proc.device.letterOf(col:element()) --> "i"
elementOfLetter(letter: string) → string
The word form a letter of `letterOf` names.
| arg | type | description |
|---|---|---|
| letter | string | `"f"`, `"i"` or `"u"`. |
examples
proc.device.elementOfLetter("i") --> "i32"gatherKey(lanes: number, dst: any) → string
The gather kernel that writes `dst`'s words from a source of `lanes`.
| arg | type | description |
|---|---|---|
| lanes | number | |
| dst | any |
gather(src: any, indices: any, count: any, capacity: number) → any
The elements of a run at `indices`, the first `count` of them, into a run of `capacity` — on the device. An index naming no element of `src`, below 0 or past its end, reads zeros.
| arg | type | description |
|---|---|---|
| src | any | A GPU Column. |
| indices | any | An f32 Column of source indices. |
| count | any | A device count of how many indices are live, or a number. |
| capacity | number | How many elements the result holds. |
examples
local P = proc.device.gather(state.P, live, n, 4096)
gatherInto(dst: any, src: any, indices: any, count: any) → any
The elements of a run at `indices`, the first `count` of them, into `dst`, a run standing — on the device. What `M.gather` does into a run of its own; the caller keeps what it reads standing until the device has read it.
| arg | type | description |
|---|---|---|
| dst | any | A GPU Column of `src`'s type the elements land in. |
| src | any | A GPU Column. |
| indices | any | An f32 Column of source indices. |
| count | any | A device count of how many indices are live. |
examples
proc.device.gatherInto(standing.P, state.P, live, n)
scatterRun(out: any, src: any, indices: any, count: any, fill: ({ number } | false) → void
`src` scattered into `out` by `indices`, the other elements filled first; `holder` is the column that holds what the scatter reads, if any.
| arg | type | description |
|---|---|---|
| out | any | |
| src | any | |
| indices | any | |
| count | any | |
| fill | ({ number } | false |
scatter(src: any, indices: any, count: any, capacity: number, fill: ({ number } | false) →
The first `count` elements of `src` written to the places `indices` names, in a run of `capacity` whose other elements hold `fill` — on the device. The inverse of `gather`: what puts elements back where they stand, a compacted set back onto the slots it was taken from. element takes. per lane. Default zeros; `false` leaves those elements holding whatever the run held, for a caller that never reads them.
| arg | type | description |
|---|---|---|
| src | any | A GPU Column, or a constant Column whose one value every scattered |
| indices | any | An f32 Column of destination places. |
| count | any | A device count of how many indices are live, or a number. |
| capacity | number | How many elements the result holds. |
| fill | ({ number } | false | The value every element nothing is scattered to holds, one number |
examples
local P = proc.device.scatter(points.P, slots, n, 4096)
scatterInto(dst: any, src: any, indices: any, count: any, fill: ({ number } | false) →
What `M.scatter` does, into `dst`, a run standing: every element nothing is scattered to filled with `fill` again, and the first `count` of `src` written where `indices` names. The caller keeps what it reads standing until the device has read it.
| arg | type | description |
|---|---|---|
| dst | any | A GPU Column of `src`'s lanes the elements land in. |
| src | any | A GPU Column, or a constant Column. |
| indices | any | An f32 Column of destination places. |
| count | any | A device count of how many indices are live. |
| fill | ({ number } | false | As `M.scatter`'s. |
examples
proc.device.scatterInto(standing.P, points.P, slots, n)
filled(t: string, capacity: number, value: { number }?) → any
A run of `capacity` elements of type `t`, every one holding `value` (one number per lane; default zeros) — on the device.
| arg | type | description |
|---|---|---|
| t | string | The column type. |
| capacity | number | How many elements it holds. |
| value | { number }? | The value, one number per lane. |
examples
local zeros = proc.device.filled("Vec3", 4096)fillInto(dst: any, value: { number }?) → any
Every element of `dst`, a run standing, set to `value` (one number per lane; default zeros) — on the device.
| arg | type | description |
|---|---|---|
| dst | any | A GPU Column. |
| value | { number }? | The value, one number per lane. |
examples
proc.device.fillInto(state:column("point", "alive"))iota(capacity: number) → any
A run of `capacity` indices, each element holding its own: 0, 1, 2 ... — the indices of a set that stands where it is.
| arg | type | description |
|---|---|---|
| capacity | number | How many elements it holds. |
examples
local here = proc.device.iota(4096)
copy(dst: any, src: any) → void
Copy `src` into `dst`, word for word, on the device: afterwards `dst` holds exactly what `src` held, a count or a float alike. The two are runs of one type and length. `dst` holds `src` until the next copy into it, so a run let go of straight after the copy is still there when the device reads it.
| arg | type | description |
|---|---|---|
| dst | any | A GPU Column. |
| src | any | A GPU Column of the same type and length. |
examples
proc.device.copy(standing, fresh)
copyAt(dst: any, at: number, src: any, count: number) → void
Copy the first `count` elements of `src` into `dst` from element `at` on, word for word, on the device. The two are runs of one type; `dst` holds `src` until it goes, so a run let go of straight after the copy is still there when the device reads it.
| arg | type | description |
|---|---|---|
| dst | any | A GPU Column. |
| at | number | The element of `dst` the first one lands at. |
| src | any | A GPU Column of the same type. |
| count | number | How many elements to copy. |
examples
proc.device.copyAt(frames, (f - 1) * capacity, framePositions, count)
placeShifted(dst: any, src: any, base: any, count: any, capacity: number, shift: any, held: boolean?) → any
Place the first `count` indices of `src` into `dst` starting at the element `base` names, each moved by the count `shift` holds — on the device. What joins parts whose indices address their own elements: a corner's point moved past the points of the parts before it. Default true.
| arg | type | description |
|---|---|---|
| dst | any | An f32 GPU Column the indices land in. |
| src | any | An f32 GPU Column of indices. |
| base | any | A device count: the element of `dst` the first one lands at. |
| count | any | A device count of how many to place. |
| capacity | number | The most `count` can be, which sizes the dispatch. |
| shift | any | A device count added to every index. |
| held | boolean? | Whether `dst` holds the runs the placement reads until it goes. |
examples
proc.device.placeShifted(joinedPt, part.pt, vertexAt, vertices, cap, pointAt)
lanesKey(lanes: { number }) → string
The lanes of each pair in a fused dispatch, as the part of its program's name that tells one set of widths from another.
| arg | type | description |
|---|---|---|
| lanes | { number } |
gatherManyInto(pairs: { { any } }, indices: any, count: any) → void
What `M.gatherInto` does for each pair, in a third of the dispatches: for every `{ dst, src }`, the elements of `src` at the first `count` of `indices` written into `dst`, a run standing. The caller keeps what they read standing until the device has read it.
| arg | type | description |
|---|---|---|
| pairs | { { any } } | `{ { dst, src }, ... }`, GPU Columns of matching lanes. |
| indices | any | An f32 Column of source indices. |
| count | any | A device count of how many indices are live. |
examples
proc.device.gatherManyInto({ { outP, P }, { outV, v } }, live, n)placeManyInto(entries: { { any } }, base: any, count: any, capacity: number, held: boolean?) → void
What `M.place` does for each entry whose source is a run, in a third of the dispatches: for every `{ dst, src, mul, add }`, the first `count` elements of `src` placed into `dst` from the element `base` names, each value written as `v * mul + add`. lanes; `mul` defaults to 1 and `add` to 0. goes. Default true; a caller keeping them standing itself passes false.
| arg | type | description |
|---|---|---|
| entries | { { any } } | `{ { dst, src, mul?, add? }, ... }`, GPU Columns of matching |
| base | any | A device count: the element of each `dst` the first one lands at. |
| count | any | A device count of how many to place. |
| capacity | number | The most `count` can be, which sizes the dispatch. |
| held | boolean? | Whether each `dst` holds the runs its placement reads until it |
examples
proc.device.placeManyInto({ { joinedP, P }, { joinedId, id, 2, 0 } }, at, n, 4096, false)add(a: any, b: any) → any
The sum of two device counts, as a new one.
| arg | type | description |
|---|---|---|
| a | any | A device count. |
| b | any | A device count. |
examples
local total = proc.device.add(nA, nB)
addInto(dst: any, a: any, b: any) → any
The sum of two device counts, written into `dst`, a count standing. The caller keeps `a` and `b` standing until the device has read them.
| arg | type | description |
|---|---|---|
| dst | any | A device count. |
| a | any | A device count. |
| b | any | A device count. |
examples
proc.device.addInto(bases[2], bases[1], nA)
sortInto(work: any, keys: any, count: any, capacity: number, bits: number) → any
The order of a run's elements by a u32 key, on the device: a stable radix sort, 8 bits a pass, into runs `work` keeps from one call to the next. Elements with equal keys keep their order, and every element at or past `count` comes after every live one, so a caller never reads the count back to know where the live ones end. runs go.
| arg | type | description |
|---|---|---|
| work | any | A table the caller keeps, `{}` at first; `releaseWork` lets its |
| keys | any | A run of `capacity` u32 keys (a Float Column read as words). |
| count | any | A device count of the live elements, or a number. |
| capacity | number | How many elements the run holds. |
| bits | number | How many low bits of a key it orders by; a key uses no more. |
examples
local order = proc.device.sortInto(work, cellKeys, live, 4096, 16)
gridInto(work: any, P: any, count: any, capacity: number, cellSize: number, bits: number?) → any
A spatial hash grid over points, on the device: every live point's cell (of side `cellSize`) hashed into one of 2^`bits` buckets, the points ordered by bucket — stably, so the same points give the same grid — and where each bucket's points start and end in that order. A kernel finding the points near a point walks it with `GRID_WGSL`, binding `cfg`, `range` and `order` as `gcfg`, `grange` and `gorder`: a neighbour search then costs the points in the 27 cells around a point rather than all of them. Its runs are `work`'s, built again in place by the next call. runs go. many buckets as points, between 2^4 and 2^16.
| arg | type | description |
|---|---|---|
| work | any | A table the caller keeps, `{}` at first; `releaseWork` lets its |
| P | any | A Vec3 GPU Column of positions. |
| count | any | A device count of the live points, or a number. |
| capacity | number | How many points the run holds. |
| cellSize | number | The side of a cell: at least the radius a search looks within. |
| bits | number? | How many buckets, as a power of two. Default: enough for twice as |
examples
local grid = proc.device.gridInto(work, points.P, live, 4096, radius)
fanNormals(P: any, pt: any, vstart: any, vcount: any, faceOf: any, vertices: number) → any
Each corner's normal from the fan triangles it belongs to, summed by area and made unit length (0, 1, 0 where they cancel), on the device: the normals a face list draws with when neither its corners nor its points carry any.
| arg | type | description |
|---|---|---|
| P | any | The points' positions, a GPU Vec3 Column. |
| pt | any | The point each corner lands on, a GPU Column. |
| vstart | any | Where each face's corners start, a GPU Column. |
| vcount | any | How many corners each face has, a GPU Column. |
| faceOf | any | The face each corner belongs to (`primitiveOf`), a GPU Column. |
| vertices | number | How many corners there are. |
examples
local N = proc.device.fanNormals(P, pt, vstart, vcount, faceOf, nv)
mode(from: string?, run: any?) → number
| arg | type | description |
|---|---|---|
| from | string? | |
| run | any? |
reset(count: any) → any
Set a device count back to zero, as a dispatch — so it lands between the passes around it, where a write from the CPU would land before all of them.
| arg | type | description |
|---|---|---|
| count | any | A device count. |
examples
proc.device.reset(deadCount)
clampCount(count: any, capacity: number) → any
Bring a device count back to at most `capacity` — what an append pass whose threads outran the run leaves it at.
| arg | type | description |
|---|---|---|
| count | any | A device count. |
| capacity | number | The most it may hold. |
examples
proc.device.clampCount(hits, 1024)
freeList(capacity: number) → any
A free list of `capacity` slots on the device: every slot free, the lowest handed out first. Slots are taken with `reserve` and given back with `push`, each a dispatch; which slots and how many never reach the CPU.
| arg | type | description |
|---|---|---|
| capacity | number | How many slots it holds. |
examples
local free = proc.device.freeList(4096)
reserve(self: ?, requested: any, into: any?) → any
Take up to `requested` slots. The grant is a two-word run: word 0 is where the taken slots start in `slots`, word 1 how many were taken (fewer than asked when the list runs short). A kernel reads the slot for its i-th new element as `slots[grant[0] + i]` for `i < grant[1]`. reserves every step keeps rather than making one each time. Omitted, a new one is made.
| arg | type | description |
|---|---|---|
| self | ? | |
| requested | any | A device count, or a number. |
| into | any? | A two-word Column to write the grant into, which a caller that |
examples
local grant = free:reserve(births)
push(self: ?, indices: any, count: any) → any
Give slots back: the first `count` indices of `indices` return to the list.
| arg | type | description |
|---|---|---|
| self | ? | |
| indices | any | An f32 Column of slots. |
| count | any | A device count, or a number. |
examples
free:push(dead, deadCount)
refill(self: ?) → any
Every slot free again, the lowest handed out first — the list as `freeList` made it, in the runs it already holds.
| arg | type | description |
|---|---|---|
| self | ? |
examples
free:refill()
release(self: ?) → void
Release the list's runs.
| arg | type | description |
|---|---|---|
| self | ? |
histogram(keys: any, count: any, buckets: number) → any
How many live elements carry each key, on the device: bucket b holds the number of elements whose key is b. A key below 0 or past the last bucket is counted nowhere. The counts are u32 words — `scan` in "words" mode turns them into where each bucket's elements start.
| arg | type | description |
|---|---|---|
| keys | any | An f32 Column of whole-number keys. |
| count | any | A device count of the live elements, or a number. |
| buckets | number | How many buckets there are. |
examples
local perPoint = proc.device.histogram(pointOfVertex, vertices, pointCount)
words(keys: any) → any
Whole-number keys held as floats — an index attribute, a group id — as the u32 words `sortInto` orders by, on the device. A negative key reads 0.
| arg | type | description |
|---|---|---|
| keys | any | An f32 Column. |
examples
local order = proc.device.sortInto(work, proc.device.words(groupOf), live, n, 16)
reduceOf(op: string?) → void
| arg | type | description |
|---|---|---|
| op | string? |
laneType(lanes: number) → string
| arg | type | description |
|---|---|---|
| lanes | number |
sameLanesType(values: any, lanes: number) → string
The type a reduction of `values` answers in: its own when it is read at the lanes it holds, so a colour folds to a colour.
| arg | type | description |
|---|---|---|
| values | any | |
| lanes | number |
releaseEdges(edges: any) → void
Let go of every run an `edges` table holds.
| arg | type | description |
|---|---|---|
| edges | any | A table from `edges`. |
examples
proc.device.releaseEdges(edges)
fromEnds(values: any, lanes: number, a: any, b: any, count: any, capacity: number, op: string?) → any
Values on elements that each join two ends — an edge its two points, a triangle side the two corners it runs between — each folded from the values at its ends by `op`, on the device.
| arg | type | description |
|---|---|---|
| values | any | A GPU Column of `lanes` floats per end. |
| lanes | number | Floats per element, 1 to 4. |
| a | any | Each element's first end, an f32 Column. |
| b | any | Each element's second end, an f32 Column. |
| count | any | A device count of the live elements. |
| capacity | number | How many elements the runs hold. |
| op | string? | "sum", "mean" (default), "min" or "max". |
examples
local heatOnEdges = proc.device.fromEnds(heat, 1, edges.a, edges.b, edges.count, edges.capacity, "mean")
reduce(values: any, lanes: number, count: any, capacity: number, op: string?) → any
One value from every live element of a run, on the device: their sum, mean, least or greatest, per lane — the total of a column, its centroid, its bounds. The elements past `count` take no part.
| arg | type | description |
|---|---|---|
| values | any | A GPU Column of `lanes` floats per element. |
| lanes | number | Floats per element, 1 to 4. |
| count | any | A device count of the live elements, or a number. |
| capacity | number | How many elements the run holds. |
| op | string? | "sum" (default), "mean", "min" or "max". |
examples
local centroid = proc.device.reduce(P, 3, live, 4096, "mean")
fillParams(fill: { number }?) → void
A fill of one number per lane as the params the segment kernel reads.
| arg | type | description |
|---|---|---|
| fill | { number }? |
primitiveOf(vstart: any, vcount: any, prims: any, capacity: number, vertices: number) → any
The primitive each vertex belongs to, on the device: every live primitive names itself on the run of vertices it starts. How a per-face value reaches its corners, and how corners fold back onto their face.
| arg | type | description |
|---|---|---|
| vstart | any | Where each primitive's vertices start, a GPU Column. |
| vcount | any | How many vertices each primitive has, a GPU Column. |
| prims | any | A device count of the live primitives, or a number. |
| capacity | number | How many primitives the runs hold. |
| vertices | number | How many vertices there are. |
examples
local faceOf = proc.device.primitiveOf(vstart, vcount, live, nprim, nv)
vertexNormals(P: any, pt: any, vstart: any, vcount: any, curve: any, points: number, vertices: number, prims: number, work: any) → any
Each point's normal from the faces around it, on the device: the sum of their normals weighted by their area, at unit length — a point on no face points up. Curves take no part. The vertices are ordered by the point they land on with a stable sort, so the same surface sums the same way every time.
| arg | type | description |
|---|---|---|
| P | any | The points' positions, a GPU Vec3 Column. |
| pt | any | The point each vertex lands on, a GPU Column. |
| vstart | any | Where each primitive's vertices start, a GPU Column. |
| vcount | any | How many vertices each primitive has, a GPU Column. |
| curve | any | Non-zero for a primitive that is a curve, a GPU Column. |
| points | number | How many points there are. |
| vertices | number | How many vertices there are. |
| prims | number | How many primitives there are. |
| work | any | A table the caller keeps for the sort's runs, `{}` at first. |
examples
local N = proc.device.vertexNormals(P, pt, vstart, vcount, curve, np, nv, nprim, work)
floats(words: any) → any
u32 words — the order a sort hands back — as the f32 indices `gather` and `scatter` read, on the device.
| arg | type | description |
|---|---|---|
| words | any | A Column of u32 words. |
examples
local indices = proc.device.floats(proc.device.sortInto(work, keys, live, n, 16))
orderKeys(values: any, descending: boolean?) → any
Float values as the u32 words `sortInto` orders by, so that ordering the words orders the values: least first, or greatest first when `descending`. Sorted over all 32 bits.
| arg | type | description |
|---|---|---|
| values | any | An f32 Column of one float per element. |
| descending | boolean? | Greatest first. |
examples
local order = proc.device.sortInto(work, proc.device.orderKeys(age), live, n, 32)
bitsBelow(n: number) → number
How many bits a key below `n` takes.
| arg | type | description |
|---|---|---|
| n | number |
segmentSteps(values: any, lanes: number, segments: any, count: any, capacity: number, key: string) → any
log2(n) steps of the segment kernel, ping-ponging between two runs.
| arg | type | description |
|---|---|---|
| values | any | |
| lanes | number | |
| segments | any | |
| count | any | |
| capacity | number | |
| key | string |
segmentScan(values: any, lanes: number, segments: any, count: any, capacity: number, op: string?) → any
The running fold of a run within segments, on the device: each live element holds the sum, least or greatest of every element of its segment up to and including itself. A segment is a run of neighbouring elements carrying the same `segments` value — the run sorted by group, or one value everywhere for a scan of the whole run. Elements past `count` keep their own value and take no part.
| arg | type | description |
|---|---|---|
| values | any | A GPU Column of `lanes` floats per element. |
| lanes | number | Floats per element, 1 to 4. |
| segments | any | An f32 Column: the segment each element is in. |
| count | any | A device count of the live elements, or a number. |
| capacity | number | How many elements the runs hold. |
| op | string? | "sum" (default), "min" or "max". |
examples
local runningTotal = proc.device.segmentScan(cost, 1, groupOf, live, n, "sum")
segmentSpread(values: any, lanes: number, segments: any, count: any, capacity: number) → any
Every live element given the value the last live element of its segment holds, on the device — what turns a running fold into each segment's total, standing on every one of its elements.
| arg | type | description |
|---|---|---|
| values | any | A GPU Column of `lanes` floats per element. |
| lanes | number | Floats per element, 1 to 4. |
| segments | any | An f32 Column: the segment each element is in. |
| count | any | A device count of the live elements, or a number. |
| capacity | number | How many elements the runs hold. |
examples
local groupTotal = proc.device.segmentSpread(runningTotal, 1, groupOf, live, n)
divideBy(values: any, lanes: number, by: any) → any
Each element of a run divided by its own divisor, every lane by the same one, on the device; a divisor of 0 gives 0. A running sum over a running count is a running mean.
| arg | type | description |
|---|---|---|
| values | any | A GPU Column of `lanes` floats per element. |
| lanes | number | Floats per element, 1 to 4. |
| by | any | An f32 Column: one divisor per element. |
examples
local mean = proc.device.divideBy(sums, 3, counts)
expand(offsets: any, total: any, capacity: number, from: any) →
A run laid out as segments end to end, expanded on the device: segment s holds its elements from `offsets[s]` up to the next segment's offset (the offsets `scan` makes of each segment's size), and each element is told the segment it belongs to and the element of a source it comes from — its segment's `from` plus its place within the segment. The inverse of a scan: what stamps a source at every point, one copy per segment. Elements at and past `total` belong to none and read -1. per segment. Segments past the live ones start at `total`. and its index in the source.
| arg | type | description |
|---|---|---|
| offsets | any | An f32 Column: where each segment starts, non-decreasing, one |
| total | any | A device count of the elements the segments hold in all. |
| capacity | number | How many elements the expanded run holds. |
| from | any | An f32 Column: where each segment's elements start in the source. |
examples
local owner, at = proc.device.expand(offsets, total, cap, from)
composeByOwnerKernel(mode: string) → any
| arg | type | description |
|---|---|---|
| mode | string |
composeByOwner(values: any, owner: any, total: any, own: any, mode: string) → any
Each element's orientation or scale composed with its owner's, on the device: "orient" turns a quaternion (x, y, z, w) by the owner's, so a copy keeps its own turn inside the owner's; "scale" multiplies a Vec3 scale by the owner's, axis by axis.
| arg | type | description |
|---|---|---|
| values | any | A GPU Column, one value per element: Vec4 for "orient", Vec3 for "scale". |
| owner | any | An f32 Column: each element's owner (what `expand` answers). |
| total | any | A device count of the live elements. |
| own | any | A GPU Column of the same type, one per owner. |
| mode | string | "orient" or "scale". |
examples
local turned = proc.device.composeByOwner(libOrient, owner, total, pts.orient, "orient")
rebase(values: any, owner: any, total: any, to: any, from: any) → any
Indices into another run moved with the elements they name, on the device: each element's index, taken from a source where its owner's elements started at `from[owner]`, now names the same element where they start at `to[owner]`. What keeps a copied corner on its own copy's points.
| arg | type | description |
|---|---|---|
| values | any | An f32 Column of indices, one per element. |
| owner | any | An f32 Column: each element's owner. |
| total | any | A device count of the live elements. |
| to | any | An f32 Column: where each owner's elements start now. |
| from | any | An f32 Column: where each owner's elements started in the source. |
examples
local pt = proc.device.rebase(libPt, owner, total, pointAt, pointFrom)
matches(values: any, value: number, count: any, capacity: number) → any
A flag on every live element of a run whose value is `value` (to the nearest whole number), on the device: 1 where it is, 0 elsewhere and past `count`. What `compact` takes to gather the elements of one kind — the points of one source, the members of one group.
| arg | type | description |
|---|---|---|
| values | any | An f32 Column of one value per element. |
| value | number | The value an element is flagged for holding. |
| count | any | A device count of the live elements, or a number. |
| capacity | number | How many elements the flags cover. |
examples
local ofRocks = proc.device.matches(pts.Mesh, 1, live, cap)
composeMatrices(dst: any, P: any, orient: any, scale: any, count: any, indices: any?) → any
One column-major 4x4 matrix per row, on the device: row r scaled by its element's `scale`, turned by its `orient` (a quaternion x, y, z, w) and moved to its `P` — the layout an instanced draw's transform buffer holds. With `indices`, row r is composed from the element `indices[r]` names; without, from element r. Rows at and past `count` hold zeros, which draw nothing.
| arg | type | description |
|---|---|---|
| dst | any | An f32 GPU Column of 16 floats per row. |
| P | any | A GPU Vec3 Column. |
| orient | any | A GPU Vec4 Column. |
| scale | any | A GPU Vec3 Column. |
| count | any | A device count of the rows to compose, or a number. |
| indices | any? | An f32 Column naming each row's element, or nil. |
examples
proc.device.composeMatrices(xf, pts.P, pts.orient, pts.scale, live)
Sub-parts
Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.
Showing up to 3 levels deep. Open a part to see what it holds further down.
Problems
Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.
agent_score is exposed.+ quality × 0.35
+ performance × 0.25
± compat factor
Usability ratings
Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".
Scoped to this part · feeds back into the world's score.