WebGPU Limits and Features

Why This Matters

WebGPU devices have default limits (guaranteed minimums) that may be lower than what your application needs. For example, the default maxBufferSize is 256 MiB — if you create a large compute buffer, you’ll silently get errors unless you request a higher limit. Similarly, optional features like float32-filterable must be explicitly enabled.

Limits

Limits define numeric constraints on resources. Every WebGPU implementation guarantees a set of minimum values, but most GPUs support much higher limits.

Common limits you may need to increase:

Limit Default When to Increase
maxBufferSize 268435456 (256 MiB) Large storage/vertex buffers
maxStorageBufferBindingSize 134217728 (128 MiB) Large compute storage buffers
maxStorageBuffersPerShaderStage 8 Many storage buffers in one shader
maxComputeWorkgroupSizeX 128 Large workgroup dimensions
maxComputeInvocationsPerWorkgroup 128 Dense compute workgroups
maxColorAttachments 8 Many render targets

Querying Adapter Limits

const adapter = await navigator.gpu?.requestAdapter();
console.log(adapter.limits.maxBufferSize);
console.log(adapter.limits.maxStorageBufferBindingSize);

Requesting Increased Limits

You must request higher limits when creating the device — otherwise you get the defaults, not the adapter’s maximums.

Raw WebGPU:

const adapter = await navigator.gpu?.requestAdapter();
const device = await adapter.requestDevice({
  requiredLimits: {
    maxBufferSize: 1024 * 1024 * 1024,            // 1 GiB
    maxStorageBufferBindingSize: 1024 * 1024 * 512, // 512 MiB
  },
});

Three.js WebGPURenderer:

Three.js accepts requiredLimits as a renderer constructor option, which gets passed through to requestDevice():

const renderer = new THREE.WebGPURenderer({
  requiredLimits: {
    maxBufferSize: 1024 * 1024 * 1024,            // 1 GiB
    maxStorageBufferBindingSize: 1024 * 1024 * 512, // 512 MiB
  },
});
await renderer.init();

If the adapter doesn’t support the requested limit, requestDevice() (or renderer.init()) will fail.

Safe Pattern: Check Before Requesting

const adapter = await navigator.gpu?.requestAdapter();

const desiredBufferSize = 1024 * 1024 * 1024; // 1 GiB
const requiredLimits = {};

if (adapter.limits.maxBufferSize >= desiredBufferSize) {
  requiredLimits.maxBufferSize = desiredBufferSize;
} else {
  console.warn('Adapter does not support 1 GiB buffers, using default');
}

const renderer = new THREE.WebGPURenderer({ requiredLimits });
await renderer.init();

Features

Features are optional capabilities that vary by GPU. Unlike limits, features are either present or absent — there’s no numeric value to adjust.

How Three.js Handles Features

Three.js automatically requests all features supported by the adapter. You generally don’t need to manage features manually when using Three.js.

Querying Available Features (Raw WebGPU)

const adapter = await navigator.gpu?.requestAdapter();
// adapter.features is a Set
console.log(adapter.features.has('float32-filterable'));
console.log(adapter.features.has('shader-f16'));

Common Optional Features

Feature Purpose
float32-filterable Linear filtering on float32 textures
float32-blendable Blending on float32 render targets
shader-f16 16-bit floats in shaders
texture-compression-bc BC (desktop) texture compression
texture-compression-etc2 ETC2 (mobile) texture compression
texture-compression-astc ASTC (mobile) texture compression
timestamp-query GPU timing measurements
depth-clip-control Disable depth clipping
dual-source-blending Two blend sources from one shader
subgroups Subgroup operations in compute
clip-distances Custom clip planes in vertex shader

Best Practices

  1. Only request limits you actually need — requesting maximums hides portability issues where your app works on your GPU but fails on weaker ones
  2. Check adapter limits before requesting — gracefully degrade when limits aren’t available
  3. Don’t forget storage buffer binding sizemaxStorageBufferBindingSize is often the bottleneck, not maxBufferSize
  4. Use webgpureport.org to check what limits/features different GPUs support

Debugging

If you’re hitting buffer size errors or validation failures:

// Log all adapter limits
const adapter = await navigator.gpu?.requestAdapter();
for (const [key, value] of Object.entries(Object.getPrototypeOf(adapter.limits))) {
  if (typeof value !== 'function') {
    console.log(`${key}: ${adapter.limits[key]}`);
  }
}

Check Chrome DevTools console for WebGPU validation errors — they often mention which limit was exceeded.


Built by Force Information Systems · Harris Computer · Constellation Software. Licensed under MIT.