Nodes and Handles
A node is the value returned by v.pass().
const A = v.pass(kernel, { input, output });Every buffer-like binding on a node gets a handle with the same name.
A.input;A.output;You can use handles when one pass consumes data from another pass, to make the dependency requirement clear:
const A = v.pass(doubleKernel, { input, output: mid });const B = v.pass(offsetKernel, { input: A.output, output: result });
v.run(B);Running B also runs A, because B depends on A.output.
This is Volten’s graph model: handles connect nodes into a dependency graph, and v.run(B) runs the work needed to produce B.
In-Place Chaining
Section titled “In-Place Chaining”Handles are created for in-place bindings too.
const A = v.pass(kernel, { data });const B = v.pass(kernel, { data: A.data });const C = v.pass(kernel, { data: B.data });
v.run(C);This lets you chain work in a way that improves the readability of the dependency chain, as well as letting you created more complex GPU compute execution dependency graphs
Declared Outputs
Section titled “Declared Outputs”Declared outputs matter when reading a node.
const kernel = new Kernel(`...`, { outputs: ['result']});
const node = v.pass(kernel, { input, result });const output = await v.read(node);If you choose to not declare outputs on your kernel, you can alternatively read a specific buffer or handle:
const data = await v.read(node.data);