GPU.js Built-In Thread Coordinates Explained
GPU.js abstracts WebGL and compute shaders into JavaScript, providing
built-in context variables that serve the same purpose as GLSL
identifiers like gl_FragCoord and
gl_GlobalInvocationID. This article details how GPU.js
exposes thread coordinates via the this.thread object, how
these variables map to native shader execution indices, and how to
utilize them within kernel functions.
The Equivalent:
this.thread
In GPU.js, the execution index is accessed through the execution
context using this.thread. Depending on whether your kernel
output is 1D, 2D, or 3D, GPU.js populates the following integer
properties:
this.thread.x: The index along the horizontal dimension.this.thread.y: The index along the vertical dimension (for 2D and 3D outputs).this.thread.z: The index along the depth dimension (for 3D outputs).
These properties serve as the functional equivalent to
gl_GlobalInvocationID in compute shaders and
gl_FragCoord in fragment-shader-based GPGPU
implementations.
Comparison to
gl_GlobalInvocationID
In WebGPU or OpenGL compute shaders,
gl_GlobalInvocationID represents the unique global
work-item ID within the dispatch grid (uvec3). GPU.js was
designed with this model in mind:
gl_GlobalInvocationID.xdirectly corresponds tothis.thread.x.gl_GlobalInvocationID.ydirectly corresponds tothis.thread.y.gl_GlobalInvocationID.zdirectly corresponds tothis.thread.z.
Like gl_GlobalInvocationID, this.thread
values are 0-indexed integers representing the discrete work item
currently being processed.
Comparison to
gl_FragCoord
When using WebGL 1 or 2 fragment shaders for compute, developers
traditionally use gl_FragCoord.xy to locate the current
pixel. However, gl_FragCoord introduces minor
differences:
- Floating-point offsets:
gl_FragCoordprovides window-relative coordinates centered at pixel halves (e.g.,0.5,1.5,2.5), requiring explicitfloor()operations to convert to integer indices. - Y-axis orientation: In raw WebGL,
gl_FragCoordstarts at the bottom-left corner.
GPU.js handles this mapping automatically. Under the hood, when
GPU.js compiles a kernel to a WebGL fragment shader, it calculates
discrete zero-based indices from internal texture coordinates, exposing
clean integers via this.thread rather than raw fragment
floats.
Companion Variable:
this.output
In addition to the thread coordinate, GPU.js provides the grid
dimensions via this.output:
this.output.x: Total width of the output array.this.output.y: Total height of the output array.this.output.z: Total depth of the output array.
This is analogous to obtaining texture dimensions via
textureSize() or calculating the total invocation bounds
(gl_NumWorkGroups * gl_WorkGroupSize) in GLSL.
Example Usage
const gpu = new GPU();
const kernel = gpu.createKernel(function() {
// this.thread.x and this.thread.y identify the invocation
// this.output.x provides the maximum width
return this.thread.x + (this.thread.y * this.output.x);
}).setOutput([512, 512]);
const result = kernel();Through this.thread and this.output, GPU.js
provides a clean, native JavaScript interface for spatial thread mapping
without requiring manual GLSL built-in parsing.