# Shape the Output: 2D

*Task 2 of 6 · [Data In, Data Out](https://gpu.rocks/learn/data-in-data-out-42b68d01.md) · GPU.js Learn*

`output` is not just a size — it's a **shape**.
`output: [16]` launches a line of 16 threads; `output: [16, 16]`
launches a 16×16 *grid* of 256 threads, and each one gets two coordinates:
`this.thread.x` (column) and `this.thread.y` (row).

The result comes back with the same shape: a 2D kernel returns an array of rows,
indexed `result[y][x]`.

## Figures

- **output is a shape — [6] is a line, [4, 4] is rows of rows**

## Goal

**Goal:** turn the kernel into a 16×16 grid that computes a
multiplication table — cell `[y][x]` holds `(x + 1) * (y + 1)`.

## Requirements

- Change `output` to a 16×16 grid: `[16, 16]`
- Use both `this.thread.x` and `this.thread.y`
- Return `(x + 1) * (y + 1)` so row 1 counts 1…16, row 2 counts 2…32, …

## Hint 1 — reading the shape

`output: [width, height]` — x runs over `width`,
y over `height`. The returned value lands in `result[y][x]`.

## Same idea elsewhere

2D and 3D launch grids are first-class everywhere: CUDA's `dim3`
grid/block sizes, WebGPU's `workgroup_size` and dispatch dimensions. Choosing
the launch shape to match the output shape is the same design move on every platform.

## Starter code

```js
// output: [width, height] — gpu.js hands you a whole grid of threads.
const gpu = new GPU({ mode });

const table = gpu.createKernel(function () {
  // TODO: use BOTH this.thread.x and this.thread.y
  // and return (x + 1) * (y + 1).
  return this.thread.x + 1;
}, {
  // TODO: make this a 16×16 grid, not a 16-cell line
  output: [16],
});

const result = await table();
console.log('rows:', result.length);
console.log('row 0:', result[0]);
```

---

Interactive version: https://gpu.rocks/learn/data-in-data-out-42b68d01/2

[Previous task](https://gpu.rocks/learn/data-in-data-out-42b68d01/1.md) · [Next task](https://gpu.rocks/learn/data-in-data-out-42b68d01/3.md)
