Uniforms and buffers
A uniform binding is a struct, which the writer emits as a std140 block. A storage buffer has no form on this target at all, so a module with one is rewritten to read from a data texture before the capability gate runs.
layout(std140) uniform Block { float scale; vec3 tint;} u;declare const u: uniform<Block>The class is the block and the declare is the instance. The field order is the layout.
uniform binding 'scale' must be a struct (a std140 UBO block)
declare const scale: uniform<f32>A default-block uniform set through glUniform* has no spelling here, so a uniform binding of a bare scalar, vector or matrix reaches WebGPU alone.
uniform sampler2D src;declare const src: storage<array<f32>>The buffer becomes a data texture, and the host uploads the same numbers as texels.
float _sfetch(sampler2D t, int i) {src[i32(uv.x)]An index into the buffer becomes a fetch through this function, which the writer defines in the modules that call it.
#define tint 0.85const tint: override<f32> = 0.85A specialization constant has no GLSL form, so the default is written as a preprocessor substitution the host can override before it compiles the stage.
precision highp float;Nothing to write.
The writer puts the qualifier at the top of every stage it emits, and the floatPrecision option decides whether the float line reads highp or mediump. The integer line stays highp, since a read back through a data texture needs the whole range.
Varyings
A value that travels from the vertex stage to the fragment stage is a @location(n) field on both sides. This target links them by name and WebGPU by number, so the field name is what has to match in the emitted GLSL.
out vec2 uv;@location(0) uv: vec2Written on the field of the struct a vertex entry returns.
in vec2 uv;@location(0) uv: vec2Written on the fragment entry parameter that reads it, under the same name.
layout(location = 0) out vec4 _ret;: vec4A bare fragment return takes location 0, and the writer names the output itself.
Extensions and capabilities
An #extension line is one half of a GPU feature and the host's getExtension call is the other. The profile for this target has 4 rows, and one of them puts a directive in the source; everything with no row at all fails the module closed here before any text is written.
floatRenderTarget None. The host turns the extension on before it links the program.
EXT_color_buffer_float float32Blend None. The host turns the extension on before it links the program.
EXT_float_blend float32Filterable None. The host turns the extension on before it links the program.
OES_texture_float_linear multiview #extension GL_OVR_multiview2 : requireOVR_multiview2 A "use typeshade" file has no spelling for these four. "enable ..." takes WGSL extension names and none of the four is one, so a module that needs one is assembled with module({ enables: [...] }) on the fn() surface. What a module's shape implies, such as a storage binding, a compute entry or a @builtin("clip_distances"), is derived from the file, and none of those has a row here.