Prompt and context
This frontend question combines a browser platform with release engineering. The application already has WebGL or CPU paths and wants faster rendering on WebGPU while reaching devices that expose only a restricted API subset. The core is capability and limits negotiation; obtaining an adapter does not mean every shader, format, or performance target is available.
The GPUWeb specification describes compatibility mode as a restricted WebGPU subset intended to map to older graphics APIs. An implementation can still reject an adapter, expose fewer features or limits, or lose a device at runtime. Availability, correctness, and performance must be measured separately.
What the interviewer evaluates
- Building a capability matrix before choosing an adapter, feature, or limit.
- Defining core, compatibility, WebGL, CPU, and static-result paths as an ordered product fallback rather than one Boolean.
- Knowing that
GPUDevice.lostis an asynchronous termination signal and recovery rebuilds resources and render state. - Designing real-device rollout, quality gates, privacy-conscious telemetry, and fast rollback.
- Separating “renders correctly,” “meets latency,” and “uses acceptable power.”
Clarifying questions
- Is the workload rendering, general compute, or in-browser inference? Each needs different storage, texture, and precision capabilities.
- What experience must low-end devices retain? This sets the minimum WebGL, CPU, or static-result path.
- May the first load run a short capability probe? Without one, historical device profiles can be stale or wrong.
- Can the canvas and resources be reinitialized after device loss? If not, the application state needs a recoverable UI boundary.
- Is rollout segmented by browser, GPU, driver, region, or user? Segmentation determines how a driver-specific regression is found.
30-second answer
“I would detect WebGPU, the adapter, features, and limits, then define core, compatibility, WebGL, CPU, or static output as an explicit capability ladder. Each rung creates only the shaders, pipelines, and resources it supports and has a correctness test and performance budget. I listen to device.lost and use a single-flight recovery flow to rebuild the device, resources, and canvas state; failure degrades and records a reason. Rollout is segmented by browser, GPU, driver, and app version. I monitor initialization, device loss, rendering errors, p95 frame time, and task completion, with a remote off switch that never removes the old path.”
Step-by-step solution
Step 1: Make capability detection a contract
Confirm a secure context and navigator.gpu, then request an adapter. Read its supported features and limits; checking that the API object exists is insufficient. Classify the result as core, compatibility, WebGL, or CPU, and use coarse browser, operating-system, GPU-vendor, driver, and app-version dimensions for telemetry.
Compatibility mode expands the runnable-device set but has more conservative feature, limit, and performance ceilings. Write the workload's hard requirements as a list: texture formats, binding layout, storage size, workgroup limit, and precision. If one required capability is absent, select the next rung instead of waiting for shader creation to fail.
Step 2: Build resources for the capability rung
Give every rung its own shader variants, pipeline descriptions, and resource budget. Start with a tiny triangle or small inference smoke test, validate command submission and output, and only then enter the full scene. Do not assume a bind group or texture format created for core is accepted in compatibility mode.
On a resource-creation failure, record a structured error and release that rung's objects. A static image, WebGL canvas, or CPU result must share the product state model so the user can finish the task. A fallback must not imply identical frame rate or precision.
Step 3: Handle device loss and recovery races
GPUDevice.lost resolves when the device lifetime ends. Enter recovering: stop submitting new work, cancel or mark old frames, request a new adapter and device, rebuild shaders, pipelines, buffers, textures, and bind groups for the capability rung, then resume the render loop. A generation token or single-flight promise prevents two recovery attempts from overwriting the new device.
If the loss reason suggests resource pressure or a driver issue, cap retries and their interval. Repeated failure switches to WebGL or CPU and tells the UI that the feature is degraded. The existing device-loss question focuses on recovery mechanics; this one focuses on compatibility capability matrices and release control, so keep the scopes separate.
Step 4: Design staged rollout and rollback
Start with an internal device matrix, then expand by browser version, GPU vendor, driver, operating system, and region. The flag must be remotely disableable, but configuration delivery cannot be a correctness single point of failure; the client keeps a safe default.
Track adapter-request failure, device-creation failure, time to first interaction, p50/p95 frame time or inference latency, shader and pipeline errors, device-loss rate, recovery success, fallback rate, and task completion. Hardware segmentation exposes driver regressions. Keep telemetry to coarse device labels and versions rather than a complete fingerprint.
Step 5: Validate correctness, performance, and power
Compare WebGPU, compatibility, WebGL, and CPU outputs with tolerances for pixels, geometry boundaries, texture colors, and inference results. Fix scene, resolution, and batch size for performance tests and report p50/p95; a flagship-device average is not a guarantee. Test submission rate, memory, and a device-temperature proxy in background and low-battery scenarios.
Set gates per rung: compatibility needs the product's minimum frame rate and output error, not the core budget. If error, power, or recovery time crosses a threshold, disable that rung, preserve WebGL/CPU output, and collect driver details with a minimal reproduction.
Design trade-offs and boundaries
#### API probe vs device profile
A live probe is accurate but costs first-load time; a device profile is fast but can be stale or fingerprinting. Use a short probe for hard capability and profiles only for ordering and rollout, never to bypass actual limits.
#### Compatibility mode vs WebGL
Compatibility mode preserves more of WebGPU's resource and command model, which can share architecture. WebGL may have broader mature coverage, but its shader, synchronization, and performance model differs. Choose by required capability, correctness migration cost, and user task, not API novelty.
#### Automatic recovery vs immediate fallback
A bounded recovery handles transient resource pressure; infinite retries turn a driver failure into jank and power amplification. After recovery fails or repeated loss crosses a threshold, switch immediately and emit one diagnostic event.
Model answer
“I would split the WebGPU rollout into a capability matrix, resource construction, a recovery state machine, and staged control. I verify the secure context, request an adapter, read features and limits, and order core, compatibility, WebGL, and CPU as a capability ladder; each rung creates only supported shaders and resources. After device.lost, I stop submission and use a generation token so one recovery flow rebuilds the device and every GPU object, then falls back on failure. Rollout is segmented by browser, GPU, driver, and version, with initialization, frame time, errors, loss, recovery, and task completion metrics plus a remote off switch. Compatibility mode broadens coverage, not performance guarantees, so correctness, latency, and power have separate gates.”
Common mistakes
- Checking only
navigator.gpu→ Adapter or device creation can still fail, and features or limits may be insufficient → Build and verify a capability matrix. - Treating compatibility mode as a low-end core → Shaders, formats, and limits may differ → Give each rung its own requirements and smoke test.
- Calling the render function again after loss → Resources belong to the dead device → Rebuild every resource through a single-flight recovery flow.
- Retrying device creation forever → A driver fault becomes jank and power amplification → Cap attempts and intervals, then fall back.
- Watching average frame rate only → A small GPU or driver cohort can fail completely → Segment p95 and task completion by browser, GPU, and driver.
Follow-ups and responses
How do you decide whether a workload fits compatibility limits?
Write hard requirements for features, texture formats, storage, workgroup size, and precision, then compare them with the adapter limits. Enter the rung only when the list passes; otherwise choose WebGL, CPU, or static output and record the missing capability.
Can you reload the page when a user is editing and the device is lost?
Not by default. Persist editing state at the application layer, pause GPU work, and try one bounded rebuild. If it fails, switch renderers while preserving the state and explain the visual degradation. Reload only when state migration is unsafe, with a recovery entry point.
A driver cohort suddenly has a high loss rate. How do you roll back?
Confirm the anomaly by GPU, driver, browser, and app version, then disable compatibility rollout for that combination while leaving other cohorts enabled. Inspect initialization, shaders, resource pressure, and loss reasons; reproduce minimally and restart from the internal matrix after a fix.
How do you show that the WebGL fallback preserves business results?
Create a cross-backend golden set for identical inputs, compare pixel or inference-output tolerances, and include empty, boundary, and high-load cases. Set separate gates for task completion, result correctness, and latency; visual similarity does not prove numerical or interaction equivalence.