Course outline
A Triangle in Raw WebGPU
In one line
WebGPU draws the same triangle with other ideas: ask for an adapter and a device (both asynchronous), write both shaders in one WGSL module, fix every setting in advance in a pipeline, record commands into an encoder, and submit them at once. Errors are checked and reported in detail.
Think of it like this
A restaurant kitchen. WebGL is a cook shouting each step as it happens. WebGPU writes the recipe card first (the pipeline), puts the ingredients on a tray (bind groups), writes the orders on a ticket (the command encoder) and hands the ticket over once (submit).
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- adapter
- A GPU the browser is willing to use (
GPUAdapter);requestAdapter()can return null. - device
- Your connection to an adapter (
GPUDevice); every buffer, texture and pipeline comes from it. - WGSL
- WebGPU Shading Language, the language of WebGPU shaders.
- render pipeline
- An immutable object with the shaders and fixed settings (formats, topology, blending) for one kind of draw.
- command encoder
- Records GPU commands into a list you submit later.
- render pass
- A recorded section that draws into a set of textures, with a clear and store rule for each.
Step by step
01Run it in a WebGPU browser
The status bar says WebGPU · raw and the console drew one triangle with WebGPU, canvas format bgra8unorm (or rgba8unorm). Without WebGPU the page says why: no navigator.gpu…, or requestAdapter() returned null… as in this site's checker, where Chrome also prints its own warning, No available adapters.
02Mind the byte order
On a bgra8unorm canvas, a raw copy of the middle pixel reads 44, 107, 255, 255: Lumen orange with blue first. Tools that read pixels back must check the format.
03Count the promises
requestAdapter, requestDevice and onSubmittedWorkDone are asynchronous: the browser may have to start or choose a GPU process. Everything after requestDevice is called synchronously.
04Read a WGSL error
The second example writes vec4f(1.0, 0.1, 0.05), three numbers for a four-number type. getCompilationInfo() gives error at line 2, column 10: no matching constructor for 'vec4<f32>(abstract-float, abstract-float, abstract-float)' (the full message then lists all 20 constructors it could have meant). Using the module later raises [Invalid ShaderModule "glow shader"] is invalid due to a previous error.: your label appears in the message.
Try it yourself
- 1
Change the topology
In the first example, change
"triangle-list"to"line-strip". With WebGPU you see two orange lines (the three points joined in order, not closed). The pipeline, not the draw call, decides how vertices join. - 2
Fix the WGSL
In the second example, write
vec4f(1.0, 0.1, 0.05, 1.0).getCompilationInfo()is now silent, and the next error appears:Entry point ""vs"" doesn't exist in the shader module [ShaderModule "glow shader"].(Chrome doubles the quotes). Each fix reveals the next bug, by name.
Code & diagrams
No `output` is checked: it depends on the browser. With WebGPU it prints `drew one triangle with WebGPU, canvas format bgra8unorm` (or `rgba8unorm`); without, why not.
Console
Run the scene to see its console.With WebGPU: the `uncaptured error event` line, `error at line 2, column 10: no matching constructor for 'vec4<f32>(…)'`, then `uncaptured error event: [Invalid ShaderModule "glow shader"] is invalid due to a previous error.` Without, it says so.
Preview
Console
Nothing logged yet.Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Forget await on requestAdapter
In the first example, remove await before navigator.gpu.requestAdapter().
Myth vs fact
Myth
If navigator.gpu exists, WebGPU works.
Fact
requestAdapter() can still return null: a blocked driver, a disabled GPU, a headless browser. This page's own test browser is that case.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
Label everything (
label: "glow pipeline"). Chrome's Dawn and Firefox's wgpu put labels into error messages; unlabeled objects appear as[Buffer (unlabeled)](Topic 14.4). - ▸
WebGPU has no
getError(). Errors go to the device asynchronously: wrap risky code inpushErrorScope("validation")/popErrorScope(), and listen foruncapturederrorfor everything else.
Remember this
- 1
The problem this solves: WebGL copies 1990s OpenGL: one global state, checked call by call. Modern GPU APIs (Vulkan, Metal, Direct3D 12) use pre-built pipelines and recorded command lists. WebGPU brings that to the web: less CPU work per draw, compute shaders, precise errors.
- 2
Adapter and device.
navigator.gpuexists only where WebGPU does.await navigator.gpu.requestAdapter()returns aGPUAdapter(a GPU the browser will use) or **null**: a blocklisted driver, or this page's test browser.await adapter.requestDevice()gives theGPUDeviceeverything is created from. A device can be lost (driver crash):device.lostresolves with the reason. - 3
The canvas.
getContext("webgpu"), thencontext.configure({ device, format })withnavigator.gpu.getPreferredCanvasFormat(). On most desktops that isbgra8unorm, blue first in memory: the triangle's middle pixel, read back as raw bytes, is44, 107, 255, 255: the same orange, stored B, G, R, A. - 4
WGSL and the pipeline. One WGSL module holds both shaders as
@vertexand@fragmentfunctions. This triangle needs no vertex buffer: the vertex shader makes the corners from@builtin(vertex_index).createRenderPipelinefixes the shaders, output format and primitive type in one immutable object, checked once when it is made. WebGL's per-draw switches become one object you can't half-set. - 5
Record, then submit.
createCommandEncoder(),beginRenderPass(which texture, how to clear),setPipeline,draw(3),end(): all recorded, not run.encoder.finish()closes the list anddevice.queue.submit()sends it; the GPU runs it later.
Explain it without notes
List the objects you create to draw one triangle with WebGPU, in order, and what each is for.
What can requestAdapter() return, and how should a page react?
Practice
Clear to Lumen blue instead of the stage colour.
Print the adapter's largest texture size and largest uniform binding.
Done when you can
You can draw a triangle with raw WebGPU
You check navigator.gpu and the adapter, and await every promise
You read WGSL errors with getCompilationInfo
You label your WebGPU objects