How GPU.js Infers Output Grid Dimensionality
This article explains how GPU.js detects and handles the
dimensionality of the execution grid defined by the
setOutput() method. By analyzing the structure and length
of the argument provided—whether an array or an object—GPU.js determines
if the kernel should execute in one, two, or three dimensions. It
translates these parameters into WebGL texture bounds and injects
coordinate-mapping mathematics into the compiled fragment shader to
expose this.thread.x, this.thread.y, and
this.thread.z to the developer.
Array-Based Dimensionality Inference
The most common way to define the output shape in GPU.js is via an
array of integers. GPU.js directly evaluates the length of
this array to infer the grid's dimensions:
- 1D Grid (
[x]): An array with one value defines a one-dimensional array of threads of lengthx. GPU.js sets the thread boundary such that onlythis.thread.xspans from0tox - 1, whileyandzdefault to 0. - 2D Grid (
[x, y]): An array with two values indicates a two-dimensional matrix. GPU.js designates the first element as the width (x) and the second as the height (y). - 3D Grid (
[x, y, z]): An array with three values defines a three-dimensional volume with width (x), height (y), and depth (z).
Object-Based Dimensionality Inference
GPU.js also accepts an object literal (e.g.,
{ x: 512, y: 512 }). In this case, dimensionality is
inferred by checking for the presence of specific coordinate
properties:
- If only
xis present, it is inferred as 1D. - If
xandyare present, it is treated as 2D. - If
x,y, andzare all provided, it is treated as 3D.
WebGL Texture Flattening and Coordinate Deconstruction
Because standard WebGL 1.0 and WebGL 2.0 fragment shaders render onto two-dimensional framebuffers (textures), GPU.js must adapt 1D and 3D specifications to fit 2D hardware memory:
- 1D Mapping: For large 1D vectors that exceed the GPU's maximum texture width limit, GPU.js wraps the 1D dimension across a 2D surface and computes the single linear index inside the shader using modulo and division logic against the texture width.
- 2D Mapping: A 2D output maps directly to standard
2D texture coordinates (
gl_FragCoord.xandgl_FragCoord.y). - 3D Mapping: For 3D outputs, GPU.js packs the third
dimension (
z) into a tiled 2D sheet (or calculates a virtual 3D coordinate space across the 2D texture).
During compilation, GPU.js generates specialized GLSL boilerplate
prepended to your kernel code. It uses the inferred dimensions to
calculate real-time values for this.thread.x,
this.thread.y, and this.thread.z from the
fragment's 2D canvas coordinates, ensuring seamless access to
multi-dimensional indices regardless of the underlying hardware
layout.