Skip to content

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

Variables

When using TypeGPU for resolution, there is no need to ever define either var<uniform> or var<storage[, address_space]>, as such definitions are added automatically.

For example, in the code snippet below, the external counter is automatically included as a @group(0) @binding(0) var<storage, read_write> counter: vec3f. In this case, the group and index match the automatically generated “catchall” bind group, used for fixed, “bindless” resources.

const
const counter: TgpuMutable<d.Vec3f>
counter
=
const root: TgpuRoot
root
.
TgpuRoot.createMutable<d.Vec3f>(typeSchema: d.Vec3f, initial?: d.v3f | undefined): TgpuMutable<d.Vec3f> (+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 The initial value of the buffer. (optional)

createMutable
(
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
,
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));
const
const increment: TgpuComputeFn<{
num: d.BuiltinNumWorkgroups;
}>
increment
=
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
['~unstable'].
computeFn: <{
num: d.BuiltinNumWorkgroups;
}>(options: {
in: {
num: d.BuiltinNumWorkgroups;
};
workgroupSize: number[];
}) => TgpuComputeFnShell<{
num: d.BuiltinNumWorkgroups;
}> (+1 overload)
computeFn
({
in: {
num: d.BuiltinNumWorkgroups;
}
in
: {
num: d.BuiltinNumWorkgroups
num
:
import d
d
.
const builtin: {
readonly vertexIndex: d.BuiltinVertexIndex;
readonly instanceIndex: d.BuiltinInstanceIndex;
readonly position: d.BuiltinPosition;
readonly clipDistances: d.BuiltinClipDistances;
... 10 more ...;
readonly subgroupSize: BuiltinSubgroupSize;
}
export builtin
builtin
.
numWorkgroups: d.BuiltinNumWorkgroups
numWorkgroups
},
workgroupSize: number[]
workgroupSize
: [1],
})((
input: {
num: d.v3u;
}
input
) => {
const
const tmp: number
tmp
=
const counter: TgpuMutable<d.Vec3f>
counter
.
TgpuMutable<Vec3f>.$: d.v3f
$
.
v3f.x: number
x
;
const counter: TgpuMutable<d.Vec3f>
counter
.
TgpuMutable<Vec3f>.$: d.v3f
$
.
v3f.x: number
x
=
const counter: TgpuMutable<d.Vec3f>
counter
.
TgpuMutable<Vec3f>.$: d.v3f
$
.
v3f.y: number
y
;
const counter: TgpuMutable<d.Vec3f>
counter
.
TgpuMutable<Vec3f>.$: d.v3f
$
.
v3f.y: number
y
+=
const tmp: number
tmp
;
const counter: TgpuMutable<d.Vec3f>
counter
.
TgpuMutable<Vec3f>.$: d.v3f
$
.
v3f.z: number
z
+=
import d
d
.
function f32(v?: number | boolean): number
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
(
input: {
num: d.v3u;
}
input
.
num: d.v3u
num
.
v3u.x: number
x
);
});
const
const pipeline: TgpuComputePipeline
pipeline
=
const root: TgpuRoot
root
['~unstable'].
withCompute<{
num: d.BuiltinNumWorkgroups;
}>(entryFn: TgpuComputeFn<{
num: d.BuiltinNumWorkgroups;
}>): WithCompute
withCompute
(
const increment: TgpuComputeFn<{
num: d.BuiltinNumWorkgroups;
}>
increment
).
WithCompute.createPipeline(): TgpuComputePipeline
createPipeline
();
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(
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
.
resolve: (options: TgpuResolveOptions) => string

Resolves a template with external values. Each external will get resolved to a code string and replaced in the template. Any dependencies of the externals will also be resolved and included in the output.

@paramoptions - The options for the resolution.

@returnsThe resolved code.

@example

const Gradient = d.struct({
from: d.vec3f,
to: d.vec3f,
});
const resolved = tgpu.resolve({
template: `
fn getGradientAngle(gradient: Gradient) -> f32 {
return atan(gradient.to.y - gradient.from.y, gradient.to.x - gradient.from.x);
}
`,
externals: {
Gradient,
},
});
console.log(resolved);
// struct Gradient_0 {
// from: vec3f,
// to: vec3f,
// }
// fn getGradientAngle(gradient: Gradient_0) -> f32 {
// return atan(gradient.to.y - gradient.from.y, gradient.to.x - gradient.from.x);
// }

resolve
({
TgpuResolveOptions.externals: Record<string, object | Wgsl>

Map of external names to their resolvable values.

externals
: {
pipeline: TgpuComputePipeline
pipeline
} }));
// resolved WGSL
@group(0) @binding(0) var<storage, read_write> counter: vec3f;
struct increment_Input {
@builtin(num_workgroups) num: vec3u,
}
@compute @workgroup_size(1) fn increment(input: increment_Input) {
var tmp = counter.x;
counter.x = counter.y;
counter.y += tmp;
counter.z += f32(input.num.x);
}

For variables of private and workgroup address spaces, TypeGPU provides tgpu.privateVar() and tgpu.workgroupVar() constructor functions.

const
const threadCounter: TgpuVar<"private", d.U32>
threadCounter
=
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
.
privateVar: <d.U32>(dataType: d.U32, initialValue?: number | undefined) => TgpuVar<"private", d.U32>

Defines a variable scoped to each entry function (private).

@paramdataType The schema of the held data's type

@paraminitialValue If not provided, the variable will be initialized to the dataType's "zero-value".

privateVar
(
import d
d
.
const u32: d.U32
export u32

A schema that represents an unsigned 32-bit integer value. (equivalent to u32 in WGSL)

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

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

@example const value = u32(7); // 7

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

@example const value = u32(-1); // 4294967295

@example const value = u32(-3.1); // 0

u32
, 0);
const
const getNext: () => number
getNext
= () => {
'use gpu';
const threadCounter: TgpuVar<"private", d.U32>
threadCounter
.
TgpuVar<"private", U32>.$: number
$
+= 1;
return [42, 418, 23][
const threadCounter: TgpuVar<"private", d.U32>
threadCounter
.
TgpuVar<"private", U32>.$: number
$
];
};
const
const myComputeFn: TgpuComputeFn<{}>
myComputeFn
=
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
['~unstable'].
computeFn: (options: {
workgroupSize: number[];
}) => TgpuComputeFnShell<{}> (+1 overload)
computeFn
({
workgroupSize: number[]
workgroupSize
: [64],
})(() => {
const
const a: number
a
=
const getNext: () => number
getNext
();
const
const b: number
b
=
const getNext: () => number
getNext
();
const
const c: number
c
=
const getNext: () => number
getNext
();
// ...
});

The meaning of const differs between JS and WGSL. In JS, a const is a reference that cannot be reassigned, while in WGSL, it means a value known at shader-creation time. Therefore, to use the WGSL const, TypeGPU provides tgpu.const(), an interface analogous to tgpu.privateVar() and tgpu.workgroupVar(), with the only difference being that the previously optional init value is now required.

const
const Boid: d.WgslStruct<{
pos: d.Vec3f;
vel: d.Vec3u;
}>
Boid
=
import d
d
.
struct<{
pos: d.Vec3f;
vel: d.Vec3u;
}>(props: {
pos: d.Vec3f;
vel: d.Vec3u;
}): d.WgslStruct<{
pos: d.Vec3f;
vel: d.Vec3u;
}>
export struct

Creates a struct schema that can be used to construct GPU buffers. Ensures proper alignment and padding of properties (as opposed to a d.unstruct schema). The order of members matches the passed in properties object.

@example const CircleStruct = d.struct({ radius: d.f32, pos: d.vec3f });

@paramprops Record with string keys and TgpuData values, each entry describing one struct member.

struct
({
pos: d.Vec3f
pos
:
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
,
vel: d.Vec3u
vel
:
import d
d
.
const vec3u: d.Vec3u
export vec3u

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

@example const vector = d.vec3u(); // (0, 0, 0) const vector = d.vec3u(1); // (1, 1, 1) const vector = d.vec3u(1, 2, 3); // (1, 2, 3)

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

vec3u
,
});
const
const boid: TgpuConst<d.WgslStruct<{
pos: d.Vec3f;
vel: d.Vec3u;
}>>
boid
=
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
.
const: <d.WgslStruct<{
pos: d.Vec3f;
vel: d.Vec3u;
}>>(dataType: d.WgslStruct<{
pos: d.Vec3f;
vel: d.Vec3u;
}>, value: {
pos: d.v3f;
vel: d.v3u;
}) => TgpuConst<d.WgslStruct<{
pos: d.Vec3f;
vel: d.Vec3u;
}>>

Creates a module constant with specified value.

const
(
const Boid: d.WgslStruct<{
pos: d.Vec3f;
vel: d.Vec3u;
}>
Boid
, {
pos: d.v3f
pos
:
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, 2, 3),
vel: d.v3u
vel
:
import d
d
.
function vec3u(x: number, y: number, z: number): d.v3u (+5 overloads)
export vec3u

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

@example const vector = d.vec3u(); // (0, 0, 0) const vector = d.vec3u(1); // (1, 1, 1) const vector = d.vec3u(1, 2, 3); // (1, 2, 3)

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

vec3u
(4, 5, 6),
});
const
const func: () => void
func
= () => {
'use gpu';
const
const pos: {
pos: d.v3f;
vel: d.v3u;
}
pos
=
const boid: TgpuConst<d.WgslStruct<{
pos: d.Vec3f;
vel: d.Vec3u;
}>>
boid
.
TgpuConst<WgslStruct<{ pos: Vec3f; vel: Vec3u; }>>.$: {
pos: d.v3f;
vel: d.v3u;
}
$
;
const
const vel: d.v3u
vel
=
const boid: TgpuConst<d.WgslStruct<{
pos: d.Vec3f;
vel: d.Vec3u;
}>>
boid
.
TgpuConst<WgslStruct<{ pos: Vec3f; vel: Vec3u; }>>.$: {
pos: d.v3f;
vel: d.v3u;
}
$
.
vel: d.v3u
vel
;
const
const velX: number
velX
=
const boid: TgpuConst<d.WgslStruct<{
pos: d.Vec3f;
vel: d.Vec3u;
}>>
boid
.
TgpuConst<WgslStruct<{ pos: Vec3f; vel: Vec3u; }>>.$: {
pos: d.v3f;
vel: d.v3u;
}
$
.
vel: d.v3u
vel
.
v3u.x: number
x
;
};