Rule 8.21
On this page

Rule 8.21

Chapter 8, Functions and entry points Test

A host call passes and returns host values by value: an f32, f64, i32 or u32 is a number, a bool a boolean, a vector a readonly tuple of its components as an argument and a tuple as a result, a matrix a flat column-major array of its components, an array<T, N> an array of N host values of T, a struct an object of its fields, and an enum member its number. A fieldless class is {} on the host and CPU. Its reflected memory footprint accounts for the GPU’s internal carrier: four bytes under natural layout, sixteen under std140, with no visible fields. Nested fields and array strides follow that footprint. Each argument is checked and converted: an ArrayLike of the right length becomes a fresh array, an f32 is rounded as a buffer write rounds it, and a value that does not fit is refused with a TypeError naming the function, the parameter and its TypeShade type; the result aliases no argument and nothing the module keeps (Rule 8.8), and an exported constant is a frozen copy. A call of a function this rule and Rule 8.20 admit is synchronous, and no later tier changes that; as a helper’s parameter, a runtime-sized array, an atomic, a texture, a sampler and a binding have no host value. A binding of an entry a host calls (Rule 8.24) takes a host value too: a uniform<T> or a sized storage<T> takes T’s, a runtime-sized storage<array<T>> of scalars or vectors takes the scalar’s typed array (Float32Array, Int32Array, Uint32Array, or Float64Array for an f64 and a vecNf64) with the vector’s components one after another, which the call pads to the element’s stride, one of structs takes an array of objects, and either may be a Resident of it (Rule 11.8), an atomic takes its integer’s, a texture_2d<f32> takes an image source (ImageBitmap, ImageData, HTMLImageElement, HTMLCanvasElement, HTMLVideoElement or OffscreenCanvas), uploaded at the call, and a sampler takes { filter?, address? } ('nearest' or 'linear'; 'clamp', 'repeat' or 'mirror'), or nothing for linear and clamp. An emulated f64 (change 0013’s split) is held by the GPU as two f32s, hi and lo, and a vecNf64 as a plane of each: the runtime splits a double into them and joins them back, and binds the _fp64 guard of a module that emulates one, which the host never passes; a matNxN<f64> has no host value yet. A storage binding the entry writes is read back into the caller’s value in place, so a written binding whose type is one scalar is passed as a typed array of length one. A kernel function (Rule 8.22) is called asynchronously: it returns Promise<void>, or Promise<R> for a result R; its value parameters take the host values above, its arrays with no size take the scalar’s typed array (Float32Array, Int32Array, Uint32Array, a vector’s components one after another) or, for a struct, an array of objects, and each array it writes is read back into the caller’s in place; each array may be a Resident of it instead (Rule 11.8), and a call whose written arrays are all resident and that returns nothing has a second signature, returning void, since nothing waits on it; before anything runs, the call checks each array against the indices a loop writes at a*i + c and refuses one too short with a TypeError naming the function, the parameter and both numbers.

The rule text and the parts under it are the compiler's own English, as the design document writes them.

Rationale

the representation is the one the CPU tier already runs on (src/core/cpu-runtime.ts), typed precisely in the host view, so there is nothing to construct and a wrong shape is a type error before it is a TypeError. The check at the call is for the caller tsc did not read: an IR node passed as a vector gave NaN in silence, and a Float32Array added to another gave a string. A later tier takes new shapes (an entry point, a runtime-sized array parameter) that are asynchronous from the day they appear, so a helper’s call site never gains an await it does not need (docs/dx.md principle 4).

Derives from

change 0009 in changes/ (“Host values were undefined”); Rule 8.8; docs/dx.md.

How it is verified

Checked by a test. A test, a gate script or a CI workflow names this rule, and the traceability check fails when a file listed below stops naming it.

Where the rule says the compiler enforces it:

toShader and fromShader in src/core/host-values.ts, which the generated module calls at every argument and result; the view’s types, from hostTypeOf in src/compiler/ts/host-face.ts; pinned by src/compiler/ts/host-face.test.ts, which checks every row in the view, a Float32Array vector, each refusal’s text, and that a result aliases no argument; the binding rows by src/compiler/ts/host-entry.test.ts and src/compiler/ts/host-draw.test.ts.

The files that verify it at commit 26de7be8, each at the first line that names the rule:

Explained in

The sections of the surface document that explain this rule, at commit 26de7be8:

See also

Source

The rule at commit 26de7be8:

Edit this page Report a problem