Signal

WebGL parameters

Captures the set of WebGL parameter caps, shader precision ranges, and extension names that the browser reports for the current GPU — values controlled by the engine, not solely the GPU driver.

Tier 1 engine src/signals/webgl.ts

What it measures

The signal queries three categories of WebGL data: eight capability limit parameters (such as MAX_TEXTURE_SIZE and MAX_VIEWPORT_DIMS), six shader precision format results (vertex and fragment shader, low/medium/high float), and the full sorted list of supported extension names. Together these 15 elements form the hash input.

Although the raw GPU hardware determines physical capabilities, browser engines apply their own caps and ship different subsets of optional extensions. Chrome's ANGLE translation layer, Firefox's native OpenGL path, and Safari's Metal backend each report different parameter sets for the same GPU.

How it's collected

The collector creates a 1x1 WebGL context (WebGL2 preferred, WebGL1 fallback) using OffscreenCanvas if available, otherwise a hidden DOM canvas. It reads the 8 GL parameter constants via getParameter, queries 6 shader precision combinations via getShaderPrecisionFormat (vertex and fragment shader crossed with LOW_FLOAT, MEDIUM_FLOAT, and HIGH_FLOAT), and calls getSupportedExtensions. The extension list is sorted alphabetically and joined with commas into a single string before being appended to the parts array.

The 15 parts are joined with the pipe delimiter and hashed with xxHash64. The WEBGL_lose_context extension is called after collection on both canvas paths to release GPU resources. Cleanup errors are silently swallowed.

text
GL_PARAMS (8, in order):
  MAX_TEXTURE_SIZE
  MAX_RENDERBUFFER_SIZE
  MAX_VIEWPORT_DIMS
  MAX_VERTEX_ATTRIBS
  MAX_VARYING_VECTORS
  MAX_FRAGMENT_UNIFORM_VECTORS
  ALIASED_LINE_WIDTH_RANGE
  ALIASED_POINT_SIZE_RANGE

SHADER_PRECISION (6, in order):
  VERTEX_SHADER   x [LOW_FLOAT, MEDIUM_FLOAT, HIGH_FLOAT]
  FRAGMENT_SHADER x [LOW_FLOAT, MEDIUM_FLOAT, HIGH_FLOAT]
  Each: rangeMin,rangeMax,precision

EXTENSIONS (1):
  getSupportedExtensions() sorted alphabetically, joined with ','

concatenated = parts.join('|')  // 15 parts, 14 pipe separators
hash = xxHash64(concatenated) -> 16-char hex

The 15-part hash construction for webgl_params

Confidence rules

ConfidenceTrigger
normalWebGL context obtained and data collected
absentNo WebGL context available, or top-level catch fires

Why engine-bound

Browser engines apply their own policy caps on many WebGL parameters independent of the GPU driver. MAX_TEXTURE_SIZE can be limited by policy, extension availability varies between Blink and WebKit, and shader precision format values can differ between Chrome's ANGLE translation layer and Firefox's native OpenGL path. The extension list is especially engine-discriminating because browsers ship different subsets of optional WebGL extensions.

Because the reported values are shaped by the engine, not exclusively by the GPU, the hash differs between Chrome and Firefox on identical hardware. This makes webgl_params a strong per-browser discriminator and a complement to the hardware-bound webgl_gpu_identity signal.

Things worth knowing

  • Float32Array and Int32Array parameter values are serialised as Array.from(value).join(',') before joining into the parts array.
  • The value field returned to callers contains paramCount and extensionCount as integers — not the raw parameter data.
  • Collection is synchronous (no timeouts, no yield points). Typical timing is 5-20 ms.
  • WEBGL_debug_renderer_info is not used by this collector; that extension belongs exclusively to webgl_gpu_identity.