Skip to content

@typegpu/kittargets · memo

Render targets

Textures that share a size, replaced together when the size changes.

kit.targets

module

Creates render targets that follow a size.

targets.create(root, source, specs, { resolution? }?) → Targets

targets.scaled(source, scale) → SizeSource

rootborrows
the root
sourcetakes
the size it follows, such as a surface
specstakes
a format and options per target, by name
resolution?takes
the fraction of each side drawn, which changes without allocating
Targetsreturns
a set of targets you fit every frame and destroy
sourcetakes
the size it scales, such as a surface
scaletakes
a factor, or a function that returns it
SizeSourcereturns
a size that targets and cameras can follow
types
SpecSizeSourceSurfaceFixedSizeDepthTextureTargets
Optionscreate · 1 field
resolution?

number | (() => number)= 1

Sets the fraction of each side to draw, capped at 1 and read at each fit().

records

fit() before the passes that use the targets; it returns true after a rebuild.

owns

a texture per target

Replaced as a set when the size changes.

allocates

on resize

The whole set, new textures and their views; a new resolution allocates nothing.

lifecycle

destroy()[Symbol.dispose]

Drag the canvas corner or change pixel ratio or resolution. A memo lookup each frame replaces the bind group after rebuilding, while a group created once retains the destroyed texture.

A renderer may need multisampled colour, depth, HDR colour and bloom textures that follow the canvas size. A WebGPU texture can’t be resized, so a new size means new textures, views and bind groups. targets.create makes a set of textures that share a size, and fit() replaces the whole set when the size changes.

import {
function memo<const A extends Args, R>(fn: (...args: A) => R): (...args: A) => R

Caches the last two results of fn, comparing arguments by identity. Calls fn only when neither cached argument list matches. For example, create a bind group with const group = memo((hdr) => root.createBindGroup(layout, { hdr })), then call group(screen.textures.hdr) each frame. Alternating between two textures, such as a history pair, calls fn only twice. Does not destroy cached results.

@param ― fn a function of up to four arguments

@returns ― fn, remembering its last two results

memo
} from '@typegpu/kit';
const
const screen: targets.Targets<{
readonly scene: {
readonly format: "rgba16float";
readonly samples: 4;
};
readonly depth: {
readonly format: "depth24plus";
readonly samples: 4;
};
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly bloom: {
readonly format: "rgba16float";
readonly scale: number;
readonly mips: 5;
readonly sampled: true;
};
readonly blur: {
readonly format: "rgba16float";
readonly scale: number;
readonly sampled: true;
};
}>
screen
=
import targets
targets
.
function create<{
readonly scene: {
readonly format: "rgba16float";
readonly samples: 4;
};
readonly depth: {
readonly format: "depth24plus";
readonly samples: 4;
};
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly bloom: {
readonly format: "rgba16float";
readonly scale: number;
readonly mips: 5;
readonly sampled: true;
};
readonly blur: {
readonly format: "rgba16float";
readonly scale: number;
readonly sampled: true;
};
}>(root: TgpuRoot, source: targets.SizeSource, specs: {
readonly scene: {
readonly format: "rgba16float";
readonly samples: 4;
};
readonly depth: {
readonly format: "depth24plus";
readonly samples: 4;
};
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly bloom: {
readonly format: "rgba16float";
readonly scale: number;
readonly mips: 5;
readonly sampled: true;
};
readonly blur: {
readonly format: "rgba16float";
readonly scale: number;
readonly sampled: true;
};
}, options?: targets.Options): targets.Targets<...>

Creates render targets that follow a size. Replaces the whole set when the size changes. Put targets needed only sometimes in their own set and create that set when needed. Throws for transient targets with sampling, storage or mip levels, for multisampled targets with storage or mip levels, and for layered targets that are multisampled, mipped or have more layers than the device allows.

@param ― source the size it follows, such as a surface

@param ― specs a format and options per target, by name

@param ― options.resolution the fraction of each side drawn, which changes without allocating

@returns ― a set of targets you fit every frame and destroy

create
(
const root: TgpuRoot
root
,
const surface: web.Surface
surface
, {
scene: {
readonly format: "rgba16float";
readonly samples: 4;
}
scene
: {
format: "rgba16float"
format
: 'rgba16float',
samples: 4
samples
: 4 }, // transient
depth: {
readonly format: "depth24plus";
readonly samples: 4;
}
depth
: {
format: "depth24plus"
format
: 'depth24plus',
samples: 4
samples
: 4 }, // transient
hdr: {
readonly format: "rgba16float";
readonly sampled: true;
}
hdr
: {
format: "rgba16float"
format
: 'rgba16float',
sampled: true
sampled
: true },
bloom: {
readonly format: "rgba16float";
readonly scale: number;
readonly mips: 5;
readonly sampled: true;
}
bloom
: {
format: "rgba16float"
format
: 'rgba16float',
scale: number
scale
: 1 / 2,
mips: 5
mips
: 5,
sampled: true
sampled
: true },
blur: {
readonly format: "rgba16float";
readonly scale: number;
readonly sampled: true;
}
blur
: {
format: "rgba16float"
format
: 'rgba16float',
scale: number
scale
: 1 / 4,
sampled: true
sampled
: true },
});
// Runs again only when `hdr` is a new texture
const
const hdrGroup: (hdr: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>) => TgpuBindGroup<{
hdr: {
texture: d.WgslTexture2d<d.F32>;
};
}>
hdrGroup
=
memo<readonly [hdr: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>], TgpuBindGroup<{
hdr: {
texture: d.WgslTexture2d<d.F32>;
};
}>>(fn: (hdr: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>) => TgpuBindGroup<{
hdr: {
texture: d.WgslTexture2d<d.F32>;
};
}>): (hdr: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>) => TgpuBindGroup<{
hdr: {
texture: d.WgslTexture2d<d.F32>;
};
}>

Caches the last two results of fn, comparing arguments by identity. Calls fn only when neither cached argument list matches. For example, create a bind group with const group = memo((hdr) => root.createBindGroup(layout, { hdr })), then call group(screen.textures.hdr) each frame. Alternating between two textures, such as a history pair, calls fn only twice. Does not destroy cached results.

@param ― fn a function of up to four arguments

@returns ― fn, remembering its last two results

memo
((
hdr: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>
hdr
: typeof
const screen: targets.Targets<{
readonly scene: {
readonly format: "rgba16float";
readonly samples: 4;
};
readonly depth: {
readonly format: "depth24plus";
readonly samples: 4;
};
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly bloom: {
readonly format: "rgba16float";
readonly scale: number;
readonly mips: 5;
readonly sampled: true;
};
readonly blur: {
readonly format: "rgba16float";
readonly scale: number;
readonly sampled: true;
};
}>
screen
.
Targets<{ readonly scene: { readonly format: "rgba16float"; readonly samples: 4; }; readonly depth: { readonly format: "depth24plus"; readonly samples: 4; }; readonly hdr: { readonly format: "rgba16float"; readonly sampled: true; }; readonly bloom: { ...; }; readonly blur: { ...; }; }>.textures: {
readonly scene: targets.Texture<{
readonly format: "rgba16float";
readonly samples: 4;
}>;
readonly depth: targets.Texture<{
readonly format: "depth24plus";
readonly samples: 4;
}>;
readonly hdr: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>;
readonly bloom: targets.Texture<{
readonly format: "rgba16float";
readonly scale: number;
readonly mips: 5;
readonly sampled: true;
}>;
readonly blur: targets.Texture<{
readonly format: "rgba16float";
readonly scale: number;
readonly sampled: true;
}>;
}

Provides the current textures. A size change replaces them. Throws after destroy.

textures
.
hdr: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>
hdr
) =>
const root: TgpuRoot
root
.
TgpuRoot.createBindGroup<{
hdr: {
texture: d.WgslTexture2d<d.F32>;
};
}>(layout: TgpuBindGroupLayout<{
hdr: {
texture: d.WgslTexture2d<d.F32>;
};
}>, entries: ExtractBindGroupInputFromLayout<{
hdr: {
texture: d.WgslTexture2d<d.F32>;
};
}>): TgpuBindGroup<{
hdr: {
texture: d.WgslTexture2d<d.F32>;
};
}>

Creates a group of resources that can be bound to a shader based on a specified layout.

@remarks ― Typed wrapper around a GPUBindGroup.

@example

const fooLayout = tgpu.bindGroupLayout({ foo: { uniform: d.vec3f }, bar: { texture: d.texture2d(d.f32) }, });

const fooBuffer = ...; const barTexture = ...;

const fooBindGroup = root.createBindGroup(fooLayout, { foo: fooBuffer, bar: barTexture, });

@param ― layout Layout describing the bind group to be created.

@param ― entries A record with values being the resources populating the bind group and keys being their associated names, matching the layout keys.

createBindGroup
(
const layout: TgpuBindGroupLayout<{
hdr: {
texture: d.WgslTexture2d<d.F32>;
};
}>
layout
, {
hdr: GPUTextureView | GPUTexture | (SampledFlag & TgpuTexture<{
size: readonly number[];
format: GPUTextureFormat;
dimension?: "2d" | undefined;
sampleCount?: 1 | undefined;
}>) | TgpuTextureView<d.WgslTexture<WgslTextureProps>>
hdr
}));
import frames
frames
.
function create(root: TgpuRoot, record: Recorder): frames.Frames

Records a frame into one encoder and submits once, with a clock. Borrows the root. The synchronous recorder borrows each frame's encoder.

@submits ― always once a frame after your recorder returns, and again at each frame.submit()

@param ― record your frame, recorded into each frame's encoder

@returns ― a loop you run with each frame's time and destroy

create
(
const root: TgpuRoot
root
, (
frame: frames.Frame
frame
) => {
const screen: targets.Targets<{
readonly scene: {
readonly format: "rgba16float";
readonly samples: 4;
};
readonly depth: {
readonly format: "depth24plus";
readonly samples: 4;
};
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly bloom: {
readonly format: "rgba16float";
readonly scale: number;
readonly mips: 5;
readonly sampled: true;
};
readonly blur: {
readonly format: "rgba16float";
readonly scale: number;
readonly sampled: true;
};
}>
screen
.
Targets<{ readonly scene: { readonly format: "rgba16float"; readonly samples: 4; }; readonly depth: { readonly format: "depth24plus"; readonly samples: 4; }; readonly hdr: { readonly format: "rgba16float"; readonly sampled: true; }; readonly bloom: { ...; }; readonly blur: { ...; }; }>.fit(): boolean

Rebuilds all textures if the source size changed, destroying the old textures. Updates regions for the current resolution. Returns true after a rebuild so callers can update bind groups that hold old textures. Call before recording passes that use the targets. Throws after destroy.

fit
(); // new textures if the canvas changed size
const
const scene: TgpuRenderPass
scene
=
frame: frames.Frame
frame
.
Frame.encoder: TgpuCommandEncoder

Records commands for submission after the recorder returns. submit() replaces this encoder. Read it at each call instead of keeping it, and let the frame submit it.

encoder
.
TgpuCommandEncoder.beginRenderPass(descriptor: TgpuRenderPassDescriptor): TgpuRenderPass

Begins recording a render pass. Attachment views accept TypeGPU textures, texture views and canvas contexts, next to raw

GPUTextureView

s.

beginRenderPass
({
TgpuRenderPassDescriptor.colorAttachments?: ColorAttachment | readonly (ColorAttachment | null)[] | undefined
colorAttachments
: {
ColorAttachment.view: GPUTextureView | TgpuTextureRenderView | (ColorTextureConstraint & RenderFlag) | TgpuTextureView<d.WgslTexture<WgslTextureProps>> | GPUCanvasContext

A

GPUTextureView

describing the texture subresource that will be output to for this color attachment.

view
:
const screen: targets.Targets<{
readonly scene: {
readonly format: "rgba16float";
readonly samples: 4;
};
readonly depth: {
readonly format: "depth24plus";
readonly samples: 4;
};
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly bloom: {
readonly format: "rgba16float";
readonly scale: number;
readonly mips: 5;
readonly sampled: true;
};
readonly blur: {
readonly format: "rgba16float";
readonly scale: number;
readonly sampled: true;
};
}>
screen
.
Targets<{ readonly scene: { readonly format: "rgba16float"; readonly samples: 4; }; readonly depth: { readonly format: "depth24plus"; readonly samples: 4; }; readonly hdr: { readonly format: "rgba16float"; readonly sampled: true; }; readonly bloom: { ...; }; readonly blur: { ...; }; }>.views: {
readonly scene: GPUTextureView;
readonly depth: GPUTextureView;
readonly hdr: GPUTextureView;
readonly bloom: GPUTextureView;
readonly blur: GPUTextureView;
}

Provides attachment views of mip 0, created once per rebuild. Throws after destroy.

views
.
scene: GPUTextureView
scene
,
ColorAttachment.resolveTarget?: GPUTextureView | TgpuTextureRenderView | (ColorTextureConstraint & RenderFlag) | TgpuTextureView<d.WgslTexture<WgslTextureProps>> | GPUCanvasContext | undefined

A

GPUTextureView

describing the texture subresource that will receive the resolved output for this color attachment if

GPURenderPassColorAttachment#view

is multisampled.

resolveTarget
:
const screen: targets.Targets<{
readonly scene: {
readonly format: "rgba16float";
readonly samples: 4;
};
readonly depth: {
readonly format: "depth24plus";
readonly samples: 4;
};
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly bloom: {
readonly format: "rgba16float";
readonly scale: number;
readonly mips: 5;
readonly sampled: true;
};
readonly blur: {
readonly format: "rgba16float";
readonly scale: number;
readonly sampled: true;
};
}>
screen
.
Targets<{ readonly scene: { readonly format: "rgba16float"; readonly samples: 4; }; readonly depth: { readonly format: "depth24plus"; readonly samples: 4; }; readonly hdr: { readonly format: "rgba16float"; readonly sampled: true; }; readonly bloom: { ...; }; readonly blur: { ...; }; }>.views: {
readonly scene: GPUTextureView;
readonly depth: GPUTextureView;
readonly hdr: GPUTextureView;
readonly bloom: GPUTextureView;
readonly blur: GPUTextureView;
}

Provides attachment views of mip 0, created once per rebuild. Throws after destroy.

views
.
hdr: GPUTextureView
hdr
,
ColorAttachment.storeOp?: GPUStoreOp | undefined

The store operation to perform on

GPURenderPassColorAttachment#view

after executing the render pass.

@default ― 'store'

storeOp
: 'discard',
},
TgpuRenderPassDescriptor.depthStencilAttachment?: DepthStencilAttachment | undefined
depthStencilAttachment
: {
DepthStencilAttachment.view: GPUTextureView | TgpuTextureRenderView | (DepthStencilTextureConstraint & RenderFlag) | TgpuTextureView<d.WgslTextureDepth2d | d.WgslTextureDepthMultisampled2d>

The texture subresource that will be output to and read from for this depth/stencil attachment.

view
:
const screen: targets.Targets<{
readonly scene: {
readonly format: "rgba16float";
readonly samples: 4;
};
readonly depth: {
readonly format: "depth24plus";
readonly samples: 4;
};
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly bloom: {
readonly format: "rgba16float";
readonly scale: number;
readonly mips: 5;
readonly sampled: true;
};
readonly blur: {
readonly format: "rgba16float";
readonly scale: number;
readonly sampled: true;
};
}>
screen
.
Targets<{ readonly scene: { readonly format: "rgba16float"; readonly samples: 4; }; readonly depth: { readonly format: "depth24plus"; readonly samples: 4; }; readonly hdr: { readonly format: "rgba16float"; readonly sampled: true; }; readonly bloom: { ...; }; readonly blur: { ...; }; }>.views: {
readonly scene: GPUTextureView;
readonly depth: GPUTextureView;
readonly hdr: GPUTextureView;
readonly bloom: GPUTextureView;
readonly blur: GPUTextureView;
}

Provides attachment views of mip 0, created once per rebuild. Throws after destroy.

views
.
depth: GPUTextureView
depth
,
DepthStencilAttachment.depthStoreOp?: GPUStoreOp | undefined

The store operation to perform on

GPURenderPassDepthStencilAttachment#view

's depth component after executing the render pass.

depthStoreOp
: 'discard' },
});
// draw the scene
const scene: TgpuRenderPass
scene
.
TgpuRenderPass.end(): void

Completes the recording of this render pass

end
();
const
const final: TgpuRenderPass
final
=
frame: frames.Frame
frame
.
Frame.encoder: TgpuCommandEncoder

Records commands for submission after the recorder returns. submit() replaces this encoder. Read it at each call instead of keeping it, and let the frame submit it.

encoder
.
TgpuCommandEncoder.beginRenderPass(descriptor: TgpuRenderPassDescriptor): TgpuRenderPass

Begins recording a render pass. Attachment views accept TypeGPU textures, texture views and canvas contexts, next to raw

GPUTextureView

s.

beginRenderPass
({
TgpuRenderPassDescriptor.colorAttachments?: ColorAttachment | readonly (ColorAttachment | null)[] | undefined
colorAttachments
: {
ColorAttachment.view: GPUTextureView | TgpuTextureRenderView | (ColorTextureConstraint & RenderFlag) | TgpuTextureView<d.WgslTexture<WgslTextureProps>> | GPUCanvasContext

A

GPUTextureView

describing the texture subresource that will be output to for this color attachment.

view
:
const surface: web.Surface
surface
.
Surface.view(frame: frames.Frame): GPUTextureView

Returns a view of the current canvas texture, created once per texture. Applies pending size changes first, which a pass using context would skip.

view
(
frame: frames.Frame
frame
) } });
const final: TgpuRenderPass
final
.
TgpuRenderCommands.setPipeline(pipeline: TgpuRenderPipeline): void

Sets the current

TgpuRenderPipeline

for subsequent draw calls

setPipeline
(
const tone: TgpuRenderPipeline<never>
tone
);
const final: TgpuRenderPass
final
.
TgpuRenderCommands.setBindGroup(bindGroup: TgpuBindGroup): void (+1 overload)

Associates a bind group with the layout it was created from

setBindGroup
(
const hdrGroup: (hdr: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>) => TgpuBindGroup<{
hdr: {
texture: d.WgslTexture2d<d.F32>;
};
}>
hdrGroup
(
const screen: targets.Targets<{
readonly scene: {
readonly format: "rgba16float";
readonly samples: 4;
};
readonly depth: {
readonly format: "depth24plus";
readonly samples: 4;
};
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly bloom: {
readonly format: "rgba16float";
readonly scale: number;
readonly mips: 5;
readonly sampled: true;
};
readonly blur: {
readonly format: "rgba16float";
readonly scale: number;
readonly sampled: true;
};
}>
screen
.
Targets<{ readonly scene: { readonly format: "rgba16float"; readonly samples: 4; }; readonly depth: { readonly format: "depth24plus"; readonly samples: 4; }; readonly hdr: { readonly format: "rgba16float"; readonly sampled: true; }; readonly bloom: { ...; }; readonly blur: { ...; }; }>.textures: {
readonly scene: targets.Texture<{
readonly format: "rgba16float";
readonly samples: 4;
}>;
readonly depth: targets.Texture<{
readonly format: "depth24plus";
readonly samples: 4;
}>;
readonly hdr: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>;
readonly bloom: targets.Texture<{
readonly format: "rgba16float";
readonly scale: number;
readonly mips: 5;
readonly sampled: true;
}>;
readonly blur: targets.Texture<{
readonly format: "rgba16float";
readonly scale: number;
readonly sampled: true;
}>;
}

Provides the current textures. A size change replaces them. Throws after destroy.

textures
.
hdr: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>
hdr
));
const final: TgpuRenderPass
final
.
TgpuRenderCommands.draw(vertexCount: number, instanceCount?: number, firstVertex?: number, firstInstance?: number): void
draw
(3);
const final: TgpuRenderPass
final
.
TgpuRenderPass.end(): void

Completes the recording of this render pass

end
();
});

Each key names a target in textures, views, levels and layers.

Field Default Meaning
format Texture format.
scale 1 Fraction of the set’s size; each side is rounded up and at least 1.
samples 1 MSAA sample count. A multisampled target can’t be mipped or stored.
mips 1 Mip levels, at most as many as the size has. levels.name[i] views level i.
sampled false Also bindable as a sampled texture.
storage false Also bindable as a storage texture, in a format TypeGPU binds as one, such as rgba16float.
transient true when multisampled and not sampled Cleared and discarded in each pass: memoryless where the browser has GPUTextureUsage.TRANSIENT_ATTACHMENT, a plain attachment elsewhere.
layers none Layers of a 2D array texture, one sample and one mip each. layers.name[k] views layer k. Passes draw a pass into each.
  • A 16 × 9 target has five mip levels, so levels.bloom can be shorter than the mips asked for. Loop over levels.
  • create throws before making any texture for a transient target that is sampled, stored or mipped, for a multisampled target with mips or storage, and for a target with layers that is multisampled or mipped or has more layers than the device’s maxTextureArrayLayers. It checks the mips you asked for, not the clamped count. The types already refuse storage on a format with no storage binding, such as depth24plus.
  • A target only sometimes needed, like a depth-of-field buffer, goes in a set of its own, created when the feature turns on. There is no enabled flag.
  • targets.Depth types the depth that TAA, depth of field and ambient occlusion read: single-sampled and sampled, in depth16unorm, depth24plus or depth32float.
  • Take a pipeline’s format from screen.textures.name.props.format, and its sampleCount from the same props. Literals break only at the first draw after the spec changes.

A transient target is cleared, discarded and never read after its pass, such as MSAA colour or depth. Where memoryless attachments are available on tile-based GPUs, it uses tile memory during the pass without video-memory storage. Elsewhere, discarding the target still avoids storing its samples. Transience is a texture usage and needs no device feature request. screen.memoryless reports support.

  • Multisampled targets are transient by default unless sampled or stored. Other targets require transient: true. screen.transient.scene reports whether scene is transient.
  • A pass into a transient target clears it and uses storeOp: 'discard', so only what it resolves outlives the pass.
  • begin throws when a pass would keep one, as a second pass that draws over the first does. Give that target transient: false:
const
const screen: targets.Targets<{
readonly scene: {
readonly format: "rgba16float";
readonly samples: 4;
readonly transient: false;
};
readonly depth: {
readonly format: "depth24plus";
readonly samples: 4;
readonly transient: false;
};
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
}>
screen
=
import targets
targets
.
function create<{
readonly scene: {
readonly format: "rgba16float";
readonly samples: 4;
readonly transient: false;
};
readonly depth: {
readonly format: "depth24plus";
readonly samples: 4;
readonly transient: false;
};
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
}>(root: TgpuRoot, source: targets.SizeSource, specs: {
readonly scene: {
readonly format: "rgba16float";
readonly samples: 4;
readonly transient: false;
};
readonly depth: {
readonly format: "depth24plus";
readonly samples: 4;
readonly transient: false;
};
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
}, options?: targets.Options): targets.Targets<...>

Creates render targets that follow a size. Replaces the whole set when the size changes. Put targets needed only sometimes in their own set and create that set when needed. Throws for transient targets with sampling, storage or mip levels, for multisampled targets with storage or mip levels, and for layered targets that are multisampled, mipped or have more layers than the device allows.

@param ― source the size it follows, such as a surface

@param ― specs a format and options per target, by name

@param ― options.resolution the fraction of each side drawn, which changes without allocating

@returns ― a set of targets you fit every frame and destroy

create
(
const root: TgpuRoot
root
,
const surface: web.Surface
surface
, {
scene: {
readonly format: "rgba16float";
readonly samples: 4;
readonly transient: false;
}
scene
: {
format: "rgba16float"
format
: 'rgba16float',
samples: 4
samples
: 4,
transient: false
transient
: false }, // kept for the glows' pass
depth: {
readonly format: "depth24plus";
readonly samples: 4;
readonly transient: false;
}
depth
: {
format: "depth24plus"
format
: 'depth24plus',
samples: 4
samples
: 4,
transient: false
transient
: false },
hdr: {
readonly format: "rgba16float";
readonly sampled: true;
}
hdr
: {
format: "rgba16float"
format
: 'rgba16float',
sampled: true
sampled
: true },
});

fit() compares the source’s size with the set’s. When it changed, it destroys every texture, creates new ones and returns true.

  • Call it before recording passes that use the targets. A pass recorded with a destroyed texture fails at submit.
  • Sizes round up to whole pixels, at least 1 and at most the device’s maxTextureDimension2D.
  • create fits once, so the textures exist before the first frame.
  • The source can be any SizeSource, such as a canvas surface, plain object or fixed-height getter. fit() reads it each time. A plain object of fixed size makes a texture of your own to draw into.
  • destroy(), or [Symbol.dispose] with using, destroys the textures. fit(), textures, views and levels then throw The target set was destroyed.

kit.memo

cpu

Caches the last two results of fn, comparing arguments by identity.

memo(fn)

kind
cpu

A cached bind group still refers to the texture it was created with after that texture is destroyed. memo(fn) reruns fn when an argument’s identity changes. Call it each frame with the current texture to create a group only when the texture changes. It also works with textures replaced by other modules.

  • Up to four arguments, so a call allocates nothing.
  • It keeps its last two results, so arguments that alternate between two textures run fn only twice per rebuild.
  • It destroys nothing; keep it for bind groups and the like.
  • levels.name is a new array per rebuild, so it works as an argument, as bloom keys its per-level groups and passes on chain.levels.glow.

A temporal effect, such as a cloud history, writes one target of a pair while it reads the other, and swaps each frame. One memo holds both groups:

const
const screen: targets.Targets<{
readonly a: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly b: {
readonly format: "rgba16float";
readonly sampled: true;
};
}>
screen
=
import targets
targets
.
function create<{
readonly a: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly b: {
readonly format: "rgba16float";
readonly sampled: true;
};
}>(root: TgpuRoot, source: targets.SizeSource, specs: {
readonly a: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly b: {
readonly format: "rgba16float";
readonly sampled: true;
};
}, options?: targets.Options): targets.Targets<{
readonly a: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly b: {
readonly format: "rgba16float";
readonly sampled: true;
};
}>

Creates render targets that follow a size. Replaces the whole set when the size changes. Put targets needed only sometimes in their own set and create that set when needed. Throws for transient targets with sampling, storage or mip levels, for multisampled targets with storage or mip levels, and for layered targets that are multisampled, mipped or have more layers than the device allows.

@param ― source the size it follows, such as a surface

@param ― specs a format and options per target, by name

@param ― options.resolution the fraction of each side drawn, which changes without allocating

@returns ― a set of targets you fit every frame and destroy

create
(
const root: TgpuRoot
root
,
const surface: web.Surface
surface
, {
a: {
readonly format: "rgba16float";
readonly sampled: true;
}
a
: {
format: "rgba16float"
format
: 'rgba16float',
sampled: true
sampled
: true },
b: {
readonly format: "rgba16float";
readonly sampled: true;
}
b
: {
format: "rgba16float"
format
: 'rgba16float',
sampled: true
sampled
: true },
});
const
const historyOf: (history: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>) => TgpuBindGroup<{
history: {
texture: d.WgslTexture2d<d.F32>;
};
}>
historyOf
=
memo<readonly [history: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>], TgpuBindGroup<{
history: {
texture: d.WgslTexture2d<d.F32>;
};
}>>(fn: (history: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>) => TgpuBindGroup<{
history: {
texture: d.WgslTexture2d<d.F32>;
};
}>): (history: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>) => TgpuBindGroup<{
history: {
texture: d.WgslTexture2d<d.F32>;
};
}>

Caches the last two results of fn, comparing arguments by identity. Calls fn only when neither cached argument list matches. For example, create a bind group with const group = memo((hdr) => root.createBindGroup(layout, { hdr })), then call group(screen.textures.hdr) each frame. Alternating between two textures, such as a history pair, calls fn only twice. Does not destroy cached results.

@param ― fn a function of up to four arguments

@returns ― fn, remembering its last two results

memo
((
history: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>
history
: typeof
const screen: targets.Targets<{
readonly a: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly b: {
readonly format: "rgba16float";
readonly sampled: true;
};
}>
screen
.
Targets<{ readonly a: { readonly format: "rgba16float"; readonly sampled: true; }; readonly b: { readonly format: "rgba16float"; readonly sampled: true; }; }>.textures: {
readonly a: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>;
readonly b: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>;
}

Provides the current textures. A size change replaces them. Throws after destroy.

textures
.
a: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>
a
) =>
const root: TgpuRoot
root
.
TgpuRoot.createBindGroup<{
history: {
texture: d.WgslTexture2d<d.F32>;
};
}>(layout: TgpuBindGroupLayout<{
history: {
texture: d.WgslTexture2d<d.F32>;
};
}>, entries: ExtractBindGroupInputFromLayout<{
history: {
texture: d.WgslTexture2d<d.F32>;
};
}>): TgpuBindGroup<{
history: {
texture: d.WgslTexture2d<d.F32>;
};
}>

Creates a group of resources that can be bound to a shader based on a specified layout.

@remarks ― Typed wrapper around a GPUBindGroup.

@example

const fooLayout = tgpu.bindGroupLayout({ foo: { uniform: d.vec3f }, bar: { texture: d.texture2d(d.f32) }, });

const fooBuffer = ...; const barTexture = ...;

const fooBindGroup = root.createBindGroup(fooLayout, { foo: fooBuffer, bar: barTexture, });

@param ― layout Layout describing the bind group to be created.

@param ― entries A record with values being the resources populating the bind group and keys being their associated names, matching the layout keys.

createBindGroup
(
const History: TgpuBindGroupLayout<{
history: {
texture: d.WgslTexture2d<d.F32>;
};
}>
History
, {
history: GPUTextureView | GPUTexture | (SampledFlag & TgpuTexture<{
size: readonly number[];
format: GPUTextureFormat;
dimension?: "2d" | undefined;
sampleCount?: 1 | undefined;
}>) | TgpuTextureView<d.WgslTexture<WgslTextureProps>>
history
}),
);
import frames
frames
.
function create(root: TgpuRoot, record: Recorder): frames.Frames

Records a frame into one encoder and submits once, with a clock. Borrows the root. The synchronous recorder borrows each frame's encoder.

@submits ― always once a frame after your recorder returns, and again at each frame.submit()

@param ― record your frame, recorded into each frame's encoder

@returns ― a loop you run with each frame's time and destroy

create
(
const root: TgpuRoot
root
, (
frame: frames.Frame
frame
) => {
const screen: targets.Targets<{
readonly a: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly b: {
readonly format: "rgba16float";
readonly sampled: true;
};
}>
screen
.
Targets<{ readonly a: { readonly format: "rgba16float"; readonly sampled: true; }; readonly b: { readonly format: "rgba16float"; readonly sampled: true; }; }>.fit(): boolean

Rebuilds all textures if the source size changed, destroying the old textures. Updates regions for the current resolution. Returns true after a rebuild so callers can update bind groups that hold old textures. Call before recording passes that use the targets. Throws after destroy.

fit
();
// Even frames write a and read b, odd frames the other way
const
const even: boolean
even
=
frame: frames.Frame
frame
.
Frame.index: number

Counts frames submitted before this one.

index
% 2 === 0;
const
const pass: TgpuRenderPass
pass
=
frame: frames.Frame
frame
.
Frame.encoder: TgpuCommandEncoder

Records commands for submission after the recorder returns. submit() replaces this encoder. Read it at each call instead of keeping it, and let the frame submit it.

encoder
.
TgpuCommandEncoder.beginRenderPass(descriptor: TgpuRenderPassDescriptor): TgpuRenderPass

Begins recording a render pass. Attachment views accept TypeGPU textures, texture views and canvas contexts, next to raw

GPUTextureView

s.

beginRenderPass
({
TgpuRenderPassDescriptor.colorAttachments?: ColorAttachment | readonly (ColorAttachment | null)[] | undefined
colorAttachments
: {
ColorAttachment.view: GPUTextureView | TgpuTextureRenderView | (ColorTextureConstraint & RenderFlag) | TgpuTextureView<d.WgslTexture<WgslTextureProps>> | GPUCanvasContext

A

GPUTextureView

describing the texture subresource that will be output to for this color attachment.

view
:
const even: boolean
even
?
const screen: targets.Targets<{
readonly a: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly b: {
readonly format: "rgba16float";
readonly sampled: true;
};
}>
screen
.
Targets<{ readonly a: { readonly format: "rgba16float"; readonly sampled: true; }; readonly b: { readonly format: "rgba16float"; readonly sampled: true; }; }>.views: {
readonly a: GPUTextureView;
readonly b: GPUTextureView;
}

Provides attachment views of mip 0, created once per rebuild. Throws after destroy.

views
.
a: GPUTextureView
a
:
const screen: targets.Targets<{
readonly a: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly b: {
readonly format: "rgba16float";
readonly sampled: true;
};
}>
screen
.
Targets<{ readonly a: { readonly format: "rgba16float"; readonly sampled: true; }; readonly b: { readonly format: "rgba16float"; readonly sampled: true; }; }>.views: {
readonly a: GPUTextureView;
readonly b: GPUTextureView;
}

Provides attachment views of mip 0, created once per rebuild. Throws after destroy.

views
.
b: GPUTextureView
b
},
});
const pass: TgpuRenderPass
pass
.
TgpuRenderCommands.setPipeline(pipeline: TgpuRenderPipeline): void

Sets the current

TgpuRenderPipeline

for subsequent draw calls

setPipeline
(
const resolve: TgpuRenderPipeline<never>
resolve
);
const pass: TgpuRenderPass
pass
.
TgpuRenderCommands.setBindGroup(bindGroup: TgpuBindGroup): void (+1 overload)

Associates a bind group with the layout it was created from

setBindGroup
(
const historyOf: (history: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>) => TgpuBindGroup<{
history: {
texture: d.WgslTexture2d<d.F32>;
};
}>
historyOf
(
const even: boolean
even
?
const screen: targets.Targets<{
readonly a: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly b: {
readonly format: "rgba16float";
readonly sampled: true;
};
}>
screen
.
Targets<{ readonly a: { readonly format: "rgba16float"; readonly sampled: true; }; readonly b: { readonly format: "rgba16float"; readonly sampled: true; }; }>.textures: {
readonly a: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>;
readonly b: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>;
}

Provides the current textures. A size change replaces them. Throws after destroy.

textures
.
b: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>
b
:
const screen: targets.Targets<{
readonly a: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly b: {
readonly format: "rgba16float";
readonly sampled: true;
};
}>
screen
.
Targets<{ readonly a: { readonly format: "rgba16float"; readonly sampled: true; }; readonly b: { readonly format: "rgba16float"; readonly sampled: true; }; }>.textures: {
readonly a: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>;
readonly b: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>;
}

Provides the current textures. A size change replaces them. Throws after destroy.

textures
.
a: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>
a
));
const pass: TgpuRenderPass
pass
.
TgpuRenderCommands.draw(vertexCount: number, instanceCount?: number, firstVertex?: number, firstInstance?: number): void
draw
(3);
const pass: TgpuRenderPass
pass
.
TgpuRenderPass.end(): void

Completes the recording of this render pass

end
();
});

After a rebuild both sides are new and zeroed, so the effect starts over from an empty history.

The resolution option sets the fraction of each side to draw, read on every fit(). Textures keep their full source size, so changing resolution during play allocates nothing. Passes use a viewport to draw within each target’s region. Bloom and finish read only that region:

import {
import bloom
bloom
,
import finish
finish
} from '@typegpu/kit';
const
const screen: targets.Targets<{
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly depth: {
readonly format: "depth24plus";
};
}>
screen
=
import targets
targets
.
function create<{
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly depth: {
readonly format: "depth24plus";
};
}>(root: TgpuRoot, source: targets.SizeSource, specs: {
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly depth: {
readonly format: "depth24plus";
};
}, options?: targets.Options): targets.Targets<{
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly depth: {
readonly format: "depth24plus";
};
}>

Creates render targets that follow a size. Replaces the whole set when the size changes. Put targets needed only sometimes in their own set and create that set when needed. Throws for transient targets with sampling, storage or mip levels, for multisampled targets with storage or mip levels, and for layered targets that are multisampled, mipped or have more layers than the device allows.

@param ― source the size it follows, such as a surface

@param ― specs a format and options per target, by name

@param ― options.resolution the fraction of each side drawn, which changes without allocating

@returns ― a set of targets you fit every frame and destroy

create
(
const root: TgpuRoot
root
,
const surface: web.Surface
surface
,
{
hdr: {
readonly format: "rgba16float";
readonly sampled: true;
}
hdr
: {
format: "rgba16float"
format
: 'rgba16float',
sampled: true
sampled
: true },
depth: {
readonly format: "depth24plus";
}
depth
: {
format: "depth24plus"
format
: 'depth24plus' },
},
{
Options.resolution?: number | (() => number) | undefined

Sets the fraction of each side to draw, capped at 1 and read at each fit(). Textures keep the source size, so changing resolution allocates nothing. Passes use viewports for the drawn regions, and sampling reads only those regions. Default 1.

resolution
: () =>
const settings: {
resolution: number;
}
settings
.
resolution: number
resolution
},
);
const
const source: () => targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>
source
= () =>
const screen: targets.Targets<{
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly depth: {
readonly format: "depth24plus";
};
}>
screen
.
Targets<{ readonly hdr: { readonly format: "rgba16float"; readonly sampled: true; }; readonly depth: { readonly format: "depth24plus"; }; }>.textures: {
readonly hdr: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>;
readonly depth: targets.Texture<{
readonly format: "depth24plus";
}>;
}

Provides the current textures. A size change replaces them. Throws after destroy.

textures
.
hdr: targets.Texture<{
readonly format: "rgba16float";
readonly sampled: true;
}>
hdr
;
const
const region: targets.SizeSource
region
=
const screen: targets.Targets<{
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly depth: {
readonly format: "depth24plus";
};
}>
screen
.
Targets<{ readonly hdr: { readonly format: "rgba16float"; readonly sampled: true; }; readonly depth: { readonly format: "depth24plus"; }; }>.regions: {
readonly hdr: targets.SizeSource;
readonly depth: targets.SizeSource;
}

Reports each drawn region from the top-left corner of its target. Multiplies target size by resolution and rounds up. fit() updates the same objects for the lifetime of the set.

regions
.
hdr: targets.SizeSource
hdr
;
const
const glow: bloom.Bloom
glow
=
import bloom
bloom
.
function create(root: TgpuRoot, options: bloom.Options): bloom.Bloom

Creates bloom from a chain of half-size textures. Each level downsamples with 13 taps, then a tent filter adds it to the next larger level. The result is mip 0 of output, at half the source size. With region, passes draw and sample only that region; changing the region allocates nothing.

@allocates ― on resize: a new chain and the bind groups of its passes; so does a new source

@owns ― targets, a sampler, 3 pipelines, 2 bind groups and a buffer per level: the chain of glow levels, the settings, a group for each pass, and the region each pass reads

@records ― record after whatever wrote the source; then output holds the glow.

@param ― options.source the HDR picture, read at every record

@param ― options.region the part of the source that holds the picture, read at every record

@returns ― a bloom you record every frame and destroy

create
(
const root: TgpuRoot
root
, {
Options.source: finish.Rendered | (() => finish.FloatTexture)

Provides the HDR picture: a rendered picture, such as aa, or a function returning a texture, such as () => screen.textures.hdr. record reads it on every call, so the texture can be rebuilt.

source
,
Options.region?: targets.SizeSource | undefined

Selects the source region from its top-left corner, such as regions.hdr when drawing below full resolution. record reads it on every call. Default the region of a rendered source, else the whole texture.

region
});
const
const final: finish.Finish
final
=
import finish
finish
.
function create(root: TgpuRoot, options: finish.Options): finish.Finish

Creates the final pass of a frame. It reads the source, adds glow, tone maps, grades, applies the vignette, encodes and dithers. It draws one triangle into the caller pass.

@allocates ― on resize: a bind group for a new source or glow

@owns ― 2 buffers, a sampler, a pipeline, 2 bind groups: the settings, the regions it reads, and a group each for the source and the glow

@records ― record into a pass of its own on the view you give, usually the canvas's, or draw into the caller's pass, after the bloom's record.

@param ― options.source the picture, rendered or a texture, read at every draw

@param ― options.region the part of the source that holds the picture, read at every draw

@param ― options.glow a bloom, or a glow of your own, added before tone mapping

@param ― options.exposure an adapted exposure, read on the GPU

@returns ― a final pass you draw every frame and destroy

create
(
const root: TgpuRoot
root
, {
Options.format: GPUTextureFormat

Sets the output format, such as the canvas format.

format
:
const surface: web.Surface
surface
.
Surface.format: GPUTextureFormat
format
,
Options.source: finish.Rendered | (() => finish.FloatTexture)

Provides the picture at any size: a rendered picture, such as aa or blur, or a function returning a texture, such as () => screen.textures.hdr. draw reads it on every call, so the texture can be rebuilt.

source
,
Options.region?: targets.SizeSource | undefined

Selects the source region from its top-left corner, such as regions.hdr when drawing below full resolution. draw reads it on every call. Default the region of a rendered source, else the whole texture.

region
,
Options.glow?: finish.Rendered | undefined

Adds a bloom, or a glow of your own such as an emission target, before tone mapping. draw reads its output and region on every call. Default none.

glow
});
import frames
frames
.
function create(root: TgpuRoot, record: Recorder): frames.Frames

Records a frame into one encoder and submits once, with a clock. Borrows the root. The synchronous recorder borrows each frame's encoder.

@submits ― always once a frame after your recorder returns, and again at each frame.submit()

@param ― record your frame, recorded into each frame's encoder

@returns ― a loop you run with each frame's time and destroy

create
(
const root: TgpuRoot
root
, (
frame: frames.Frame
frame
) => {
const screen: targets.Targets<{
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly depth: {
readonly format: "depth24plus";
};
}>
screen
.
Targets<{ readonly hdr: { readonly format: "rgba16float"; readonly sampled: true; }; readonly depth: { readonly format: "depth24plus"; }; }>.fit(): boolean

Rebuilds all textures if the source size changed, destroying the old textures. Updates regions for the current resolution. Returns true after a rebuild so callers can update bind groups that hold old textures. Call before recording passes that use the targets. Throws after destroy.

fit
(); // takes the resolution into the regions
const
const scene: TgpuRenderPass
scene
=
frame: frames.Frame
frame
.
Frame.encoder: TgpuCommandEncoder

Records commands for submission after the recorder returns. submit() replaces this encoder. Read it at each call instead of keeping it, and let the frame submit it.

encoder
.
TgpuCommandEncoder.beginRenderPass(descriptor: TgpuRenderPassDescriptor): TgpuRenderPass

Begins recording a render pass. Attachment views accept TypeGPU textures, texture views and canvas contexts, next to raw

GPUTextureView

s.

beginRenderPass
({
TgpuRenderPassDescriptor.colorAttachments?: ColorAttachment | readonly (ColorAttachment | null)[] | undefined
colorAttachments
: {
ColorAttachment.view: TgpuTextureRenderView | (ColorTextureConstraint & RenderFlag) | GPUTextureView | TgpuTextureView<WgslTexture<WgslTextureProps>> | GPUCanvasContext

A

GPUTextureView

describing the texture subresource that will be output to for this color attachment.

view
:
const screen: targets.Targets<{
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly depth: {
readonly format: "depth24plus";
};
}>
screen
.
Targets<{ readonly hdr: { readonly format: "rgba16float"; readonly sampled: true; }; readonly depth: { readonly format: "depth24plus"; }; }>.views: {
readonly hdr: GPUTextureView;
readonly depth: GPUTextureView;
}

Provides attachment views of mip 0, created once per rebuild. Throws after destroy.

views
.
hdr: GPUTextureView
hdr
},
TgpuRenderPassDescriptor.depthStencilAttachment?: DepthStencilAttachment | undefined
depthStencilAttachment
: {
DepthStencilAttachment.view: TgpuTextureRenderView | GPUTextureView | (DepthStencilTextureConstraint & RenderFlag) | TgpuTextureView<WgslTextureDepth2d | WgslTextureDepthMultisampled2d>

The texture subresource that will be output to and read from for this depth/stencil attachment.

view
:
const screen: targets.Targets<{
readonly hdr: {
readonly format: "rgba16float";
readonly sampled: true;
};
readonly depth: {
readonly format: "depth24plus";
};
}>
screen
.
Targets<{ readonly hdr: { readonly format: "rgba16float"; readonly sampled: true; }; readonly depth: { readonly format: "depth24plus"; }; }>.views: {
readonly hdr: GPUTextureView;
readonly depth: GPUTextureView;
}

Provides attachment views of mip 0, created once per rebuild. Throws after destroy.

views
.
depth: GPUTextureView
depth
},
});
const scene: TgpuRenderPass
scene
.
TgpuRenderPass.setViewport(x: number, y: number, width: number, height: number, minDepth: number, maxDepth: number): void
setViewport
(0, 0,
const region: targets.SizeSource
region
.
SizeSource.width: number
width
,
const region: targets.SizeSource
region
.
SizeSource.height: number
height
, 0, 1);
// draw the scene
const scene: TgpuRenderPass
scene
.
TgpuRenderPass.end(): void

Completes the recording of this render pass

end
();
const glow: bloom.Bloom
glow
.
Bloom.record(target: frames.Frame | TgpuCommandEncoder, options?: Timed): void

Records bloom passes after the source is written. Optional timer writes measure the passes together.

record
(
frame: frames.Frame
frame
);
const final: finish.Finish
final
.
Finish.record(target: frames.Frame | TgpuCommandEncoder, view: GPUTextureView, options?: finish.RecordOptions): void

Opens a pass on view, such as surface.view(frame), draws into it and ends it. A viewport draws the picture into that rectangle and clears the rest, transparent with alpha: 'premultiplied' and black otherwise. Optional timer writes measure the pass.

record
(
frame: frames.Frame
frame
,
const surface: web.Surface
surface
.
Surface.view(frame: frames.Frame): GPUTextureView

Returns a view of the current canvas texture, created once per texture. Applies pending size changes first, which a pass using context would skip.

view
(
frame: frames.Frame
frame
));
});
  • regions.name describes the drawn region from the target’s top-left corner. Its dimensions are the target size multiplied by resolution, rounded up. The objects stay the same for the life of the set, and fit() updates them.
  • A clear clears the whole texture; the viewport limits only the drawing.
  • A shader of your own that samples a target reads uv * region / size, kept half a texel inside the region, as bloom and finish do.
  • The resolution is at most 1.
  • dynamicResolution picks the resolution that keeps the frame under a GPU budget.

For a resolution that stays put, targets.scaled(source, scale) is a smaller SizeSource that sets and cameras can share. Its textures take less memory, and a new scale makes new ones at the next fit(). Both of these scale the whole set; a spec’s scale is fixed per target.

views.name (mip 0) and levels.name (one per mip) are attachment views of one mip level each, made once per rebuild. Use these for attachments. TypeGPU’s default texture view covers every mip level, which an attachment can’t accept. textures.name is the TypeGPU texture, for bind groups and other views.

layers.name holds an attachment view of each layer, and of the one 2D texture for a target without layers. views.name is layer 0. To sample every layer, view the whole array:

import {
import d
d
} from 'typegpu';
import {
import targets
targets
} from '@typegpu/kit';
const
const size: {
width: number;
height: number;
pixelRatio: number;
}
size
= {
width: number
width
: 1024,
height: number
height
: 1024,
pixelRatio: number
pixelRatio
: 1 };
const
const maps: targets.Targets<{
readonly depth: {
readonly format: "depth16unorm";
readonly layers: 3;
readonly sampled: true;
};
}>
maps
=
import targets
targets
.
function create<{
readonly depth: {
readonly format: "depth16unorm";
readonly layers: 3;
readonly sampled: true;
};
}>(root: TgpuRoot, source: targets.SizeSource, specs: {
readonly depth: {
readonly format: "depth16unorm";
readonly layers: 3;
readonly sampled: true;
};
}, options?: targets.Options): targets.Targets<{
readonly depth: {
readonly format: "depth16unorm";
readonly layers: 3;
readonly sampled: true;
};
}>

Creates render targets that follow a size. Replaces the whole set when the size changes. Put targets needed only sometimes in their own set and create that set when needed. Throws for transient targets with sampling, storage or mip levels, for multisampled targets with storage or mip levels, and for layered targets that are multisampled, mipped or have more layers than the device allows.

@param ― source the size it follows, such as a surface

@param ― specs a format and options per target, by name

@param ― options.resolution the fraction of each side drawn, which changes without allocating

@returns ― a set of targets you fit every frame and destroy

create
(
const root: TgpuRoot
root
,
const size: {
width: number;
height: number;
pixelRatio: number;
}
size
, {
depth: {
readonly format: "depth16unorm";
readonly layers: 3;
readonly sampled: true;
}
depth
: {
format: "depth16unorm"
format
: 'depth16unorm',
layers: 3
layers
: 3,
sampled: true
sampled
: true },
});
const
const all: TgpuTextureView<d.WgslTextureDepth2dArray>
all
=
const maps: targets.Targets<{
readonly depth: {
readonly format: "depth16unorm";
readonly layers: 3;
readonly sampled: true;
};
}>
maps
.
Targets<{ readonly depth: { readonly format: "depth16unorm"; readonly layers: 3; readonly sampled: true; }; }>.textures: {
readonly depth: targets.Texture<{
readonly format: "depth16unorm";
readonly layers: 3;
readonly sampled: true;
}>;
}

Provides the current textures. A size change replaces them. Throws after destroy.

textures
.
depth: targets.Texture<{
readonly format: "depth16unorm";
readonly layers: 3;
readonly sampled: true;
}>
depth
.
TgpuTexture<{ size: [number, number, number]; format: "depth16unorm"; }>.createView<d.WgslTextureDepth2dArray>(schema: d.WgslTextureDepth2dArray, viewDescriptor?: (TgpuTextureViewDescriptor & {
sampleType?: "float" | "unfilterable-float" | undefined;
}) | undefined): TgpuTextureView<d.WgslTextureDepth2dArray> (+3 overloads)
createView
(
import d
d
.
function textureDepth2dArray(): d.WgslTextureDepth2dArray
export textureDepth2dArray
textureDepth2dArray
());
  • Nothing waits for the size to settle, so a drag-resize rebuilds the set in every frame the size changes. A rotation is one rebuild.
  • Two sets that follow the same source fit and rebuild separately.
  • A spec, such as samples, is fixed when the set is made; fit() replaces textures and keeps the specs. Another sample count is another set, and a new description of passes with new pipelines.
  • A set created when a feature turns on allocates its textures in that frame, mid-game.
  • On React Native, transient targets are plain attachments, and memoryless reports it. Budget memory for their multisampled colour and depth.
  • Set storeOp: 'discard' yourself when opening a pass into a transient target outside begin. Memoryless targets reject other store operations. Reading a discarded plain attachment in a later pass or copy produces no validation error.
  • Only single-mip attachment views are made. A sampled view of a range of mips is yours to make and keep, with memo if it follows the set.
  • With resolution, the textures take the full size’s memory at any resolution.
  • WebGPU has no view of a rectangle, so whatever samples a target crops in the shader. A shader of your own that samples with a full-texture uv reads past the region, where the texture holds an older frame or the clear colour.