Skip to content

Slots

Slots are a powerful dependency injection mechanism in TypeGPU that allows you to write shader logic without having to tightly couple to specific resources. Similarly to bind group layouts, you can think of slots as of typed “holes” in TypeGPU shaders, that can be filled in later on from the outside. The main differences between slots and bound resources include the following:

  • Slots are filled in before the shader module compile time, instead of just before the shader execution starts.
  • Slots can contain not only buffers, but also basically any JavaScript value, even TypeGPU functions.

Main use cases for slots include:

  • Generics — instead of rewriting a function for each generic parameter, it suffices to fill a slot with a different value.
  • Passing callbacks — high-level libraries based on TypeGPU can leave slots for user-defined functions to call.

A slot is created using the tgpu.slot() function and can optionally take a default value:

const
const filterColorSlot: TgpuSlot<d.v3f>
filterColorSlot
=
const tgpu: {
const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant;
fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn;
comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime;
resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve;
resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext;
init: typeof import("node_modules/typegpu/src/core/root/init").init;
initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice;
slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot;
lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy;
... 10 more ...;
'~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");
}

@moduletypegpu

tgpu
.
slot: <d.v3f>(defaultValue?: d.v3f | undefined) => TgpuSlot<d.v3f>
slot
<
import d
d
.
export v3f

Interface representing its WGSL vector type counterpart: vec3f or vec3. A vector with 3 elements of type f32

v3f
>(); // Slot for a 3D vector.
const
const mySlot: TgpuSlot<number>
mySlot
=
const tgpu: {
const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant;
fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn;
comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime;
resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve;
resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext;
init: typeof import("node_modules/typegpu/src/core/root/init").init;
initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice;
slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot;
lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy;
... 10 more ...;
'~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");
}

@moduletypegpu

tgpu
.
slot: <number>(defaultValue?: number | undefined) => TgpuSlot<number>
slot
<number>(42); // Slot with a default value.
interface
interface Config
Config
{
Config.fogEnabled: boolean
fogEnabled
: boolean;
Config.tint: d.v3f
tint
:
import d
d
.
export v3f

Interface representing its WGSL vector type counterpart: vec3f or vec3. A vector with 3 elements of type f32

v3f
;
}
const
const configSlot: TgpuSlot<Config>
configSlot
=
const tgpu: {
const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant;
fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn;
comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime;
resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve;
resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext;
init: typeof import("node_modules/typegpu/src/core/root/init").init;
initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice;
slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot;
lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy;
... 10 more ...;
'~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");
}

@moduletypegpu

tgpu
.
slot: <Config>(defaultValue?: Config | undefined) => TgpuSlot<Config>
slot
<
interface Config
Config
>();

You can access a slot’s value using .$:

const value = mySlot.$;

Slots are resolved during the TypeGPU resolution phase. The slot object itself does not hold any value. Instead, you can bind it in one of two ways.

The first way to bind a value to a slot is to call the with method on a wrapped TypeGPU function:

const
const filterColorSlot: TgpuSlot<d.v3f>
filterColorSlot
=
const tgpu: {
const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant;
fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn;
comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime;
resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve;
resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext;
init: typeof import("node_modules/typegpu/src/core/root/init").init;
initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice;
slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot;
lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy;
... 10 more ...;
'~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");
}

@moduletypegpu

tgpu
.
slot: <d.v3f>(defaultValue?: d.v3f | undefined) => TgpuSlot<d.v3f>
slot
<
import d
d
.
export v3f

Interface representing its WGSL vector type counterpart: vec3f or vec3. A vector with 3 elements of type f32

v3f
>();
const
const filter: (color: d.v3f) => d.v3f
filter
= (
color: d.v3f
color
:
import d
d
.
export v3f

Interface representing its WGSL vector type counterpart: vec3f or vec3. A vector with 3 elements of type f32

v3f
):
import d
d
.
export v3f

Interface representing its WGSL vector type counterpart: vec3f or vec3. A vector with 3 elements of type f32

v3f
=> {
'use gpu';
const
const filterColor: d.v3f
filterColor
=
const filterColorSlot: TgpuSlot<d.v3f>
filterColorSlot
.
TgpuSlot<v3f>.$: d.v3f
$
;
return
color: d.v3f
color
.
vecInfixNotation<v3f>.mul(other: number | d.v3f | d.m3x3f): d.v3f
mul
(
const filterColor: d.v3f
filterColor
);
};
// Bind the filter function with a red color.
const
const filterWithRed: TgpuGenericFn<(color: d.v3f) => d.v3f>
filterWithRed
=
const tgpu: {
const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant;
fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn;
comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime;
resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve;
resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext;
init: typeof import("node_modules/typegpu/src/core/root/init").init;
initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice;
slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot;
lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy;
... 10 more ...;
'~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");
}

@moduletypegpu

tgpu
.
fn: <(color: d.v3f) => d.v3f>(inner: (color: d.v3f) => d.v3f) => TgpuGenericFn<(color: d.v3f) => d.v3f> (+2 overloads)
fn
(
const filter: (color: d.v3f) => d.v3f
filter
)
.
Withable<TgpuGenericFn<(color: d.v3f) => d.v3f>>.with<d.v3f>(slot: TgpuSlot<d.v3f>, value: Eventual<d.v3f>): TgpuGenericFn<(color: d.v3f) => d.v3f> (+2 overloads)
with
(
const filterColorSlot: TgpuSlot<d.v3f>
filterColorSlot
,
import d
d
.
function vec3f(x: number, y: number, z: number): d.v3f (+5 overloads)
export vec3f

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

@example const vector = d.vec3f(); // (0.0, 0.0, 0.0) const vector = d.vec3f(1); // (1.0, 1.0, 1.0) const vector = d.vec3f(1, 2, 3.5); // (1.0, 2.0, 3.5)

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

vec3f
(1, 0, 0));
// Bind the filter function with a green color.
const
const filterWithGreen: TgpuGenericFn<(color: d.v3f) => d.v3f>
filterWithGreen
=
const tgpu: {
const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant;
fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn;
comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime;
resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve;
resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext;
init: typeof import("node_modules/typegpu/src/core/root/init").init;
initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice;
slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot;
lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy;
... 10 more ...;
'~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");
}

@moduletypegpu

tgpu
.
fn: <(color: d.v3f) => d.v3f>(inner: (color: d.v3f) => d.v3f) => TgpuGenericFn<(color: d.v3f) => d.v3f> (+2 overloads)
fn
(
const filter: (color: d.v3f) => d.v3f
filter
)
.
Withable<TgpuGenericFn<(color: d.v3f) => d.v3f>>.with<d.v3f>(slot: TgpuSlot<d.v3f>, value: Eventual<d.v3f>): TgpuGenericFn<(color: d.v3f) => d.v3f> (+2 overloads)
with
(
const filterColorSlot: TgpuSlot<d.v3f>
filterColorSlot
,
import d
d
.
function vec3f(x: number, y: number, z: number): d.v3f (+5 overloads)
export vec3f

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

@example const vector = d.vec3f(); // (0.0, 0.0, 0.0) const vector = d.vec3f(1); // (1.0, 1.0, 1.0) const vector = d.vec3f(1, 2, 3.5); // (1.0, 2.0, 3.5)

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

vec3f
(0, 1, 0));

In the example above, after resolution we are left with two different WGSL functions:

fn filter_0(color: vec3f) -> vec3f{
var filterColor = vec3f(1, 0, 0);
return (color * filterColor);
}
fn filter_1(color: vec3f) -> vec3f{
var filterColor = vec3f(0, 1, 0);
return (color * filterColor);
}

The other way to fill in a slot is to call the with method during the creation of a TgpuComputePipeline or TgpuRenderPipeline:

const
const resultBuffer: TgpuMutable<d.I32>
resultBuffer
=
const root: TgpuRoot
root
.
TgpuRoot.createMutable<d.I32>(typeSchema: d.I32, initial?: number | ((buffer: TgpuBuffer<NoInfer<d.I32>>) => void) | undefined): TgpuMutable<d.I32> (+1 overload)

Allocates memory on the GPU, allows passing data between host and shader. Can be mutated in-place on the GPU. For a general-purpose buffer, use

TgpuRoot.createBuffer

.

@paramtypeSchema The type of data that this buffer will hold.

@paraminitial Either initial value of the buffer, or an initializer to execute on the mapped buffer. (optional)

createMutable
(
import d
d
.
const i32: d.I32
export i32

A schema that represents a signed 32-bit integer value. (equivalent to i32 in WGSL)

Can also be called to cast a value to an i32 in accordance with WGSL casting rules.

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

@example const value = i32(3.14); // 3

@example const value = i32(-3.9); // -3

@example const value = i32(10000000000) // 1410065408

i32
, 0);
const
const multiplierSlot: TgpuSlot<number>
multiplierSlot
=
const tgpu: {
const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant;
fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn;
comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime;
resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve;
resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext;
init: typeof import("node_modules/typegpu/src/core/root/init").init;
initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice;
slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot;
lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy;
... 10 more ...;
'~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");
}

@moduletypegpu

tgpu
.
slot: <number>(defaultValue?: number | undefined) => TgpuSlot<number>
slot
<number>();
const
const computeMultiply: TgpuComputeFn<{}>
computeMultiply
=
const tgpu: {
const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant;
fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn;
comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime;
resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve;
resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext;
init: typeof import("node_modules/typegpu/src/core/root/init").init;
initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice;
slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot;
lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy;
... 10 more ...;
'~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");
}

@moduletypegpu

tgpu
.
computeFn: (options: {
workgroupSize: number[];
}) => TgpuComputeFnShell<{}> (+1 overload)
computeFn
({
workgroupSize: number[]
workgroupSize
: [1] })(() => {
const resultBuffer: TgpuMutable<d.I32>
resultBuffer
.
TgpuMutable<I32>.$: number
$
=
const resultBuffer: TgpuMutable<d.I32>
resultBuffer
.
TgpuMutable<I32>.$: number
$
*
const multiplierSlot: TgpuSlot<number>
multiplierSlot
.
TgpuSlot<number>.$: number
$
;
});
const
const pipeline: TgpuComputePipeline
pipeline
=
const root: TgpuRoot
root
.
Withable<WithBinding>.with<number>(slot: TgpuSlot<number>, value: Eventual<number>): WithBinding (+2 overloads)
with
(
const multiplierSlot: TgpuSlot<number>
multiplierSlot
, 3)
.
WithBinding.createComputePipeline<{}>(descriptor: TgpuComputePipeline.Descriptor<{}>): TgpuComputePipeline
createComputePipeline
({
compute: TgpuComputeFn<{}>
compute
:
const computeMultiply: TgpuComputeFn<{}>
computeMultiply
});

The pipeline above resolves to the following WGSL:

@group(0) @binding(0) var<storage, read_write> resultBuffer_1: i32;
@compute @workgroup_size(1) fn computeMultiply_0(){
resultBuffer_1 = (resultBuffer_1 * 3);
}

Slots allow libraries to expose customization points to their users. They enable internal behavior to be modified without sacrificing type safety or performance.

physics.ts
const
const defaultGravity: TgpuFn<(pos: d.Vec2f) => d.Vec2f>
defaultGravity
=
const tgpu: {
const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant;
fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn;
comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime;
resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve;
resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext;
init: typeof import("node_modules/typegpu/src/core/root/init").init;
initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice;
slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot;
lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy;
... 10 more ...;
'~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");
}

@moduletypegpu

tgpu
.
fn: <[d.Vec2f], d.Vec2f>(argTypes: [d.Vec2f], returnType: d.Vec2f) => TgpuFnShell<[d.Vec2f], d.Vec2f> (+2 overloads)
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 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
)((
pos: d.v2f
pos
) => {
return
import d
d
.
function vec2f(x: number, y: number): d.v2f (+3 overloads)
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
(0, -9.8);
});
export const gravitySlot =
const tgpu: {
const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant;
fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn;
comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime;
resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve;
resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext;
init: typeof import("node_modules/typegpu/src/core/root/init").init;
initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice;
slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot;
lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy;
... 10 more ...;
'~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");
}

@moduletypegpu

tgpu
.
slot: <TgpuFn<(pos: d.Vec2f) => d.Vec2f>>(defaultValue?: TgpuFn<(pos: d.Vec2f) => d.Vec2f> | undefined) => TgpuSlot<TgpuFn<(pos: d.Vec2f) => d.Vec2f>>
slot
(
const defaultGravity: TgpuFn<(pos: d.Vec2f) => d.Vec2f>
defaultGravity
);
const gravitySlot: TgpuSlot<TgpuFn<(pos: d.Vec2f) => d.Vec2f>>
export const
const stepPhysics: TgpuFn<() => d.Void>
stepPhysics
=
const tgpu: {
const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant;
fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn;
comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime;
resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve;
resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext;
init: typeof import("node_modules/typegpu/src/core/root/init").init;
initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice;
slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot;
lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy;
... 10 more ...;
'~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");
}

@moduletypegpu

tgpu
.
fn: <[]>(argTypes: [], returnType?: undefined) => TgpuFnShell<[], d.Void> (+2 overloads)
fn
([])(() => {
for (const
const obj: {
position: d.v2f;
velocity: d.v2f;
}
obj
of
const objects: TgpuReadonly<d.WgslArray<d.WgslStruct<{
position: d.Vec2f;
velocity: d.Vec2f;
}>>>
objects
.
TgpuReadonly<WgslArray<WgslStruct<{ position: Vec2f; velocity: Vec2f; }>>>.$: {
position: d.v2f;
velocity: d.v2f;
}[]
$
) {
// Calling whatever implementation was provided.
const
const gravity: d.v2f
gravity
=
const gravitySlot: TgpuSlot<TgpuFn<(pos: d.Vec2f) => d.Vec2f>>
gravitySlot
.
TgpuSlot<TgpuFn<(pos: Vec2f) => Vec2f>>.$: (pos: d.v2f) => d.v2f
$
(
const obj: {
position: d.v2f;
velocity: d.v2f;
}
obj
.
position: d.v2f
position
);
const obj: {
position: d.v2f;
velocity: d.v2f;
}
obj
.
velocity: d.v2f
velocity
=
add<d.v2f>(lhs: d.v2f, rhs: d.v2f): d.v2f (+4 overloads)
add
(
const obj: {
position: d.v2f;
velocity: d.v2f;
}
obj
.
velocity: d.v2f
velocity
,
mul<d.v2f>(lhs: d.v2f, rhs: number): d.v2f (+7 overloads)
mul
(
const gravity: d.v2f
gravity
,
const deltaTime: TgpuUniform<d.F32>
deltaTime
.
TgpuUniform<F32>.$: number
$
));
}
});
main.ts
import { stepPhysics, gravitySlot } from './physics.ts';
const gravityTowardsCenter = tgpu.fn([vec2f], vec2f)((pos) => {
return mul(normalize(pos), -1);
});
const stepPhysicsCustomized = stepPhysics
.with(gravitySlot, gravityTowardsCenter);
const main = tgpu.computeFn()(() => {
stepPhysicsCustomized(); // <- Will use altered gravity.
});

tgpu.lazy(compute) defers a JavaScript computation until shader resolution. Its result is memoized for the current resolution namespace and slot bindings, so shared dependencies are computed only once. Access the resolved value with .$, just like a slot:

const
const componentCount: TgpuSlot<number>
componentCount
=
const tgpu: {
const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant;
fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn;
comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime;
resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve;
resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext;
init: typeof import("node_modules/typegpu/src/core/root/init").init;
initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice;
slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot;
lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy;
... 10 more ...;
'~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");
}

@moduletypegpu

tgpu
.
slot: <number>(defaultValue?: number | undefined) => TgpuSlot<number>
slot
(4);
const
const ResultArray: TgpuLazy<d.WgslArray<d.F32>>
ResultArray
=
const tgpu: {
const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant;
fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn;
comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime;
resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve;
resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext;
init: typeof import("node_modules/typegpu/src/core/root/init").init;
initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice;
slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot;
lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy;
... 10 more ...;
'~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");
}

@moduletypegpu

tgpu
.
lazy: <d.WgslArray<d.F32>>(compute: () => d.WgslArray<d.F32>) => TgpuLazy<d.WgslArray<d.F32>>
lazy
(() =>
import d
d
.
arrayOf<d.F32>(elementType: d.F32, elementCount: number): d.WgslArray<d.F32> (+1 overload)
export arrayOf

Creates an array schema that can be used to construct gpu buffers. Describes arrays with fixed-size length, storing elements of the same type.

@example

const LENGTH = 3; const array = d.arrayOf(d.u32, LENGTH);

If elementCount is not specified, a partially applied function is returned.

@example const array = d.arrayOf(d.vec3f); // ^? (n: number) => WgslArray<d.Vec3f>

@paramelementType The type of elements in the array.

@paramelementCount The number of elements in the array.

arrayOf
(
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
,
const componentCount: TgpuSlot<number>
componentCount
.
TgpuSlot<number>.$: number
$
)
);
const
const createResult: TgpuFn<() => d.Void>
createResult
=
const tgpu: {
const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant;
fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn;
comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime;
resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve;
resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext;
init: typeof import("node_modules/typegpu/src/core/root/init").init;
initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice;
slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot;
lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy;
... 10 more ...;
'~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");
}

@moduletypegpu

tgpu
.
fn: <[]>(argTypes: [], returnType?: undefined) => TgpuFnShell<[], d.Void> (+2 overloads)
fn
([])(() => {
const
const result: number[]
result
=
const ResultArray: TgpuLazy<d.WgslArray<d.F32>>
ResultArray
.
TgpuLazy<WgslArray<F32>>.$: d.WgslArray
() => number[] (+1 overload)
$
();
});
const
const createShortResult: TgpuFn<() => d.Void>
createShortResult
=
const createResult: TgpuFn<() => d.Void>
createResult
.
Withable<TgpuFn<() => Void>>.with<number>(slot: TgpuSlot<number>, value: Eventual<number>): TgpuFn<() => d.Void> (+2 overloads)
with
(
const componentCount: TgpuSlot<number>
componentCount
, 2);

A lazy computation can read slots, accessors, and other lazy values. Use .with(slotOrAccessor, value) on the lazy object when it should carry a binding into its computation and into resources returned from it.

const configuredResult = ResultArray.with(componentCount, 8);

Every configurable TypeGPU object supports .pipe(transform). It lets libraries package a set of slot or accessor bindings as a reusable configuration transform:

import type {
(alias) interface Configurable
import Configurable
Configurable
} from 'typegpu';
const
const lightingEnabled: TgpuSlot<boolean>
lightingEnabled
=
const tgpu: {
const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant;
fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn;
comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime;
resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve;
resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext;
init: typeof import("node_modules/typegpu/src/core/root/init").init;
initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice;
slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot;
lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy;
... 10 more ...;
'~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");
}

@moduletypegpu

tgpu
.
slot: <boolean>(defaultValue?: boolean | undefined) => TgpuSlot<boolean>
slot
(false);
const
const lightCount: TgpuSlot<number>
lightCount
=
const tgpu: {
const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant;
fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn;
comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime;
resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve;
resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext;
init: typeof import("node_modules/typegpu/src/core/root/init").init;
initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice;
slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot;
lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy;
... 10 more ...;
'~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");
}

@moduletypegpu

tgpu
.
slot: <number>(defaultValue?: number | undefined) => TgpuSlot<number>
slot
(0);
const
const injectLighting: (cfg: Configurable) => Configurable
injectLighting
= (
cfg: Configurable
cfg
:
(alias) interface Configurable
import Configurable
Configurable
) =>
cfg: Configurable
cfg
.
Withable<Configurable>.with<boolean>(slot: TgpuSlot<boolean>, value: Eventual<boolean>): Configurable (+2 overloads)
with
(
const lightingEnabled: TgpuSlot<boolean>
lightingEnabled
, true)
.
Withable<Configurable>.with<number>(slot: TgpuSlot<number>, value: Eventual<number>): Configurable (+2 overloads)
with
(
const lightCount: TgpuSlot<number>
lightCount
, 4);
const
const configuredRoot: WithBinding
configuredRoot
=
const root: TgpuRoot
root
.
WithBinding.pipe(transform: (cfg: Configurable) => Configurable): WithBinding
pipe
(
const injectLighting: (cfg: Configurable) => Configurable
injectLighting
);

The transform receives the current configurable object and must return a configurable object. Transforms can be chained and can themselves call .with(...) or another .pipe(...), making them useful for library-level feature injection.

It is possible to use slots even in TypeGPU functions that are implemented in WGSL:

const
const colorSlot: TgpuSlot<d.v3f>
colorSlot
=
const tgpu: {
const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant;
fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn;
comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime;
resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve;
resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext;
init: typeof import("node_modules/typegpu/src/core/root/init").init;
initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice;
slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot;
lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy;
... 10 more ...;
'~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");
}

@moduletypegpu

tgpu
.
slot: <d.v3f>(defaultValue?: d.v3f | undefined) => TgpuSlot<d.v3f>
slot
(
import d
d
.
function vec3f(x: number, y: number, z: number): d.v3f (+5 overloads)
export vec3f

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

@example const vector = d.vec3f(); // (0.0, 0.0, 0.0) const vector = d.vec3f(1); // (1.0, 1.0, 1.0) const vector = d.vec3f(1, 2, 3.5); // (1.0, 2.0, 3.5)

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

vec3f
(1, 0, 0));
const
const getColor: TgpuFn<() => d.Vec3f>
getColor
=
const tgpu: {
const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant;
fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn;
comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime;
resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve;
resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext;
init: typeof import("node_modules/typegpu/src/core/root/init").init;
initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice;
slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot;
lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy;
... 10 more ...;
'~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");
}

@moduletypegpu

tgpu
.
fn: <[], d.Vec3f>(argTypes: [], returnType: d.Vec3f) => TgpuFnShell<[], d.Vec3f> (+2 overloads)
fn
([],
import d
d
.
const vec3f: d.Vec3f
export vec3f

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

@example const vector = d.vec3f(); // (0.0, 0.0, 0.0) const vector = d.vec3f(1); // (1.0, 1.0, 1.0) const vector = d.vec3f(1, 2, 3.5); // (1.0, 2.0, 3.5)

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

vec3f
)`() {
return colorSlot;
}`.
TgpuFnBase<() => Vec3f>.$uses(dependencyMap: Record<string, unknown>): TgpuFn<() => d.Vec3f>
$uses
({
colorSlot: TgpuSlot<d.v3f>
colorSlot
});

The code above resolves to the following WGSL:

fn getColor() -> vec3f {
return vec3f(1, 0, 0);
}