Builtin Library
README.md
compute_observe
What the compute subsystem is holding on the GPU, and why a resource key names
nothing. Backs compute.observe, compute.resources, compute.diagnose and
compute.absentReasons, composing the one reading only the engine can take
(__computeObserve.inventory()) into the calls content reaches for.
The inventory
local r = compute.observe()
print(r.totals.count, r.totals.bytes)
for _, res in ipairs(r.resources) do
print(res.key, res.kind, res.bytes, res.owner.shader)
end
One row per live resource across both registries compute owns — the buffer map
and the texture manager's volumes, storage targets, history pairs and samplers.
Each row carries the key it is filed under verbatim (the same string a dispatch
names it by and a dispatch failure prints), its kind, its bytes, its extent
and format where it has them, the usage bits it was created with, and the
frame it was created on.
owner is read back out of the key: a resource a .computeShader ref made is
filed under <shader-guid>::<name>#<serial>, so owner.shader names the
shader, owner.name what the caller called it and owner.serial which of that
caller's resources under that name it is. A resource created under a bare name
carries the whole key as owner.name.
The engine files its own resources under the same grammar: a compiled shader's
params uniform is <shader-guid>::__params, so it names that shader as its
owner and compute.resources(ref) accounts for it beside the buffers and
volumes the shader made.
totals.bytes is what the rows sum to, and it is the compute figure
renderer.gpuMemory() reports: both are read off the same registries, so a
listing reconciles against the memory call by construction.
published is false when no renderer has published a reading yet — the engine
saying it cannot answer, which reads differently from an engine answering with
nothing held.
The same document is served at /zero/runtime/compute, and the resources and
totals halves are readable on their own there.
Narrowing to one shader
for _, r in ipairs(compute.resources(shaderRef)) do print(r.key, r.bytes) end
Takes a .computeShader ref, a guid, or an asset identity. A guid stands for
itself, so a resource stays reachable by its owner once the asset that made it
is gone — which is the state a leak is in. A value carrying no shader raises —
a blank string among them — so a narrowing that cannot be done reads as an
error rather than as the whole inventory or as an owner that holds nothing.
Why a key names nothing
local d = compute.diagnose("705c73a8-...::f_target#6")
if not d.exists then print(d.reason, d.current) end
reason comes from the closed set compute.absentReasons() enumerates, and
each entry is a state the inventory distinguishes on its own:
| reason | what the inventory read |
|---|---|
resident | a resource is filed under exactly this key; the row is on resource |
notPublished | no renderer has published an inventory, so no key can be answered for |
replaced | the owner holds a resource under the same name at a different serial — current names it |
nameUnused | the owner holds resources, none under this name |
ownerAbsent | no live resource carries this key's owner |
unowned | the key carries no owner segment, and nothing is filed under it |
A reason is the inventory at the moment the call read it. The inventory is republished on a frame where a registry gained or lost an entry, so a resource created and diagnosed inside one script sees the reading from before it was made; wait a frame and ask again.