ModuleDecl
On this page

ModuleDecl

Interface in IR

The whole-shader unit: everything a backend needs to emit a complete WGSL or GLSL ES 3.00 module, or to evaluate one on the CPU oracle.

import type { ModuleDecl } from 'typeshade'

The signature, the description and the examples come from the compiler's own source at commit 26de7be8.

Syntax

interface ModuleDecl {
readonly consts: readonly ConstDecl[];
readonly structs: readonly StructDecl[];
readonly bindings: readonly BindingDecl[];
readonly funcs: readonly FuncDecl[];
readonly vars?: readonly ModuleVarDecl[];
readonly externs?: readonly ExternVarDecl[];
readonly overrides?: readonly OverrideDecl[];
readonly enables?: readonly DeclarableCapability[];
readonly diagnostics?: readonly DiagnosticDirective[];
}

Description

The whole-shader unit: everything a backend needs to emit a complete WGSL or GLSL ES 3.00 module, or to evaluate one on the CPU oracle. It holds the four declaration arrays, consts, structs, bindings and funcs, plus the opt-in seams overrides, externs and enables. It is the argument every backend entry point takes, emitModule, emitGlslModule and compileModule, so it is the seam where authoring ends and backend-neutral emit begins.

Assemble one with module, which also derives structs, bindings and consts from the handles passed in uses. A hand-built object literal works too, since backends only ever read this shape, and gives up that convenience.

enables is where a module names the GPU features its emit needs, by neutral id, and its type is what keeps that list honest. It is readonly DeclarableCapability[], which is Capability minus every id derived from the module’s own shape — storageBuffer (a storage binding), compute (a @compute entry), msaaTextureLoad (a multisampled load), storageTexture, texture1d, textureCubeArray and textureGather (the binding or the call that needs each), bgra8unormStorage (a storage texture’s format) and packed4x8Dot (the packed 4x8 calls). Naming one of those here is a compile error, so it cannot read as a declaration that quietly does nothing. Each backend’s own capProfile table is the authority for the ids that remain: it maps a neutral id to that target’s directive and hostFeature, coverage is built from its keys, and a backend whose table has no row for a declared id fails closed at emit.

Examples

Example

import { module } from 'typeshade'
const m = module({ enables: ['floatRenderTarget'], structs: [VsOut.decl], funcs: [vs, fs] })

Instance properties

constsread only readonly ConstDecl[]
structsread only readonly StructDecl[]
bindingsread only readonly BindingDecl[]
funcsread only readonly FuncDecl[]
varsoptionalread only readonly ModuleVarDecl[]

Module-scope variables that are not resources (roadmap 0.2 item 5): the var<workgroup> and var<private> declarations. WGSL emits each between the structs and the bindings; GLSL ES 3.00 spells a private one as a plain global and has no form for workgroup memory. Absent or empty leaves the emitted source unchanged.

externsoptionalread only readonly ExternVarDecl[]

Host-provided globals, the declarations externVar returns. Each emits nothing and appears in reflect().requires, so a host can check the module’s expectations against what its prelude supplies. Absent or empty leaves the emitted source unchanged.

overridesoptionalread only readonly OverrideDecl[]

Pipeline specialization constants, the declarations overrideConst returns. Each emits a WGSL module-scope override and a GLSL #define, is reported by reflect so the host knows the WGSL constants dictionary and the GLSL define header, and reads as an opaque value in function bodies so the optimizer preserves the branches it guards for the driver to eliminate. Absent or empty means no override declaration and unchanged emitted source.

enablesoptionalread only readonly DeclarableCapability[]

The opt-in capabilities this module turns on, by neutral id, such as ['floatRenderTarget'] or ['f16']. Each folds into the module’s required caps, so a backend whose capProfile lacks a row fails closed with SD0030 naming the cap, and a backend whose row carries a directive emits it: enable f16; on WGSL, an #extension line on GLSL ES 3.00. A row with no directive is host-side only, the host activates it from reflect(m).requiredFeatures and the emitted bytes do not move. Absent or empty means no directive and unchanged emitted source.

The type is DeclarableCapability, which excludes all nine caps derived from the module’s shape — storageBuffer, compute, msaaTextureLoad, storageTexture, the three texture ids, and bgra8unormStorage and packed4x8Dot, derived from a binding’s format and from the calls; naming one here is a compile error. The caps derived from a @builtin(...) id instead (clipDistances, primitiveIndex, subgroups, §50) are not excluded: deriving and declaring fold into one set, so naming one is harmless.

diagnosticsoptionalread only readonly DiagnosticDirective[]

The WGSL diagnostic(<severity>, <rule>); directives this module carries (§54). One rule today: derivative_uniformity, whose default severity is error, so switching it off is how an author says “I know this sample is under a non-uniform branch and I want it anyway”. Module-scope, though the author writes it on an entry: WGSL’s @diagnostic on a function covers that function’s own body and not the functions it calls, and a sample is as often in a helper as in the entry.

The WGSL writer emits one line each, before every other directive. GLSL ES 3.00 has no equivalent and needs none — implicit derivatives in non-uniform control flow are undefined there rather than refused (glsl-es-300.txt:3751-3752) — so the GLSL text does not move. Absent or empty leaves the emitted source unchanged.

See also

Source

src/core/ir/nodes.ts, line 824, at commit 26de7be8

Edit this page Report a problem