a Direct3D 11 WebGL renderer reports the uniform limits ANGLE fixes for its vendor
When the unmasked renderer is ANGLE Direct3D 11: MAX_VERTEX_UNIFORM_VECTORS is 4095 for an NVIDIA renderer and 4096 for any other vendor, MAX_FRAGMENT_UNIFORM_VECTORS is 1024, and at shader model 5 MAX_VARYING_VECTORS is 30 — in WebGL 1 and WebGL 2. N/A for other backends, other platforms and masked renderers (severity: warn).
What a detector infers
Chrome, Edge, Brave and Firefox on Windows render WebGL through ANGLE's Direct3D 11 backend, and that backend does not ask the driver for its shader limits: it sets them from the Direct3D feature level.
MAX_FRAGMENT_UNIFORM_VECTORS is hard-coded to 1024, MAX_VARYING_VECTORS is the 32 D3D11 output registers minus the two ANGLE reserves (30 at feature level 11, which is what "vs_5_0 ps_5_0" in the renderer means), and MAX_VERTEX_UNIFORM_VECTORS is the 4096-entry constant buffer — minus one register on NVIDIA only, where ANGLE turns on a driver workaround that skips register zero (renderer11_utils.cpp: skipVSConstantRegisterZero is conditioned on isNvidia).
So an NVIDIA renderer reports 4095 and every other vendor 4096. The vendor in "ANGLE (<vendor>, …" is ANGLE's name for the same PCI vendor id the workaround tests, and Firefox's renderer sanitizer copies it verbatim, so the rule holds in both engines. A renderer string rewritten to another vendor, with the limits left to the real adapter, is off by exactly one.
How to resolve it
Take the renderer string and the limits from the same adapter. A persona that names a GPU from a different vendor than the real one has to report that vendor's MAX_VERTEX_UNIFORM_VECTORS (4095 for NVIDIA, 4096 otherwise); leaving it to the real driver leaks the real vendor. The simpler fix is to pick personas from the host's own GPU vendor.
Read in the wild by
Clearcote (measured)
Measured while establishing ground truth for this row. Clearcote r27 on an NVIDIA host, with its default persona naming an Intel UHD Graphics 770, reports MAX_VERTEX_UNIFORM_VECTORS 4095 — NVIDIA's value — because persona limits are clamped to the real driver's. Recorded as a known gap for a persona whose GPU vendor differs from the host's.
Same Windows machine (GeForce RTX 3070): Chrome, Edge, Brave 153 and Firefox 144 report 4095 / 1024 / 30 under an NVIDIA renderer. Camoufox's and CloakBrowser's Intel personas report 4096 / 1024 / 30. Clearcote r27 under "ANGLE (Intel, Intel(R) UHD Graphics 770 (0xA780) Direct3D11 vs_5_0 ps_5_0, D3D11)": 4095 / 1024 / 30.
clearcotelabs.com/auditEvery attribution traces to a published artifact. See the sources and their limits.
Nearby checks in Render & GPU
- the WebGL renderer string is one ANGLE's Direct3D 11 backend can print
webgl-renderer-angle-formatOn Windows, Chrome's WebGL renderer string is assembled by ANGLE's Direct3D 11 backend, not typed by anyone: the adapter's description, then… - WebGL exposes a full parameter table + UNMASKED vendor/renderer
webgl-param-tableBeyond the two headline strings, a WebGL context answers getParameter for dozens of driver-specific limits. - WebGL parameters return the JavaScript types the specification assigns them
webgl-param-value-typesgetParameter does not return loose values: the WebGL specification fixes the JavaScript TYPE of each one. - the anisotropy limit reads as a number once its WebGL extension is enabled
webgl-anisotropy-after-extensionEXT_texture_filter_anisotropic adds exactly one parameter to getParameter, MAX_TEXTURE_MAX_ANISOTROPY_EXT, and the extension guarantees it… - WebGL vendor/renderer identical in a Worker
webgl-worker-vs-mainThe audit reads UNMASKED_VENDOR and UNMASKED_RENDERER on the main thread, then spawns a dedicated Worker that builds its own WebGL context… - masked WebGL VENDOR matches the engine
webgl-engine-vendorThis check reads the plain gl.getParameter(gl.VENDOR) — the masked value, not the debug extension's unmasked GPU string. - WebGL1 and WebGL2 report the same UNMASKED GPU
webgl1-webgl2-coherenceThe check creates a WebGL1 context and a WebGL2 context and reads UNMASKED_VENDOR_WEBGL / UNMASKED_RENDERER_WEBGL from each through the… - canvas readback is not noise-injected (1×1 probe)
canvas-tamperThe probe fills a single pixel with pure black on a 1x1 canvas and reads it straight back with getImageData.
Clearcote is a browser built for fingerprint coherence
It is a Chromium fork, maintained by the same people who wrote this reference. It ships as a compiled browser rather than as a stealth script injected into someone else's — which is a description of how it is built, and is not an argument about how it behaves on this check.
This audit takes no position on how Clearcote scores on Render & GPU checks, on this one, or anywhere else. It has no baseline corpus of other people's fingerprints to rank you against and no vendor scoreboard — nearly every check is self-referential, asking one browser the same question through two independent APIs and reporting whether both answers can be true at once. It runs identically on any browser, including ours. Run it on yours and read the result yourself.
See the other checks in Render & GPU — the family webgl-d3d11-limits-vs-vendor belongs to.
