# The Dawn of Inadequacy

**URL:** <https://discourse.threejs.org/t/the-dawn-of-inadequacy/95624>\
**Category:** Discussion\
**Tags:** webgpu\
**Created:** [October 21, 2026, 2:22am UTC](https://discourse.threejs.org/t/the-dawn-of-inadequacy/95624 "2026-10-21T02:22:56Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Usnul](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/usnul/32/2355_2.png) [@Usnul](https://discourse.threejs.org/u/Usnul)\
**Post date:** [October 21, 2026, 2:22am UTC](https://discourse.threejs.org/t/the-dawn-of-inadequacy/95624/1 "2026-10-21T02:22:56Z")

</div>

WebGPU is not ready for production. The reason for that is Chrome.

I desperately wish for it to be different as I [made a bet](https://discourse.threejs.org/t/shade-webgpu-graphics/66969) on WebGPU about 3-4 years ago.

First, a bit of a history lesson, WebGPU came out in beta (origin trial) in Chrome 94, in September 21, 2021. That’s just over 5 years ago now.

WebGPU was officially released in Chrome 113, on May 2, 2023 on desktop and January 23, 2024 for Android.

It’s fair to say that WebGPU should be a production-ready and mature platform today. It isn’t.

WebGPU has a critical flaw in lifecycle management. Here’s a typical recording from my WebGPU engine:

 ![image](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/1/a/1a57d3ccd7b849896406edd36e2f8bfa68aa2415.png)

At a first glance it looks okay, about 6-7ms on the main thread per frame, but what’s this massive gap with no main thread work?

 ![image](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/6/a/6ac2a292785ced27926a68305d17d6d48017029e.png)

If we look closer we see that GPU is apparently busy here

 ![image](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/4/c/4c003ac713f77b104780e7ce9e1f1ab925436d51.png)

Let’s have a look what windows says, because it looks like the GPU is choking with work, right?

 ![image](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/e/f/ef6db48ddfe2ec76aeb9bd81e8a3fba785786efd.png)

So if the GPU is not choking, what is going on?

 ![image](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/9/0/9037876121fd87eb435ea1bfc4254d7858c11409.png)

Chrome just helpfully says “GPU” for every green sliver.

Chrome’s WebGPU implementation happens to be done as a separate process, and the main thread’s WebGPU API communicates with the process via TCP. So, in reality, the green slivers are both the GPU work, as well as any and all overhead of the Dawn’s “GPU” process, including marshalling data, validation on both CPU and GPU and, as it happens, garbage collection.

This brings us to the crux of the matter. The reason, I asserts that Chrome is not yet production ready, as far as WebGPU is concerned, is the garbage collection. Or “memory management” to put it more broadly.

What happens is WebGPU GPU process accumulates a bunch of objects for each frame, objects you can’t really reuse:

- GPUCommandEncoder
- GPUCommandBuffer
- GPUComputePassEncoder
- GPURenderPassEncoder

In theory - you could reuse these objects, but in practice it’s a pathological design to do so, and it goes against what the API was designed for. That is - “in theory anything in possible”, but in practice you would create a new command encoder each frame, and you would open up at least one render pass encoder each frame, and you would create a command buffer.

Now, these things don’t get destroyed normally, and they don’t get swept up in incremental pauses, instead, we get a MagorGC pause of, sometimes hundreds of milliseconds, or in our example here - a few frames worth.

I have bent over backwards chasing these demons over the past years.

BindingGroups seem like they should be super easy to create and destroy, and they are on Vulkan and the like, but they create garbage in Dawn that leads to major GC pauses, so, fine, I spent time designing and re-designing young/old heap-style caches for BindingGroups, the caches work and they work really well, most of the pauses are gone. I understand that three.js recently did something similar.

Next, we have TextureViews, they are incredibly tiny, but again, it’s garbage, so I cache these too. What else?

Creating buffers, even tiny ones are garbage, so I don’t, I have a bunch of allocators for every flavour of use case, no buffer being created or destroyed between frames. Are we done yet?

No, sadly these demons still remain:

- GPUCommandEncoder
- GPUCommandBuffer
- GPUComputePassEncoder
- GPURenderPassEncoder

And they’re not going away anytime soon. It’s been 5 years since WebGPU was available and 3.5 years since it came out as a full release, and yet it’s still incapable of creating a jank-free experience in WebGPU.

Quite ironically, the problem is CPU-side, so people with a decent GPU chip but a slow CPU, such as on mobile and on laptops - they get the shortest end of this stick.

> The GPU is willing, but the CPU is weak.

I don’t have friends at google. Come to think of it, I don’t have friends. If you do, that is, if you have friends at google, please whisper sweetly into their ear something along the lines of

> Please fix object lifecycle for WebGPU objects or improve the GC on the GPU process, dear google friend

* * *

To sum up, if you’ve ever experienced jank on WebGPU and wondered what you’re doing wrong, the answer is: nothing. It’s not you, it’s Chrome.

---

<div class="post-metadata">

**Author:** ![agargaro](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/agargaro/32/35529_2.png) [@agargaro](https://discourse.threejs.org/u/agargaro)\
**Post date:** [October 21, 2026, 2:37pm UTC](https://discourse.threejs.org/t/the-dawn-of-inadequacy/95624/2 "2026-10-21T14:37:49Z")

</div>

For the past month, I’ve been trying to migrate my InstancedMesh2 library to WebGPU, and I’ve noticed that in some scenarios it’s significantly slower than WebGL. For example, in a scenario where I have many instances and need to perform some partial updates to the matrix buffer—I don’t think there’s anything I can do about it, since there’s a bug that’s been open since 2022:

> **[Chromium](https://issues.chromium.org/issues/40058804)**

It’s pretty frustrating.

---

<div class="post-metadata">

**Author:** ![torrent](https://avatars.discourse-cdn.com/v4/letter/t/4bbf92/32.png) [@torrent](https://discourse.threejs.org/u/torrent)\
**Post date:** [October 21, 2026, 3:21pm UTC](https://discourse.threejs.org/t/the-dawn-of-inadequacy/95624/3 "2026-10-21T15:21:57Z")

</div>

Funny you make this post right now. I’m learning how to work with WebGPU directly after using three.js for years, with the goal of creating my own lightweight abstraction over WebGPU. I just ran across this same issue: learning that you have to create a `GPUCommandEncoder` object, `GPURenderPassEncoder` object, `GPUCommandBuffer` object, etc. on ever render. It has me scratching my head, because surely the WebGPU API designers wouldn’t require you to create garbage on every render?  
Garbage collection jank sucks but it’s easily manageable if you write your project with a garbage-free design. Unfortunately there is no way around it with WebGPU in this area.
