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.
"use typeshade";
class Clip { @builtin("position") pos: vec4;}
class Color { @location(0) color: vec4;}
@vertexexport 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.) };}
@fragmentexport 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.
struct Clip { @builtin(position) pos: vec4<f32>,}
struct Color { @location(0) color: vec4<f32>,}
@vertexfn 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));}
@fragmentfn 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.
#version 300 esprecision 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);}#version 300 esprecision 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 differs | WGSL | GLSL ES 3.00 |
|---|---|---|
| Compute stages | A @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. |
| Precision | A type carries its own width, so the program declares nothing. | The program opens with a default precision for floating-point and integer values. |
| Builtin inputs | A 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 outputs | A stage returns a struct whose fields carry their locations. | A stage writes to declared out variables, and the position goes to the reserved one. |
| Extensions | A 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
- WGSL specification defines the first of the two targets.
- GLSL ES 3.00 specification and the WebGL2 specification define the second.
- MDN WebGPU API and MDN WebGL2RenderingContext show how a host hands each of them to a driver.
- Functions in the language reference gives each builtin with the WGSL and GLSL ES 3.00 text the compiler writes for it, and Types does the same for every type.
Next: Examples, where every example in the compiler’s registry names the targets it emits.