> 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/transient-to-present.ts

# webgpu: transient-to-present

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

```ts
/**
 * Source: Original ZenFG package recipe.
 * Demonstrates: Graph-owned transient textures and derived resource usage.
 * Flow: Record offscreen rendering and presentation, then compile and execute the frame.
 * 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 { FrameGraph, TextureAccess, type FrameGraphRecording } from '@zenfg/webgpu';

export type TransientToPresentRecordOptions = {
	readonly recorder: FrameGraphRecording;
	readonly backbufferTexture: GPUTexture;
	readonly scenePipeline: GPURenderPipeline;
	readonly presentPipeline: GPURenderPipeline;
	readonly sampler: GPUSampler;
	readonly width: number;
	readonly height: number;
};

export type TransientToPresentOptions = {
	readonly graph: FrameGraph;
	readonly context: GPUCanvasContext;
	readonly scenePipeline: GPURenderPipeline;
	readonly presentPipeline: GPURenderPipeline;
	readonly sampler: GPUSampler;
	readonly width: number;
	readonly height: number;
	readonly frameIndex: number;
};

/** Declares transient rendering followed by presentation without compiling it. */
export function recordTransientToPresent(options: TransientToPresentRecordOptions): void {
	const sceneColor = options.recorder.createTexture({
		label: 'scene-color',
		format: 'rgba16float',
		size: [options.width, options.height],
	});
	const backbuffer = options.recorder.importSwapchainTexture(
		options.backbufferTexture,
		{ label: 'backbuffer' },
	);

	options.recorder.render({
		label: 'scene',
		colorAttachments: [{
			target: sceneColor,
			loadOp: 'clear',
			storeOp: 'store',
			clearValue: { r: 0, g: 0, b: 0, a: 1 },
		}],
		encode({ pass }) {
			pass.setPipeline(options.scenePipeline);
			pass.draw(3);
		},
	});

	const sampledSceneColor = options.recorder.use(sceneColor, TextureAccess.Sampled);
	options.recorder.render({
		label: 'present',
		uses: [sampledSceneColor],
		colorAttachments: [{
			target: backbuffer,
			loadOp: 'clear',
			storeOp: 'store',
			clearValue: { r: 0, g: 0, b: 0, a: 1 },
		}],
		encode({ device, pass, unwrap }) {
			const bindGroup = device.createBindGroup({
				layout: options.presentPipeline.getBindGroupLayout(0),
				entries: [
					{ binding: 0, resource: options.sampler },
					{ binding: 1, resource: unwrap(sampledSceneColor) },
				],
			});
			pass.setPipeline(options.presentPipeline);
			pass.setBindGroup(0, bindGroup);
			pass.draw(3);
		},
	});

	options.recorder.markPresent(backbuffer);
}

/** Renders into a transient texture and samples it into the current surface. */
export function renderTransientToPresent(options: TransientToPresentOptions): void {
	const recorder = options.graph.beginFrame();
	recordTransientToPresent({
		recorder,
		backbufferTexture: options.context.getCurrentTexture(),
		scenePipeline: options.scenePipeline,
		presentPipeline: options.presentPipeline,
		sampler: options.sampler,
		width: options.width,
		height: options.height,
	});
	recorder.compile().execute({ frameIndex: options.frameIndex });
}

```
