Task 3 of 5

toArray() Is a Tollbooth

Here's the mental model that makes GPU code fast: computation on the card is nearly free — it's the transfers that cost. Every kernel that is not pipeline: true ends with an implicit download, and passing that array to the next kernel triggers a re-upload. A three-stage chain without pipelines pays the toll four times for one result.

The starter below is a fully working three-stage audio chain — normalize, gamma, smooth — and every hop goes through JavaScript. Your job isn't to fix the math. It's to fix the traffic: intermediates become pipeline kernels, and only the final stage returns plain numbers. The chain call itself shouldn't change by a single character.

Goal: refactor the chain so stages 1 and 2 keep their results on the GPU, the final stage returns numbers, and the output is bit-for-bit the same idea — just without the round trips.

Requirements

Hint 1 — where is the readback hiding?

There's no .toArray() in the starter, but the readbacks are still there: a non-pipeline kernel's awaited return value is the readback. Count them: normalize downloads, gamma re-uploads and downloads, smooth re-uploads.

Hint 2 — a two-line diff

Add pipeline: true to the settings of normalize and gamma. That's the entire refactor — the chain line already does the right thing once textures flow through it.

Same idea elsewhere

Profile any real CUDA or ROCm app and the widest bars are often cudaMemcpy DtoH/HtoD, not kernels; in WebGPU the same toll is mapAsync plus staging-buffer copies. "Keep data resident, read back once at the end" is performance rule number one on every GPU platform.

All tasks in Pipelines & Textures

  1. Flip On the Pipeline
  2. Chain Kernels, Skip the Round Trip
  3. toArray() Is a Tollbooth
  4. Feedback Loops: immutable Textures
  5. The Payoff: Photo to Screen, Zero Readbacks

This page is an interactive exercise — the editor, the GPU runner and your saved progress need JavaScript. The text above is the full brief.