Builtin Library
README.md
compute Module
Public Luau surface over the __compute Internal FFI namespace — GPU
compute pipelines.
Purpose
A compute shader is a .computeShader asset, and everything you do with one you
do through a resolved reference to it. This module carries what is left: the
readback poll, and the name-keyed entry points kept working for content written
before the reference surface existed.
Usage
local double = asset.resolve("@builtin::shaders.compute_double", "computeShader")
local scratch = double:createBuffer("scratch", { size = 4096, readback = true })
scratch:write({ 1.0, 2.0, 3.0, 4.0 })
double:dispatch({ buffers = { scratch }, workgroups = { 1 } })
local key = scratch:read()
while not compute.isReadbackReady(key) do task.wait(0) end
local floats = compute.getReadbackResult(key)
asset.resolve records your script's dependency on the shader — which is what
carries the shader along when the world is packed, pulled or published. A name
passed to one of the entry points below records nothing, and the shader is left
behind.
Is it compiled yet?
compute.programState(ref) says where a shader's compiled program stands:
"absent" (nothing held under this key and nothing in flight), "pending"
(a registration or compile was asked for and has not reached the device — a
recompile of a resident program reads pending too), "ready" (compiled and
resident, so a dispatch binds it), or "failed", with the reason as a second
return.
if compute.programState(shaderRef) == "ready" then
shaderRef:dispatch({ buffers = { buf }, workgroups = { 1 } })
end
ref:compile() queues the compile and the pipeline is built on the render side
frames later, so that call cannot answer this. A dispatch issued before the
program is ready is held behind the compile and dropped if it never lands, and
a readback taken then reports the buffer as it was.
Is anything broken?
compute.failing() lists every (shader, target) pair whose most recent
dispatch failed, with the reason. An empty result means every dispatch the
engine has been given is running. For one shader, ref:status() reports each of
its targets, running or not.
for _, d in ipairs(compute.failing()) do
print(d.shader, d.target, d.failures, d.lastError)
end
A dispatch is recorded into a command encoder frames after the call that asked
for it returned, so the call answers that it queued the dispatch and these two
answer what the dispatch did. A zero in any workgroups dimension is one of the
things they report: it is refused, and a count computed from how much data there
is passes through math.max(1, ...) so an empty set dispatches one workgroup
rather than none.
Exports
- Health:
programState,failing. - Readback:
isReadbackReady,readbackState,getReadbackResult,getReadbackResultU32,getReadbackResultBytes. A handle answers a read itself —buf:read(offset, len)gives aReadbackwithready,stateand the three drains on it. - Deprecated, name-keyed:
registerShader,destroyShader,registerShaderEx,destroyShaderEx,compile,compileByName,dispatch,dispatchOnVertices,dispatchEx,setParam. Each has a method on the.computeShaderreference — seetypes/computeShader. - Deprecated, name-keyed buffers:
createBuffer(name, { size, readback? }),destroyBuffer,readBuffer,writeBuffer(name, data, offset?),writeBufferU32,writeBufferBytes. Each reaches the substrate under the name a dispatch binds it by; hold the handle fromsubstrate.createBufferorref:createBufferinstead.