Course outline
The GPU and Why It Is Fast
In one line
The GPU is a chip with thousands of small workers that all run the same short program on different data at once. That suits 3D, where the same steps repeat for every corner and every pixel, and it makes the number of draw calls a cost of its own.
Think of it like this
A CPU is like one very clever chef who can cook any dish but one at a time. A GPU is like a huge kitchen with a thousand cooks who can each do only a few simple steps, all following the same card. To make one fancy dish, the chef is better. To make a thousand identical sandwiches at once, the kitchen wins by far.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- GPU
- Graphics processing unit: a chip with thousands of small cores that run one program on huge amounts of data at the same time.
- shader
- A small program that runs on the GPU. Vertex shaders place corners; fragment shaders colour pixels.
- draw call
- One instruction to the GPU to draw one mesh with one material. Each costs the CPU some time.
- driver
- Software from the GPU maker that turns the browser's graphics commands into the chip's own commands.
- instancing
- Drawing many copies of one shape in a single draw call, each copy with its own position.
- CPU bound / GPU bound
- Which side is the slower one: the CPU preparing the frame, or the GPU drawing it.
Step by step
01Your code asks three.js
You call renderer.render(scene, camera). three.js walks the scene, throws away meshes the camera can't see, sorts the rest, and for each mesh prepares its data and its shader program.
02The browser and driver pass it on
For each mesh three.js makes WebGL calls: use this program, bind these buffers, set these values, draw. The browser validates each call (a web page must never crash the machine) and the driver turns it into GPU commands. This chain is the real cost of a draw call.
03The GPU runs the vertex program
The GPU starts the vertex shader on many vertices at once. Each run reads one vertex's data and returns one position. No run can see the others, and that is what lets thousands run side by side.
04Then the fragment program
After the triangles are turned into pixels (Topic 1.4), the fragment shader runs once for each covered pixel, again in parallel, and returns a colour.
05The picture is shown
The finished pixels are in the canvas's buffer. The browser puts that buffer on the page. Then the next frame begins, about 16 milliseconds later on a 60 Hz screen.
Try it yourself
- 1
Fewer boxes, fewer trips
In "The same triangles in 400 trips", change
N = 400toN = 100. The first line becomesdraw calls 100 | triangles 1200, and the other two stay at 1 draw call. The cost of separate meshes grows with the number of meshes; the cost of the single mesh does not. - 2
Change the wave
In the shader example, change
p.z += 0.25 * sin(p.x * 4.0 + uTime);top.y += 0.25 * sin(p.x * 4.0 + uTime);. The wave now moves the corners up and down instead of towards the camera, and the colours stay the same, because only the vertex program changed.
Code & diagrams
Three ways to draw 400 boxes. Merging gives one mesh that can no longer move its boxes separately; InstancedMesh keeps one position per box.
Console
Run the scene to see its console.Expected console output
400 separate meshes draw calls 400 | triangles 4800
1 merged mesh draw calls 1 | triangles 4800
1 InstancedMesh draw calls 1 | triangles 4800The wave is the vertex program, the colours are the fragment program. Look at the status bar: 1 draw call, 1 shader program.
Console
Run the scene to see its console.Expected console output
corners sent through the vertex program each frame: 861
triangles: 1600, draw calls: 1, shader programs: 1Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
A typo in a shader
In the shader example, delete the semicolon at the end of the gl_FragColor = ... line.
Myth vs fact
Myth
The GPU is a faster CPU.
Fact
It is slower at any single task and far faster at doing the same task on thousands of items at once. Code with lots of different branches, or steps that need the previous result, runs badly on it.
Myth
Fewer triangles always means a faster scene.
Fact
A scene with 400 two-triangle meshes can be slower than one with a million triangles in one mesh, because each draw call costs the CPU. Triangles, pixels and draw calls are three separate costs.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
Draw-call cost is mostly CPU and driver work, so it grows with the number of meshes, materials and state changes, and it is hit harder by WebGL than by WebGPU, which lets you record the commands once and replay them (Phase 13 and Phase 14). Even so, the rule of thumb holds on both: keep a phone to roughly a hundred or a few hundred draw calls per frame (Topic 17.2 shows where that number comes from and how to measure your own).
- ▸
GPUs run shader code in lock-step groups of threads (called warps or wavefronts, 32 or 64 wide, depending on the chip). If threads in a group take different branches of an
if, both branches run for all of them. That is why shader code avoids branching on per-pixel data. - ▸
On integrated and mobile GPUs the CPU and the GPU share one memory, so uploading a buffer is cheaper than on a desktop card with its own memory. A mobile GPU also renders in small tiles to save memory bandwidth, which makes extra full-screen passes (Phase 15) especially costly there.
Remember this
- 1
The problem this solves: 3D needs the same small calculation for millions of numbers on every frame: move this corner, colour that pixel. A single fast processor doing them one after another would take far too long. Knowing how the GPU is organised explains why some code is free and some is expensive.
- 2
CPU and GPU. The CPU (central processing unit) runs your JavaScript and the browser. It has a few powerful cores, good at varied, branching work. The GPU (graphics processing unit) has hundreds to thousands of simpler cores, built to run one small program over huge lists of data in parallel. On a phone, both are on one chip and share memory; on a gaming PC the GPU is a separate card with its own memory.
- 3
Two tiny programs. In the pipeline (Topic 1.4) you give the GPU two short programs called shaders. The vertex shader runs once for every vertex and decides where it lands on the screen. The fragment shader runs once for every pixel a triangle covers and decides its colour. The GPU runs the same program on many vertices or pixels at the same time. The second live example shows both, written in GLSL (the shader language of WebGL).
- 4
Who does what. Your JavaScript calls three.js. three.js calls the browser's WebGL (or WebGPU) functions. The browser checks them for safety and passes them to the graphics driver, software from the GPU maker that turns them into the chip's own commands. The GPU runs them. Your code never touches the GPU directly, and every step costs a little time.
- 5
Draw calls. One draw call is one instruction "draw this mesh with this material". Each one needs the CPU to set up state, check things and talk to the driver, so a draw call has a cost even when the mesh has two triangles. A scene of 400 small separate meshes can be slower than a single mesh of 400 times the triangles. The first live example sends the same 4,800 triangles in 400 trips and in 1.
- 6
Where the time goes. A frame can be slow for two different reasons. If the CPU takes too long preparing (too many draw calls, too much JavaScript) the scene is CPU bound. If the GPU takes too long colouring (too many triangles or pixels) it is GPU bound. The fix is different for each, which is why the status bar shows draw calls, triangles and the pixel ratio side by side.
Explain it without notes
Why can a scene with 5,000 small separate meshes run slower than a scene with one 5-million-triangle mesh?
What are the vertex shader and the fragment shader, and how many times does each run for one triangle?
Practice
A scene shows 1,000 identical trees. Which technique keeps it at one draw call, and what must you give up?
In TRIPS, write the one-line change that makes the instanced version draw only the first 100 boxes.
Done when you can
Explain the difference between a CPU and a GPU in one picture
Say what the vertex and fragment shaders do and how often each runs
Define a draw call and say why many small ones are slow
Tell a CPU-bound frame from a GPU-bound one