WavedashDocs

Shader stutter

Why WebGL and WebGPU games hitch on first render, how to warm up shaders, and how to reproduce stutter during development.

On native platforms, shaders are compiled ahead of time and cached by the GPU driver. On the web, WebGL and WebGPU shaders are compiled at runtime the first time they're used, which causes visible frame hitches — often called "shader jank" — that can last hundreds of milliseconds per shader.

Why it happens

  • The browser compiles shaders on the GPU the first time they're encountered during rendering.
  • Engines like Unity and Godot may use dozens of shader variants (one per material/lighting combo).
  • The browser can cache compiled shaders, but that cache isn't guaranteed to persist — it may be cleared on browser updates, when the user clears site data, or when the GPU driver changes.
  • On macOS specifically, the OS caches compiled Metal GPU binaries in a system directory outside the browser. This is the cache that actually prevents recompilation, not the browser's own shader cache.

What you can do

  • Warm up shaders early. Render all your materials and objects off-screen during the loading screen so compilation happens before gameplay starts. In Unity, use ShaderVariantCollection.WarmUp(). In Godot, instantiate materials during a preload scene.
  • Reduce shader variants. Fewer unique shaders means less compilation. Consolidate materials where possible and avoid unnecessary keyword permutations.
  • Expect cold starts. Unlike native, you can't rely on a persistent shader cache. Design your loading flow assuming the player may need to compile every shader on every visit.

Testing shader warmup in Chrome

After the first visit, Chrome (or macOS) caches compiled shaders, so you won't see stutter again — which makes it hard to tell if your warmup code is actually working. To simulate a cold start, clear the right shader cache and restart the browser. Which cache matters depends on your OS.

Windows

Clearing Chrome's app-level cache is sufficient.

  1. Quit Chrome completely (all windows, not just the tab).
  2. Delete the shader cache folder.

WebGPU — delete DawnWebGPUCache:

%LOCALAPPDATA%\Google\Chrome\User Data\Default\DawnWebGPUCache

WebGL — delete GPUCache and the top-level ShaderCache:

%LOCALAPPDATA%\Google\Chrome\User Data\Default\GPUCache
%LOCALAPPDATA%\Google\Chrome\User Data\ShaderCache

Default refers to your Chrome profile. If you use a non-default profile, look for Profile 1, Profile 2, etc.

  1. Reopen Chrome and load your game — you should now see shader compilation stutter on first play.

macOS

Clearing Chrome's own shader cache (DawnWebGPUCache, GPUCache) is not enough on macOS. The OS caches compiled GPU binaries in a separate system directory, and that's what actually prevents recompilation. You need to clear that instead.

  1. Quit Chrome completely (all windows, not just the tab).
  2. Delete the system Metal cache by running this in Terminal:
rm -rf "$(getconf DARWIN_USER_CACHE_DIR)/com.google.Chrome.helper/com.apple.metal"
  1. Reopen Chrome and load your game — you should now see shader compilation stutter on first play.

Once you can reproduce stutter, verify that your warmup phase compiles all shaders before gameplay begins. Look for hitches during the first few seconds of gameplay — especially the first time new visual effects or materials appear on screen.

There is no way to fully eliminate shader compilation stutter on the web. Even with warming, complex games will have a noticeable loading phase the first time shaders are compiled.