Inspecting a graph-owned custom node¶
Custom-node diagnostics inspect the actual instance owned by a prepared
SignalGraph. Type enumeration, saved state and worker completions do not
establish which GPU output an audio callback selected.
Register a CustomNodeDiagnosticsDescriptor after its exact custom type/version.
This companion leaves the positional CustomNodeType aggregate unchanged.
Replacing a custom type withdraws its diagnostic companion; register the matching
inspector again. Prepared-topology edits carry, remove and publish companions
alongside their type registrations.
For example, after registering and preparing the GPU realization:
auto identity = graph.custom_node_diagnostic_handle(node_id);
pulp::host::space::convolution::GpuConvolutionDiagnostics report;
auto result = graph.query_custom_node_diagnostics(
identity.handle, pulp::host::space::convolution::kGpuDiagnosticSchema,
report, pulp::host::CustomNodeDiagnosticConsistency::LiveApproximate);
if (result.availability == pulp::host::CustomNodeDiagnosticAvailability::Available) {
// report.report.lanes[0].delivery.gpu_blocks is selected output, not completion.
}
Retry Busy later on the control thread. After reprepare, obtain a new handle;
never automatically relabel a stale result as belonging to the new generation.
To reconcile delivery totals, first stop and join the sole process caller, then
query with AudioCallerStopped before release. This ordering is the caller's
responsibility, not an operation performed by the query.
On a control thread, obtain custom_node_diagnostic_handle(node_id), then call
query_custom_node_diagnostics(handle, schema, report). The report must be an
owned trivially-copyable value of the schema's exact size, at most 4096 bytes.
The callback receives bytes and copies with memcpy, so caller buffer alignment
does not leak into provider casts. Reports contain no borrowed instance pointers,
strings or callback closures. Treat the result availability as authoritative;
non-available reads clear in-bound output buffers. Oversized buffers are rejected
without traversing caller memory.
Busy means lifecycle mutation holds the graph lock or a swap edit is open.
StaleHandle means graph identity/generation changed or the authored node does
not match the live instance. Prepare, release and topology changes invalidate
old handles. MissingNode, Unsupported, NotPrepared and SchemaMismatch
remain distinct from an available report with zero GPU deliveries.
The query tries the existing graph mutation lock, retaining its debug ownership
checks. It copies Slot::live()'s control-thread shared owner under that lock;
it never acquires an RCU reader pin while holding the mutation lock. This matches
existing prepared-topology ownership and cannot invert release's reader drain.
Prepare, replacement, removal and release cannot change the inspected instance
until the callback returns. Graph destruction must still be serialized by its
caller, as with every other graph method. No diagnostic work is added to the
audio callback. Generic type-key lookup may allocate on this control-thread
path; the query is not RT-safe. A user-supplied inspector must not allocate, wait, reenter graph
methods or mutate lifecycle; a try-lock is not a wall-time guarantee for arbitrary
provider code.
Live reports are approximate independent atomic loads. AudioCallerStopped
records the caller's explicit promise that the sole audio process caller is
stopped. It does not stop processing itself, stop workers, certify physical
retirement or prove unique terminal outcomes per block. Read stopped delivery
totals before release resets the state; prove drain separately. Worker stats may
still advance even with the audio caller stopped.
Forge GPU convolution¶
space::convolution::gpu_convolution_diagnostics() supplies the companion for
space.convolution_reverb_gpu version 1. Its fixed schema
kGpuDiagnosticSchema returns GpuConvolutionDiagnostics, including the actual
engine's preparation, authenticated provider capability, block size, latency and
two independent lanes of transport stats and selected-delivery counters.
Preparation generation is returned in the query envelope. Counts represent
internal transport quanta, not arbitrary host callback partitions. Generic worker
output is never relabeled as GPU output.
A live parameter wrapper must register its diagnostic companion under its exact
wrapped type/version and unwrap only its privately owned instance before invoking
the original inspector. Preserve the original producer identity in the companion's
producer_type_id/producer_type_version; the envelope separately preserves the
registered alias. Never cast a wrapper instance directly to GpuInstance.
CPU-only/default types have no GPU inspector and report Unsupported. The C++
seam does not yet add a unified-controls operation. That follow-on should expose
the same closed statuses and fixed typed payload after installed product proof.
Focused fake tests and source compilation do not establish actual plugin GPU
delivery, numerical correctness, physical teardown or a performance improvement.