WGSL and GLSL
On this page

WGSL and GLSL ES 3.00

One `"use typeshade"` file reaches WebGPU as WGSL and WebGL2 as GLSL ES 3.00. The blocks on this page are compiled while the page is built, from the file above them, by the compiler pinned at 26de7be8.

The source

A triangle, with a vertex entry that places it and a fragment entry that colours it. The two structs give each stage its output shape.

hello.shade.ts
"use typeshade";
class Clip {
@builtin("position") pos: vec4;
}
class Color {
@location(0) color: vec4;
}
@vertex
export function vs(@builtin("vertex_index") i: u32): Clip {
const x = i === 1 ? 0.8 : i === 2 ? 0. : -0.8;
const y = i === 2 ? 0.8 : -0.8;
return { pos: vec4(x, y, 0., 1.) };
}
@fragment
export function fs(): Color {
return { color: vec4(1., 0., 0., 1.) };
}

WGSL

WGSL is the language a WebGPU device accepts, and one module holds every stage. The structs survive as structs, each entry point keeps its stage attribute, and the builtin input stays an attribute on the parameter that receives it.

The emitted WGSL module
struct Clip {
@builtin(position) pos: vec4<f32>,
}
struct Color {
@location(0) color: vec4<f32>,
}
@vertex
fn vs(@builtin(vertex_index) i: u32) -> Clip {
let _cse0 = (i == 2u);
let x = select(select(-0.8, 0.0, _cse0), 0.8, (i == 1u));
let y = select(-0.8, 0.8, _cse0);
return Clip(vec4<f32>(x, y, 0.0, 1.0));
}
@fragment
fn fs() -> Color {
return Color(vec4<f32>(1.0, 0.0, 0.0, 1.0));
}

GLSL ES 3.00

A WebGL2 program is linked from one vertex shader and one fragment shader, so the compiler emits a separate program for each stage. Each one opens with its version line and its default precision, the vertex index arrives under the name the language reserves for it, and the fragment output becomes a declared out variable.

The emitted GLSL ES 3.00 vertex shader
#version 300 es
precision highp float;
precision highp int;
void main() {
uint i = uint(gl_VertexID);
bool _cse0 = (i == 2u);
float x = ((i == 1u) ? 0.8 : (_cse0 ? 0.0 : -0.8));
float y = (_cse0 ? 0.8 : -0.8);
gl_Position = vec4(x, y, 0.0, 1.0);
}
The emitted GLSL ES 3.00 fragment shader
#version 300 es
precision highp float;
precision highp int;
layout(location = 0) out vec4 color;
void main() {
color = vec4(1.0, 0.0, 0.0, 1.0);
}

Where the targets differ

Each difference is named by the page of the guide that handles it. Where the two disagree, WGSL defines what a construct means, and GLSL ES 3.00 is a target the compiler writes to (Rule 1.2no test checks this yet).

What differsWGSLGLSL ES 3.00
Compute stagesA @compute entry emits a compute shader carrying its workgroup size.The target has no compute stage, so a module that declares one emits WGSL alone.
PrecisionA type carries its own width, so the program declares nothing.The program opens with a default precision for floating-point and integer values.
Builtin inputsA builtin stays an attribute on the parameter that receives it.A builtin becomes the name the language reserves for it, and the parameter goes away.
Stage outputsA stage returns a struct whose fields carry their locations.A stage writes to declared out variables, and the position goes to the reserved one.
ExtensionsA GPU feature is turned on by a declaration at the top of the module.A GPU feature is turned on by a preprocessor line, and the host asks the context for the matching extension.

Further reading

Next: Examples, where every example in the compiler’s registry names the targets it emits.

Edit this page Report a problem