Skip to content

Sign up to be notified when the ShaderHunt platform is available, along with interactive examples teaching TypeGPU from the ground up.

Textures

In a similar fashion to buffers, textures provide a way to store and manage data on the GPU. They allow for both read and write access from WGSL shaders, and can also be sampled in the case of sampled textures. The main advantage of using textures over buffers is their optimized memory layout for spatial data, which can lead to better performance in certain scenarios as well as additional functionality such as filtering and mipmapping.

TypeGPU textures serve as a wrapper that provides type safety and higher level utilities (such as automatic mipmap generation). They also allow - in a similar way to buffers - for fixed resource creation that can be used directly in shaders without the need for manual bind group management.

Let’s look at an example of creating and using a typed texture.

import
const tgpu: {
fn: {
<Args extends d.AnyData[] | []>(argTypes: Args, returnType?: undefined): TgpuFnShell<Args, d.Void>;
<Args extends d.AnyData[] | [], Return extends d.AnyData>(argTypes: Args, returnType: Return): TgpuFnShell<Args, Return>;
};
... 10 more ...;
'~unstable': {
...;
};
}
tgpu
from 'typegpu';
import * as
import d
d
from 'typegpu/data';
const
const root: TgpuRoot
root
= await
const tgpu: {
fn: {
<Args extends d.AnyData[] | []>(argTypes: Args, returnType?: undefined): TgpuFnShell<Args, d.Void>;
<Args extends d.AnyData[] | [], Return extends d.AnyData>(argTypes: Args, returnType: Return): TgpuFnShell<Args, Return>;
};
... 10 more ...;
'~unstable': {
...;
};
}
tgpu
.
init: (options?: InitOptions) => Promise<TgpuRoot>

Requests a new GPU device and creates a root around it. If a specific device should be used instead, use

@seeinitFromDevice. *

@example

When given no options, the function will ask the browser for a suitable GPU device.

const root = await tgpu.init();

@example

If there are specific options that should be used when requesting a device, you can pass those in.

const adapterOptions: GPURequestAdapterOptions = ...;
const deviceDescriptor: GPUDeviceDescriptor = ...;
const root = await tgpu.init({ adapter: adapterOptions, device: deviceDescriptor });

init
();
const
const texture: TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag
texture
=
const root: TgpuRoot
root
['~unstable'].
createTexture<number, number, number, [256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<...>
createTexture
({
size: [256, 256]

The width, height, and depth or layer count of the texture.

size
: [256, 256],
format: "rgba8unorm"

The format of the texture.

format
: 'rgba8unorm' as
type const = "rgba8unorm"
const
,
}).
TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.$usage<["sampled"]>(usages_0: "sampled"): TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag
$usage
('sampled');
const
const response: Response
response
= await
function fetch(input: string | URL | Request, init?: RequestInit): Promise<Response> (+1 overload)
fetch
('path/to/image.png');
const
const blob: Blob
blob
= await
const response: Response
response
.
Body.blob(): Promise<Blob>
blob
();
const
const image: ImageBitmap
image
= await
function createImageBitmap(image: ImageBitmapSource, options?: ImageBitmapOptions): Promise<ImageBitmap> (+1 overload)
createImageBitmap
(
const blob: Blob
blob
);
// Uploading image data to the texture (will be resampled if sizes differ)
const texture: TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag
texture
.
TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.write(source: ExternalImageSource | ExternalImageSource[]): void (+1 overload)
write
(
const image: ImageBitmap
image
);
// Creating a view to use in shader
const sampledView =
const texture: TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag
texture
.
TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.createView(): TgpuTextureView<d.WgslTexture2d<d.F32>> (+1 overload)
createView
();
const sampledView: TgpuTextureView<d.WgslTexture2d<d.F32>>

Textures can be created using the root['~unstable'].createTexture method. It accepts a descriptor similar to vanilla GPUTextureDescriptor. If specified, the properties will be reflected in the created texture type - this will later help with static checks when creating views or binding the texture in a layout.

type TextureProps = {
size: readonly number[];
format: GPUTextureFormat;
viewFormats?: GPUTextureFormat[] | undefined;
dimension?: GPUTextureDimension | undefined;
mipLevelCount?: number | undefined;
sampleCount?: number | undefined;
};
const texture =
const root: TgpuRoot
root
['~unstable'].
createTexture<number, number, number, [512, 512, 128], "rgba8unorm", 4, number, GPUTextureFormat[], "3d">(props: CreateTextureOptions<[512, 512, 128], "rgba8unorm", 4, number, GPUTextureFormat[], "3d">): TgpuTexture<...>
createTexture
({
const texture: TgpuTexture<{
size: [512, 512, 128];
format: "rgba8unorm";
dimension: "3d";
mipLevelCount: 4;
}>
size: [512, 512, 128]

The width, height, and depth or layer count of the texture.

size
: [512, 512, 128],
format: "rgba8unorm"

The format of the texture.

format
: 'rgba8unorm',
mipLevelCount?: 4 | undefined

The number of mip levels the texture will contain.

@default1

mipLevelCount
: 4,
dimension?: "3d" | undefined

Whether the texture is one-dimensional, an array of two-dimensional layers, or three-dimensional.

@default'2d'

dimension
: '3d',
})

Similar to buffers, textures need usage flags to specify how they will be used. You can add usage flags using the .$usage(...) method.

const
const texture: TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag & StorageFlag & RenderFlag
texture
=
const root: TgpuRoot
root
['~unstable'].
createTexture<number, number, number, [256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<...>
createTexture
({
size: [256, 256]

The width, height, and depth or layer count of the texture.

size
: [256, 256],
format: "rgba8unorm"

The format of the texture.

format
: 'rgba8unorm',
})
.
TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.$usage<["sampled"]>(usages_0: "sampled"): TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag
$usage
('sampled') // Can be sampled in shaders
.
TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.$usage<["storage"]>(usages_0: "storage"): TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag & StorageFlag
$usage
('storage') // Can be written or read to as storage texture
.
TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.$usage<["render"]>(usages_0: "render"): TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag & StorageFlag & RenderFlag
$usage
('render'); // Can be used as a render target

You can also add multiple flags at once:

const
const texture: TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag & RenderFlag & StorageFlag
texture
=
const root: TgpuRoot
root
['~unstable'].
createTexture<number, number, number, [256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<...>
createTexture
({
size: [256, 256]

The width, height, and depth or layer count of the texture.

size
: [256, 256],
format: "rgba8unorm"

The format of the texture.

format
: 'rgba8unorm',
}).
TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.$usage<["sampled", "storage", "render"]>(usages_0: "sampled", usages_1: "storage", usages_2: "render"): TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag & RenderFlag & StorageFlag
$usage
('sampled', 'storage', 'render');

The .write() method provides multiple overloads for different data sources:

// Image sources (single or array)
write(source: ExternalImageSource | ExternalImageSource[]): void
// Raw binary data with optional mip level
write(source: ArrayBuffer | TypedArray | DataView, mipLevel?: number): void

You can write various image sources to textures. ExternalImageSource includes:

  • HTMLCanvasElement
  • HTMLImageElement
  • HTMLVideoElement
  • ImageBitmap
  • ImageData
  • OffscreenCanvas
  • VideoFrame
const
const texture: TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag
texture
=
const root: TgpuRoot
root
['~unstable'].
createTexture<number, number, number, [256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<...>
createTexture
({
size: [256, 256]

The width, height, and depth or layer count of the texture.

size
: [256, 256],
format: "rgba8unorm"

The format of the texture.

format
: 'rgba8unorm',
}).
TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.$usage<["sampled"]>(usages_0: "sampled"): TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag
$usage
('sampled');
// From an ImageBitmap
const
const response: Response
response
= await
function fetch(input: string | URL | Request, init?: RequestInit): Promise<Response> (+1 overload)
fetch
('path/to/image.png');
const
const blob: Blob
blob
= await
const response: Response
response
.
Body.blob(): Promise<Blob>
blob
();
const
const imageBitmap: ImageBitmap
imageBitmap
= await
function createImageBitmap(image: ImageBitmapSource, options?: ImageBitmapOptions): Promise<ImageBitmap> (+1 overload)
createImageBitmap
(
const blob: Blob
blob
);
const texture: TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag
texture
.
TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.write(source: ExternalImageSource | ExternalImageSource[]): void (+1 overload)
write
(
const imageBitmap: ImageBitmap
imageBitmap
);
// From an HTMLCanvasElement
const
const canvas: HTMLCanvasElement
canvas
=
var document: Document
document
.
Document.createElement<"canvas">(tagName: "canvas", options?: ElementCreationOptions): HTMLCanvasElement (+2 overloads)

Creates an instance of the element for the specified tag.

@param

tagName The name of an element.

MDN Reference

createElement
('canvas');
const
const ctx: CanvasRenderingContext2D | null
ctx
=
const canvas: HTMLCanvasElement
canvas
.
HTMLCanvasElement.getContext(contextId: "2d", options?: CanvasRenderingContext2DSettings): CanvasRenderingContext2D | null (+5 overloads)

Returns an object that provides methods and properties for drawing and manipulating images and graphics on a canvas element in a document. A context object includes information about colors, line widths, fonts, and other graphic parameters that can be drawn on a canvas.

@param

contextId The identifier (ID) of the type of canvas to create. Internet Explorer 9 and Internet Explorer 10 support only a 2-D context using canvas.getContext("2d"); IE11 Preview also supports 3-D or WebGL context using canvas.getContext("experimental-webgl");

MDN Reference

getContext
('2d');
// ... draw on canvas
const texture: TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag
texture
.
TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.write(source: ExternalImageSource | ExternalImageSource[]): void (+1 overload)
write
(
const canvas: HTMLCanvasElement
canvas
);

For 3D textures or texture arrays, you can write multiple images:

const
const texture3d: TgpuTexture<{
size: [256, 256, 3];
format: "rgba8unorm";
dimension: "3d";
}> & SampledFlag
texture3d
=
const root: TgpuRoot
root
['~unstable'].
createTexture<number, number, number, [256, 256, 3], "rgba8unorm", number, number, GPUTextureFormat[], "3d">(props: CreateTextureOptions<[256, 256, 3], "rgba8unorm", number, number, GPUTextureFormat[], "3d">): TgpuTexture<...>
createTexture
({
size: [256, 256, 3]

The width, height, and depth or layer count of the texture.

size
: [256, 256, 3],
format: "rgba8unorm"

The format of the texture.

format
: 'rgba8unorm',
dimension?: "3d" | undefined

Whether the texture is one-dimensional, an array of two-dimensional layers, or three-dimensional.

@default'2d'

dimension
: '3d',
}).
TgpuTexture<{ size: [256, 256, 3]; format: "rgba8unorm"; dimension: "3d"; }>.$usage<["sampled"]>(usages_0: "sampled"): TgpuTexture<{
size: [256, 256, 3];
format: "rgba8unorm";
dimension: "3d";
}> & SampledFlag
$usage
('sampled');
// Write array of images for each layer
const texture3d: TgpuTexture<{
size: [256, 256, 3];
format: "rgba8unorm";
dimension: "3d";
}> & SampledFlag
texture3d
.
TgpuTexture<{ size: [256, 256, 3]; format: "rgba8unorm"; dimension: "3d"; }>.write(source: ExternalImageSource | ExternalImageSource[]): void (+1 overload)
write
([
const imageBitmap1: ImageBitmap
imageBitmap1
,
const imageBitmap2: ImageBitmap
imageBitmap2
,
const imageBitmap3: ImageBitmap
imageBitmap3
]);

You can write raw binary data directly to textures using ArrayBuffer, typed arrays, or DataView:

const
const texture: TgpuTexture<{
size: [2, 2];
format: "rgba8unorm";
}> & SampledFlag
texture
=
const root: TgpuRoot
root
['~unstable'].
createTexture<number, number, number, [2, 2], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[2, 2], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<...>
createTexture
({
size: [2, 2]

The width, height, and depth or layer count of the texture.

size
: [2, 2],
format: "rgba8unorm"

The format of the texture.

format
: 'rgba8unorm',
}).
TgpuTexture<{ size: [2, 2]; format: "rgba8unorm"; }>.$usage<["sampled"]>(usages_0: "sampled"): TgpuTexture<{
size: [2, 2];
format: "rgba8unorm";
}> & SampledFlag
$usage
('sampled');
// Using Uint8Array for RGBA data (4 pixels, 4 bytes each)
const
const data: Uint8Array<ArrayBuffer>
data
= new
var Uint8Array: Uint8ArrayConstructor
new (elements: Iterable<number>) => Uint8Array<ArrayBuffer> (+6 overloads)
Uint8Array
([
255, 0, 0, 255, // Red pixel
0, 255, 0, 255, // Green pixel
0, 0, 255, 255, // Blue pixel
255, 255, 0, 255, // Yellow pixel
]);
const texture: TgpuTexture<{
size: [2, 2];
format: "rgba8unorm";
}> & SampledFlag
texture
.
TgpuTexture<{ size: [2, 2]; format: "rgba8unorm"; }>.write(source: ArrayBuffer | TypedArray | DataView, mipLevel?: number): void (+1 overload)
write
(
const data: Uint8Array<ArrayBuffer>
data
);
// Write to a specific mip level
const
const mipData: Uint8Array<ArrayBuffer>
mipData
= new
var Uint8Array: Uint8ArrayConstructor
new (length: number) => Uint8Array<ArrayBuffer> (+6 overloads)
Uint8Array
(4 * 128 * 128); // Data for 128x128
const texture: TgpuTexture<{
size: [2, 2];
format: "rgba8unorm";
}> & SampledFlag
texture
.
TgpuTexture<{ size: [2, 2]; format: "rgba8unorm"; }>.write(source: ArrayBuffer | TypedArray | DataView, mipLevel?: number): void (+1 overload)
write
(
const mipData: Uint8Array<ArrayBuffer>
mipData
, 1); // Write to mip level 1

You can also copy from another texture:

const
const sourceTexture: TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag
sourceTexture
=
const root: TgpuRoot
root
['~unstable'].
createTexture<number, number, number, [256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<...>
createTexture
({
size: [256, 256]

The width, height, and depth or layer count of the texture.

size
: [256, 256],
format: "rgba8unorm"

The format of the texture.

format
: 'rgba8unorm',
}).
TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.$usage<["sampled"]>(usages_0: "sampled"): TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag
$usage
('sampled');
const
const targetTexture: TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag
targetTexture
=
const root: TgpuRoot
root
['~unstable'].
createTexture<number, number, number, [256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<...>
createTexture
({
size: [256, 256]

The width, height, and depth or layer count of the texture.

size
: [256, 256],
format: "rgba8unorm"

The format of the texture.

format
: 'rgba8unorm',
}).
TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.$usage<["sampled"]>(usages_0: "sampled"): TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag
$usage
('sampled');
const targetTexture: TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag
targetTexture
.
TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.copyFrom<TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag>(source: TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag): void
copyFrom
(
const sourceTexture: TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag
sourceTexture
);

TypeGPU provides automatic mipmap generation for textures:

const
const texture: TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
mipLevelCount: 9;
}> & SampledFlag & RenderFlag
texture
=
const root: TgpuRoot
root
['~unstable'].
createTexture<number, number, number, [256, 256], "rgba8unorm", 9, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[256, 256], "rgba8unorm", 9, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<...>
createTexture
({
size: [256, 256]

The width, height, and depth or layer count of the texture.

size
: [256, 256],
format: "rgba8unorm"

The format of the texture.

format
: 'rgba8unorm',
mipLevelCount?: 9 | undefined

The number of mip levels the texture will contain.

@default1

mipLevelCount
: 9, // log2(256) + 1
}).
TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; mipLevelCount: 9; }>.$usage<["sampled", "render"]>(usages_0: "sampled", usages_1: "render"): TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
mipLevelCount: 9;
}> & SampledFlag & RenderFlag
$usage
('sampled', 'render');
const texture: TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
mipLevelCount: 9;
}> & SampledFlag & RenderFlag
texture
.
TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; mipLevelCount: 9; }>.write(source: ExternalImageSource | ExternalImageSource[]): void (+1 overload)
write
(
const imageBitmap: ImageBitmap
imageBitmap
);
const texture: TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
mipLevelCount: 9;
}> & SampledFlag & RenderFlag
texture
.
TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; mipLevelCount: 9; }>.generateMipmaps(baseMipLevel?: number, mipLevels?: number): void
generateMipmaps
(); // Generate all mip levels automatically

To create a view - which will also serve as fixed texture usage - you can use one of the available texture schemas. You can pass it to the .createView method of the texture.

const
const texture: TgpuTexture<{
size: [512, 512];
format: "rgba8unorm";
}> & SampledFlag
texture
=
const root: TgpuRoot
root
['~unstable'].
createTexture<number, number, number, [512, 512], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[512, 512], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<...>
createTexture
({
size: [512, 512]

The width, height, and depth or layer count of the texture.

size
: [512, 512],
format: "rgba8unorm"

The format of the texture.

format
: 'rgba8unorm',
}).
TgpuTexture<{ size: [512, 512]; format: "rgba8unorm"; }>.$usage<["sampled"]>(usages_0: "sampled"): TgpuTexture<{
size: [512, 512];
format: "rgba8unorm";
}> & SampledFlag
$usage
('sampled');
const
const sampledView: TgpuTextureView<d.WgslTexture2d<d.F32>>
sampledView
=
const texture: TgpuTexture<{
size: [512, 512];
format: "rgba8unorm";
}> & SampledFlag
texture
.
TgpuTexture<{ size: [512, 512]; format: "rgba8unorm"; }>.createView<d.WgslTexture2d<d.F32>>(schema: d.WgslTexture2d<d.F32>, viewDescriptor?: (TgpuTextureViewDescriptor & {
sampleType?: "float" | "unfilterable-float";
}) | undefined): TgpuTextureView<...> (+1 overload)
createView
(
import d
d
.
texture2d<d.F32>(sampleType: d.F32): d.WgslTexture2d<d.F32> (+1 overload)
export texture2d
texture2d
(
import d
d
.
const f32: d.F32
export f32

A schema that represents a 32-bit float value. (equivalent to f32 in WGSL)

Can also be called to cast a value to an f32.

@example const value = f32(); // 0

@example const value = f32(1.23); // 1.23

@example const value = f32(true); // 1

f32
));
// in this case the same as:
// - texture.createView(d.texture2d()); (defaults to f32)
// - texture.createView(); (defaults to texture2d<f32>)

To sample textures in shaders, you’ll often need a sampler that defines how the texture should be filtered and addressed. The createSampler method accepts the same descriptor as the vanilla WebGPU GPUSamplerDescriptor:

const
const sampler: TgpuFixedSampler
sampler
=
const root: TgpuRoot
root
['~unstable'].
function createSampler(props: WgslSamplerProps): TgpuFixedSampler
createSampler
({
WgslSamplerProps.magFilter?: GPUFilterMode

Specifies the sampling behavior when the sample footprint is smaller than or equal to one texel.

magFilter
: 'linear',
WgslSamplerProps.minFilter?: GPUFilterMode

Specifies the sampling behavior when the sample footprint is larger than one texel.

minFilter
: 'linear',
WgslSamplerProps.mipmapFilter?: GPUMipmapFilterMode

Specifies behavior for sampling between mipmap levels.

mipmapFilter
: 'linear',
WgslSamplerProps.addressModeU?: GPUAddressMode
addressModeU
: 'repeat',
WgslSamplerProps.addressModeV?: GPUAddressMode
addressModeV
: 'repeat',
});

The returned sampler object can be used like a fixed resource directly in shaders, or bound in a bind group for manual binding.

Textures can be used in shaders through bind groups or as fixed resources, similar to buffers.

const
const texture: TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag
texture
=
const root: TgpuRoot
root
['~unstable'].
createTexture<number, number, number, [256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<...>
createTexture
({
size: [256, 256]

The width, height, and depth or layer count of the texture.

size
: [256, 256],
format: "rgba8unorm"

The format of the texture.

format
: 'rgba8unorm',
}).
TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.$usage<["sampled"]>(usages_0: "sampled"): TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag
$usage
('sampled');
const
const sampler: TgpuFixedSampler
sampler
=
const root: TgpuRoot
root
['~unstable'].
function createSampler(props: WgslSamplerProps): TgpuFixedSampler
createSampler
({
WgslSamplerProps.magFilter?: GPUFilterMode

Specifies the sampling behavior when the sample footprint is smaller than or equal to one texel.

magFilter
: 'linear',
WgslSamplerProps.minFilter?: GPUFilterMode

Specifies the sampling behavior when the sample footprint is larger than one texel.

minFilter
: 'linear',
});
const
const bindGroupLayout: TgpuBindGroupLayout<{
myTexture: {
texture: d.WgslTexture2d<d.F32>;
};
mySampler: {
sampler: "filtering";
};
}>
bindGroupLayout
=
const tgpu: {
fn: {
<Args extends d.AnyData[] | []>(argTypes: Args, returnType?: undefined): TgpuFnShell<Args, d.Void>;
<Args extends d.AnyData[] | [], Return extends d.AnyData>(argTypes: Args, returnType: Return): TgpuFnShell<Args, Return>;
};
... 10 more ...;
'~unstable': {
...;
};
}
tgpu
.
bindGroupLayout: <{
myTexture: {
texture: d.WgslTexture2d<d.F32>;
};
mySampler: {
sampler: "filtering";
};
}>(entries: {
myTexture: {
texture: d.WgslTexture2d<d.F32>;
};
mySampler: {
sampler: "filtering";
};
}) => TgpuBindGroupLayout<...> (+1 overload)
bindGroupLayout
({
myTexture: {
texture: d.WgslTexture2d<d.F32>;
}
myTexture
: {
texture: d.WgslTexture2d<d.F32>
texture
:
import d
d
.
function texture2d(): d.WgslTexture2d<d.F32> (+1 overload)
export texture2d
texture2d
() },
mySampler: {
sampler: "filtering";
}
mySampler
: {
sampler: "filtering"
sampler
: 'filtering' },
});
const
const bindGroup: TgpuBindGroup<{
myTexture: {
texture: d.WgslTexture2d<d.F32>;
};
mySampler: {
sampler: "filtering";
};
}>
bindGroup
=
const root: TgpuRoot
root
.
TgpuRoot.createBindGroup<{
myTexture: {
texture: d.WgslTexture2d<d.F32>;
};
mySampler: {
sampler: "filtering";
};
}>(layout: TgpuBindGroupLayout<{
myTexture: {
texture: d.WgslTexture2d<d.F32>;
};
mySampler: {
sampler: "filtering";
};
}>, entries: ExtractBindGroupInputFromLayout<...>): TgpuBindGroup<...>

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

@example

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

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

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

@paramlayout Layout describing the bind group to be created.

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

createBindGroup
(
const bindGroupLayout: TgpuBindGroupLayout<{
myTexture: {
texture: d.WgslTexture2d<d.F32>;
};
mySampler: {
sampler: "filtering";
};
}>
bindGroupLayout
, {
myTexture: GPUTextureView | GPUTexture | (SampledFlag & TgpuTexture<{
size: readonly number[];
format: GPUTextureFormat;
dimension?: "2d";
sampleCount?: 1;
}>) | TgpuTextureView<...>
myTexture
:
const texture: TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag
texture
,
// views can also be used - as long as the schema matches
// myTexture: texture.createView(),
mySampler: TgpuSampler | GPUSampler
mySampler
:
const sampler: TgpuFixedSampler
sampler
,
});

For textures that remain consistent across operations, you can create fixed texture views:

const
const texture: TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag
texture
=
const root: TgpuRoot
root
['~unstable'].
createTexture<number, number, number, [256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>(props: CreateTextureOptions<[256, 256], "rgba8unorm", number, number, GPUTextureFormat[], GPUTextureDimension>): TgpuTexture<...>
createTexture
({
size: [256, 256]

The width, height, and depth or layer count of the texture.

size
: [256, 256],
format: "rgba8unorm"

The format of the texture.

format
: 'rgba8unorm',
}).
TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.$usage<["sampled"]>(usages_0: "sampled"): TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag
$usage
('sampled');
// Create a fixed sampled view
const
const sampledView: TgpuTextureView<d.WgslTexture2d<d.F32>>
sampledView
=
const texture: TgpuTexture<{
size: [256, 256];
format: "rgba8unorm";
}> & SampledFlag
texture
.
TgpuTexture<{ size: [256, 256]; format: "rgba8unorm"; }>.createView(): TgpuTextureView<d.WgslTexture2d<d.F32>> (+1 overload)
createView
();
const
const sampler: TgpuFixedSampler
sampler
=
const root: TgpuRoot
root
['~unstable'].
function createSampler(props: WgslSamplerProps): TgpuFixedSampler
createSampler
({
WgslSamplerProps.magFilter?: GPUFilterMode

Specifies the sampling behavior when the sample footprint is smaller than or equal to one texel.

magFilter
: 'linear',
WgslSamplerProps.minFilter?: GPUFilterMode

Specifies the sampling behavior when the sample footprint is larger than one texel.

minFilter
: 'linear',
});
const
const myShader: TgpuFn<(uv: d.Vec2f) => d.Vec4f>
myShader
=
const tgpu: {
fn: {
<Args extends d.AnyData[] | []>(argTypes: Args, returnType?: undefined): TgpuFnShell<Args, d.Void>;
<Args extends d.AnyData[] | [], Return extends d.AnyData>(argTypes: Args, returnType: Return): TgpuFnShell<Args, Return>;
};
... 10 more ...;
'~unstable': {
...;
};
}
tgpu
.
fn: <[d.Vec2f], d.Vec4f>(argTypes: [d.Vec2f], returnType: d.Vec4f) => TgpuFnShell<[d.Vec2f], d.Vec4f> (+1 overload)
fn
([
import d
d
.
const vec2f: d.Vec2f
export vec2f

Schema representing vec2f - a vector with 2 elements of type f32. Also a constructor function for this vector value.

@example const vector = d.vec2f(); // (0.0, 0.0) const vector = d.vec2f(1); // (1.0, 1.0) const vector = d.vec2f(0.5, 0.1); // (0.5, 0.1)

@example const buffer = root.createBuffer(d.vec2f, d.vec2f(0, 1)); // buffer holding a d.vec2f value, with an initial value of vec2f(0, 1);

vec2f
],
import d
d
.
const vec4f: d.Vec4f
export vec4f

Schema representing vec4f - a vector with 4 elements of type f32. Also a constructor function for this vector value.

@example const vector = d.vec4f(); // (0.0, 0.0, 0.0, 0.0) const vector = d.vec4f(1); // (1.0, 1.0, 1.0, 1.0) const vector = d.vec4f(1, 2, 3, 4.5); // (1.0, 2.0, 3.0, 4.5)

@example const buffer = root.createBuffer(d.vec4f, d.vec4f(0, 1, 2, 3)); // buffer holding a d.vec4f value, with an initial value of vec4f(0, 1, 2, 3);

vec4f
)((
uv: d.v2f
uv
) => {
'use gpu';
// Use the fixed texture view directly
return
import std
std
.
textureSample<d.texture2d<d.F32>>(texture: d.texture2d<d.F32>, sampler: d.sampler, coords: d.v2f, offset?: d.v2i): d.v4f (+8 overloads)
export textureSample
textureSample
(
const sampledView: TgpuTextureView<d.WgslTexture2d<d.F32>>
sampledView
.
TgpuTextureView<WgslTexture2d<F32>>.$: d.texture2d<d.F32>
$
,
const sampler: TgpuFixedSampler
sampler
.
TgpuSampler.$: d.sampler
$
,
uv: d.v2f
uv
);
});