CPU and GPU
On this page

CPU and GPU

A TypeShade file is TypeScript to your editor and a GPU program to the compiler. The restrictions the language guide states are not house style. Each one follows from something the hardware does, so this page gives the fact first and the rule after it.

Invocations

A TypeScript function runs once when you call it. An entry point is called by the GPU instead, once for every vertex in a draw, once for every fragment a primitive covers, and once for every work item in a dispatch. Those runs happen beside each other and cannot read each other. Nothing outside the function tells one of them which one it is.

@compute([64, 1, 1])
export function paint(@builtin("global_invocation_id") gid: vec3u) {
pixels[gid.x] = camera.pos.x
}

What follows: a stage decorator says which of the three is calling, and a @builtin(...) parameter is how an invocation learns its own place in the work. Shader stages states the decorators and Functions states the parameters.

Memory

An invocation works in registers and in the buffers and textures the host bound before the draw. There is no heap under it, so a shader has nothing to allocate from, no array that can grow and no string to build. A class in a TypeShade file describes the bytes of a GPU struct, and the host writes those bytes.

class Camera {
view: mat4
pos: vec3
}
declare const camera: uniform<Camera>

What follows: new builds a value and not an object with identity, the order of a class's fields is the layout of the bytes the host writes, and every resource arrives through declare. Types states the struct surface and Resources states the declarations.

Calls

A shader has no call stack to return through, and the call graph is flattened before a driver sees it. A function that calls itself, directly or through another function, leaves the compiler with nothing to flatten.

What follows: recursion is rejected, and a helper is an ordinary function the compiler can follow to its leaves. Functions states what a call may be.

Loops

The invocations of a stage move through a loop together, and the ones that leave early wait for the rest. A counted loop compares its counter to a bound the body does not write and steps toward it, which is what the compiler checks; the bound itself may be a value the program learns at run time.

for (let i = 0; i < 4; i++) {
pixels[i] = pixels[i] + camera.pos.x
}

What follows: a for counts toward a bound its body does not move, and a while ends where its condition or a break says. Control flow states which conditions and loops compile.

Value types

A GPU register has a width and a layout, fixed when the shader is compiled. A variable therefore holds one value type from its declaration to the end of its scope, with no union of two value types and nothing at run time that could choose between them.

let value: f32 = 1
let index: u32 = 0
let direction: vec3 = vec3(0, 1, 0)

What follows: every value carries a written GPU type such as f32, u32 or vec4. Types states the type surface and GPU types states the values.

Facts and rules

The facts above with the rule each produces, and the page of the language guide that states it.

What the GPU doesWhat TypeShade asks forStated in
Calls an entry point once per vertex, fragment or work itemA stage decorator on the entry point and a parameter for every builtin inputShader stages
Gives an invocation registers and bound resources, with no heap under themNo growing array and no string; new builds a value, a class is a layout and a resource is a declareResources
Runs without a call stackA call graph the compiler can flatten, so no recursionFunctions
Moves the invocations of a stage through a loop togetherA loop bound the compiler can readControl flow
Holds a value of one width in a registerOne value type per variable, written outGPU types

Further reading

  • WGSL specification writes down the execution model these facts come from, including what an invocation is and what it may hold.
  • MDN WebGPU API is the browser side of the same model, written for a JavaScript developer.

Next in this path: The pipeline, which says what each stage is handed and what it produces.

Edit this page Report a problem