DEV Community

Cover image for I Fixed WebGPU on Linux. Then Forgot How I Did It.
Jessica Doering
Jessica Doering Subscriber

Posted on

I Fixed WebGPU on Linux. Then Forgot How I Did It.

I spent a ridiculous amount of time trying to get WebGPU working properly on my Linux machine.

I eventually figured it out, wrote a script to launch Chrome with all the necessary flags, and even made a desktop launcher so I could just click an icon whenever I wanted to run browser-based AI models.

Problem solved.

Except recently, I started thinking about all the trouble I'd gone through and realized something.

I couldn't remember how I'd fixed it.

Actually, I couldn't even remember where I'd saved the script.

So I did what any reasonable developer would do in 2026. I sent an AI agent to search my computer for code I'd written myself.

And what did it find?

Not only had I saved the script, I'd also written documentation explaining how it worked and backed everything up in TWO different resource directories.

Apparently, past me was considerably more organized than present me remembered.

Anyway, since I've already done all the hard work (and then forgotten about it), I figured I might as well share what I learned.

I just wanted to run AI models in my browser

I've spent quite a bit of time experimenting with local AI models, particularly small language models running through Transformers.js and ONNX Runtime.

I love the idea of running models directly in the browser. No server to maintain, no API calls to pay for, and inference happens right on your own hardware.

WebGPU makes a lot of that possible by allowing web applications to use the GPU for computation.

Which sounds great, right?

Except my setup wasn't exactly cooperating.

I'm running Arch-based Linux with Wayland on a laptop with hybrid graphics:

  • Intel Raptor Lake UHD integrated graphics
  • NVIDIA RTX 4090 Laptop GPU

And getting Chrome, Vulkan, NVIDIA, and Wayland to play nicely together was an absolute pain.

There are several layers involved. Your GPU drivers need to work, Vulkan needs to find the right device, Chrome needs to use the right graphics backend, and WebGPU needs to initialize successfully.

And just because one of those things works doesn't mean the next one will.

I spent a lot of time troubleshooting different configurations before I finally had something reliable enough to use regularly.

The solution that worked for me

Eventually, I ended up with a Bash script that launches a separate Chrome instance configured specifically for WebGPU.

Here's the script I recovered:

#!/usr/bin/env bash

# Launch Google Chrome with NVIDIA PRIME offload + Vulkan + WebGPU on X11.
# Dedicated separate profile so it can run alongside normal Chrome.

set -euo pipefail

CHROME_PROFILE_DIR="${HOME}/.config/chrome-webgpu-nvidia"

mkdir -p "$CHROME_PROFILE_DIR"

VK_LOADER_DRIVERS_SELECT='*nvidia*' \
__NV_PRIME_RENDER_OFFLOAD=1 \
__GLX_VENDOR_LIBRARY_NAME=nvidia \
__VK_LAYER_NV_optimus=NVIDIA_only \
google-chrome-stable \
  --user-data-dir="$CHROME_PROFILE_DIR" \
  --enable-unsafe-webgpu \
  --enable-features=Vulkan \
  --ozone-platform=x11 \
  "$@"
Enter fullscreen mode Exit fullscreen mode

It's not particularly complicated to look at.

But getting to the point where I knew which settings to use was another story.

I also created a .desktop launcher for it, so now when I want to experiment with WebGPU, I can just open that version of Chrome without having to remember any of this.

Which, as we've established, is probably a good thing.

What all those settings actually do

1. Getting Chrome to use the NVIDIA GPU

My laptop has two GPUs. There's the integrated Intel GPU and the dedicated NVIDIA GPU.

With hybrid graphics, applications don't necessarily use the GPU you'd expect.

That's a problem when you're trying to run models on your RTX 4090 and your browser decides the integrated GPU looks perfectly adequate.

So my script sets four environment variables:

VK_LOADER_DRIVERS_SELECT='*nvidia*'
__NV_PRIME_RENDER_OFFLOAD=1
__GLX_VENDOR_LIBRARY_NAME=nvidia
__VK_LAYER_NV_optimus=NVIDIA_only
Enter fullscreen mode Exit fullscreen mode

Here's what they're for:

  • VK_LOADER_DRIVERS_SELECT filters the Vulkan driver manifests so that the NVIDIA driver is selected.
  • __NV_PRIME_RENDER_OFFLOAD=1 enables NVIDIA PRIME render offloading.
  • __GLX_VENDOR_LIBRARY_NAME=nvidia selects NVIDIA for GLX vendor dispatch.
  • __VK_LAYER_NV_optimus=NVIDIA_only tells NVIDIA's Optimus Vulkan layer to expose only the NVIDIA GPU.

Not all four variables necessarily matter for every application or graphics path, but this combination was part of my working configuration.

The important thing was making sure Chrome could actually access and use the GPU I wanted.

2. Making Wayland cooperate by... not using native Wayland

This one still makes me laugh.

I'm running a Wayland desktop, but my working Chrome launcher includes:

--ozone-platform=x11
Enter fullscreen mode Exit fullscreen mode

That tells Chrome to use its X11 backend, which runs through XWayland inside my Wayland session.

At the time, I was running into problems getting Vulkan and Chrome's native Wayland backend to cooperate with NVIDIA.

Running Chrome through XWayland was the workaround that finally worked for my setup.

So after all that effort to get things running properly under Wayland, part of my solution was essentially telling Chrome to pretend it was running under X11.

Sometimes the practical solution isn't the elegant one.

It's the one that actually works.

3. Giving Chrome its own profile

This was one of the more useful discoveries.

--user-data-dir="$CHROME_PROFILE_DIR"
Enter fullscreen mode Exit fullscreen mode

Chrome normally reuses an existing browser instance when you try to launch it again with the same profile.

So if Chrome is already open and you try launching another window with different GPU flags, you might discover that your new settings aren't actually being applied.

Using a separate profile directory gives my WebGPU launcher its own Chrome process and GPU configuration.

That also means I can keep my regular browser open while running a separate instance for development.

No need to mess with my normal browsing setup every time I want to test something.

4. Enabling Vulkan and WebGPU

Finally, these two flags:

--enable-unsafe-webgpu
--enable-features=Vulkan
Enter fullscreen mode Exit fullscreen mode

The first enables experimental WebGPU support and bypasses certain GPU restrictions.

The second enables Chromium's Vulkan graphics feature.

There's an important distinction here: enabling Vulkan in Chrome doesn't necessarily guarantee that WebGPU itself is using Vulkan through Dawn, Chromium's WebGPU implementation.

The exact behavior depends on your Chromium version, platform, and graphics configuration.

Also, --enable-unsafe-webgpu is intended for development and testing. It's not something I'd recommend casually enabling in your everyday browser.

A note about newer Chrome versions: WebGPU support on Linux has been improving, so you might not need this exact configuration anymore. In particular, newer releases have expanded support for Intel and NVIDIA hardware. Check your current browser and driver support before copying every flag into your own setup.

How to check whether it's actually working

After launching Chrome with the script, open:

chrome://gpu
Enter fullscreen mode Exit fullscreen mode

Look at the Graphics Feature Status section.

Ideally, you want to see hardware acceleration enabled for WebGPU and Vulkan rather than software fallbacks.

It's also worth checking the GPU and driver information to make sure Chrome is using the NVIDIA device instead of Intel or a software renderer like SwiftShader.

But don't stop there.

Being able to see WebGPU listed as hardware accelerated doesn't guarantee your actual application will run correctly.

Try running a real WebGPU sample or the model you're planning to use.

I've learned this the hard way more than once.

For example, while building my recent Mimu note-taking app, Safari on my iPhone reported that WebGPU was available. But attempting to initialize the Whisper model with WebGPU caused the tab to crash and reload.

The WASM version worked fine.

And for that particular small model, WASM was fast enough that using WebGPU wasn't worth the trouble anyway.

That was another useful reminder that the theoretically faster option isn't always the best one.

And then I forgot where I put everything

So here's where this whole thing comes full circle.

Recently, I've started keeping detailed build logs for my projects.

Not just what I built, but what broke, what I tried, why I made certain decisions, and what I'd do differently if I approached the same problem again.

Writing more on DEV has actually encouraged this habit. Thinking about what I might eventually write makes me pay more attention to what I'm doing while I'm building.

And I've already found myself going back through my notes and reconsidering decisions I made just a day or two earlier.

Which got me thinking about all those earlier experiences with WebGPU.

I wished I'd documented them better.

Turns out, I had.

I just couldn't remember doing it.

My AI agent found the original launcher in:

~/.local/bin/chrome-webgpu-nvidia
Enter fullscreen mode Exit fullscreen mode

The desktop entry was in:

~/.local/share/applications/
Enter fullscreen mode Exit fullscreen mode

And the documentation and additional copies were sitting in my PINKPIXEL/RESOURCES directory.

In two different folders.

I had already done everything I was wishing past me had done.

I just hadn't done a particularly good job of making that information easy to find again.

Which is even funnier considering I'm currently building an app designed to help people capture, organize, and remember things.

Apparently, I really do need it.

What I learned from all this

The technical lesson here is that getting WebGPU working on Linux can involve more than just enabling a browser flag, especially with hybrid graphics.

Depending on your hardware and software versions, you may need to pay attention to which GPU is being selected, which graphics backend Chrome is using, and whether your application is actually getting hardware acceleration.

But I think the bigger lesson for me has less to do with WebGPU.

I've built a lot of things over the years. I've solved problems, experimented with technologies, and figured out workarounds that took far more effort than I expected.

And then I moved on to the next interesting thing.

I didn't always stop to think about what I'd learned or how useful that experience might be later.

That's something I've been trying to change.

Keeping build logs has made me more thoughtful about the decisions I'm making, and writing about my experiences has encouraged me to look at them more closely.

Sometimes that means discovering a better way to approach something.

Sometimes it means remembering a useful technique.

And sometimes it means finding out that I already solved a problem, documented it, backed it up twice, and completely forgot about the whole thing.

At least now I know where my WebGPU script is.

For the moment, anyway.

Top comments (6)

Collapse
 
yixiang_xiao_7e85b6ed0d35 profile image
yixiang xiao •

Great post, this hits so close to home πŸ˜„ I spent a few weeks shipping a Pandoc WASM
build (~56 MB binary) that runs entirely in-browser, and I landed at the opposite
end of the same conclusion β€” for CPU-bound workloads (file conversion), plain WASM
with a good IndexedDB cache was faster AND simpler than wrestling with WebGPU
cross-browser. No Vulkan flags, no X11 hacks, no GPU detection headaches.

Also the part about past-you being more organized than present-you is too real. My
dev journal is just a growing folder of files I've cryptically named fixes-notes.md 🫠

Did you end up ditching the WebGPU launcher for WASM inference after all, or do you
still keep it around for heavier models?

Collapse
 
nullandvoid_ profile image
Jyanthi •

56 MB just to convert files is wild πŸ˜‚ WASM really said, β€œWhy make it complicated when it can just work?” And those cryptic notes are basically every developer’s autobiography! πŸ˜…

Collapse
 
sylwia-lask profile image
Sylwia Laskowska •

Wow, that's an epic fight with Linux!!! 🀩

Collapse
 
anas_issath profile image
Anas Issath •

Sending an AI agent to find code you wrote yourself is peak 2026 developer life πŸ˜‚ Also love that the Wayland fix was basically telling Chrome to pretend it’s on X11. The Safari note about WASM beating WebGPU for small models is a great reminder too. Past you deserves a thank-you note!

Collapse
 
alexcodebytes profile image
Oleksandr •

"Sending an AI agent to find code you wrote yourself is peak 2026 developer life" is the most accurate description of modern development I've read this year.

We've reached the point where we need AI to remember what we did before AI. It's funny, but it's also a real problem: if you can't find your own work, you can't build on it.

Collapse
 
alexcodebytes profile image
Oleksandr •

"Sometimes the practical solution isn't the elegant one. It's the one that actually works" is the most honest sentence in this article.

I've spent hours trying to make Wayland and NVIDIA cooperate, only to end up with --ozone-platform=x11 as the final answer. It feels wrong, but it works, and at some point "works" beats "elegant".

Curious how much of this is still necessary on newer Chrome versions. The article mentions WebGPU support has improved, but I'm wondering if the hybrid graphics problem (Intel vs NVIDIA) is still the same.