Rule 11.11
On this page

Rule 11.11

Chapter 11, Targets and the oracle Test

The program runtime, typeshade/runtime, loads a manifest (Rule 11.10) and runs its entries on WebGPU, on the host’s device or on one it requests with the features the programs need; its module closure must hold no file of src/compiler/ and no package, and its bundle must stay within the size budget scripts/bundle-budget.json records. The load-time emitter, repack from typeshade/emit, emits a manifest again from the portable IR it carries, under the options the manifest records (emit), with a variant the build did not write (console), and must refuse a manifest with no IR and an IR another package version wrote, naming both versions; its module closure must hold no file of src/compiler/ and no package, within its own budget; the runtime takes it as createRuntime({ emit }) and never imports it, so load(m, { console: true }) of a manifest with no recorded variant records through it, and is refused, naming the remedy, without it. It builds each pipeline’s layout from the manifest, the bindings the pipeline’s entries reach each visible to the stages that reach them and each texture laid out by the sample type the manifest gives it, and never layout: 'auto'; it makes each shader module from the text the manifest holds and binds the bindings the manifest lists, the _fp64 guard among them where it lists one, so a program packed under emit options (Rule 11.10) runs as it was packed; it binds by the names the source declares, packing a plain host value (Rule 8.21) by the binding’s layout, and refuses an unknown name, a missing binding and a value of the wrong shape with a TypeError naming the entry, its line and the binding; it creates each pipeline with the override values the host gives it by name, the same to every stage, one pipeline for each set of values, and refuses with a TypeError a name the manifest does not declare, naming the program’s overrides, and a value its type cannot hold, naming the override and what its type takes; it refuses a manifest of another schema, a feature the device lacks, and a colour target whose format cannot hold the entry’s output there; it reads a texture back as bytes (every uncompressed colour format and depth32float, rows tightly packed) or as numbers (a float, unorm or snorm format and depth32float; an integer format is refused with a TypeError that names read()), recording and submitting the copy before the read awaits anything, so that a read reads what was submitted before the call; a frame that repeats its shapes creates no GPU object; and the console.* calls of a program loaded to record reach the host’s sink or its console after the submit that ran them, and that submit resolves to what each console buffer it read back held (its entry, the lines it kept and the calls that did not fit), where a runtime given a sink prints nothing, the warning for the calls that did not fit included, since its host takes the count.

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

Rationale

a host that develops dynamically needs a runtime, and an application must not ship the compiler to have one: the front end is 1.4 MB gzipped with TypeScript, the runtime about 11 KB; a boundary a bundler infers from one sideEffects line is not a boundary, so the check reads the imports.

Derives from

changes 0025 (section 2) and 0028 in changes/; issues #335 (decision 1), #404, #407 and #414; Rule 11.10.

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:

createRuntime and RuntimeImpl in src/runtime/runtime.ts, ProgramImpl in src/runtime/program.ts and src/runtime/resources.ts; the boundary by scripts/bundle-boundary.ts, in CI’s typecheck + unit job; pinned by src/runtime/runtime.test.ts against a recording device (creation per frame, layouts, a texture’s sample type in its layout, each refusal’s text, the override values each stage is created with and the pipeline cache’s key on them, the shader module and layout a manifest packed under emit options gives and the variant a load-time emitter adds under the options the manifest records, the console’s events and the counts a submit resolves to, what a runtime given a sink prints and what one that prints does, a draw, a Resident both layers bind uploaded once, one device for both layers, a Texture as a call’s image, the bytes a texture’s read() copies and the numbers its readFloats() decodes for every format WebGPU has, and the order the queue runs a read and a frame in), and on WebGPU by the compile gate’s program tier (scripts/entry-calls-page.ts), which dispatches every compute entry of the examples from its module’s manifest and holds each written value to the call’s; and by the user journeys’ harness (journeys/_harness.mjs), which runs every journey’s compute and render run on WebGPU through typeshade/runtime as the packed tarball ships it, imported in the page with no bundler, its console lines and the counts submit() resolves to, the dropped count included, each held to the lines the sink was handed, and a run’s override values set by name on its pipeline (journeys/overrides/), each result held to the CPU oracle’s run of the module with the values as the overrides’ defaults; and by a program that loads an r32float level beside two textures a sampler reads (journeys/textures/), whose layouts WebGPU accepts; and by values above 1 and below 0 drawn into an rgba16float target and read back with readFloats() while a later frame is submitted (journeys/hdr-target/), whose numbers are held to the half floats the target stores; and by programs that compute in emulated doubles, packed at the defaults and under each level, parens and flavor (journeys/emit-options/), whose WGSL and bindings WebGPU accepts and whose results are held to plain JavaScript’s doubles; and by the engine journey (journeys/engine/), a host engine on the runtime’s public exports alone, two materials that share a camera and lights, a shadow pass, a render to texture and 60 frames, which the harness refuses on any other import or any WebGPU call of its own, and whose frames after the first make no GPU object, its last frame held to a reference computed in plain JavaScript.

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