> Development branch documentation · commit 327c05c78d2f528e4f4a679fcc7a77d9aa161f48
> Package versions: @zenfg/webgpu 0.1.0, @zenfg/snapshot 0.1.0, @zenfg/inspector 0.1.0, zenfg 0.1.0, zenfg-snapshot 0.1.0
> Source: https://github.com/uinosoft/zenfg/blob/327c05c78d2f528e4f4a679fcc7a77d9aa161f48/packages/webgpu/examples/compute-output.ts

# webgpu: compute-output

This is the complete, compile-checked package recipe. The caller owns the device and application state.

```ts
/**
 * Source: Original ZenFG package recipe.
 * Demonstrates: A compute result retained by an explicit output root.
 * Flow: Create storage, record compute writes, mark the output and execute.
 * The caller owns the device and native inputs; ZenFG owns graph execution.
 * Read next: README.md for inputs and related recipes. The Examples adapter
 * and recipeHost.ts provide browser setup and snapshot capture.
 */
import { BufferAccess, FrameGraph, type FrameGraphRecording } from '@zenfg/webgpu';

export type ComputeOutputRecordOptions = {
	readonly recorder: FrameGraphRecording;
	readonly pipeline: GPUComputePipeline;
	readonly outputBuffer: GPUBuffer;
	readonly outputSize: number;
	readonly workgroupCount: number;
};

export type ComputeOutputOptions = Omit<ComputeOutputRecordOptions, 'recorder'> & {
	readonly graph: FrameGraph;
	readonly frameIndex: number;
};

/**
 * Declares a compute dispatch that fully overwrites the exposed output range.
 * The supplied shader must write every byte in that range.
 */
export function recordComputeOutput(options: ComputeOutputRecordOptions): void {
	const output = options.recorder.importBuffer(options.outputBuffer, {
		label: 'compute-output',
		exposedSize: options.outputSize,
		initialContents: 'undefined',
	});
	const outputWrite = options.recorder.use(output, BufferAccess.StorageWrite, {
		range: { offset: 0, size: options.outputSize },
		contents: 'overwrite',
	});

	options.recorder.compute({
		label: 'write-output',
		uses: [outputWrite],
		encode({ device, pass, unwrap }) {
			const bindGroup = device.createBindGroup({
				layout: options.pipeline.getBindGroupLayout(0),
				entries: [{ binding: 0, resource: { buffer: unwrap(outputWrite) } }],
			});
			pass.setPipeline(options.pipeline);
			pass.setBindGroup(0, bindGroup);
			pass.dispatchWorkgroups(options.workgroupCount);
		},
	});

	options.recorder.markOutput(output);
}

/** Records and executes one compute dispatch into a caller-owned output buffer. */
export function computeOutput(options: ComputeOutputOptions): void {
	const recorder = options.graph.beginFrame();
	recordComputeOutput({
		recorder,
		pipeline: options.pipeline,
		outputBuffer: options.outputBuffer,
		outputSize: options.outputSize,
		workgroupCount: options.workgroupCount,
	});
	recorder.compile().execute({ frameIndex: options.frameIndex });
}

```
