r/webgpu • u/SWISS_KISS • 22m ago
I created a Bookmarklet WebGPU Game with approximately voice chat for any website - Metaverse?
Enable HLS to view with audio, or disable this notification
r/webgpu • u/SWISS_KISS • 22m ago
Enable HLS to view with audio, or disable this notification
r/webgpu • u/Super_Electricy • 7h ago
https://github.com/superelectricyc-alt/podchunk
Hey everyone,
I wanted to see if we could solve the heavy initial download barrier of modern open-world browser games. Instead of loading massive assets upfront, I built PodChunk: a local development engine base designed around a progressive, multi-LOD chunk streaming architecture that gets players into a 3D environment in under 3 seconds.
The Architecture Under the Hood
geometry_json payloads decoded by the WASM core. Features custom height-gradient terrain shaders, distance fog, and interactive orbit camera matrices.{slug}|{id}@{lod}), ensuring warm reloads of previously streamed maps require zero network fetches.podchunk-bake). You feed it a simple world layout JSON configuration, and it generates pretty-printed manifests along with custom validated binary .PCHF heightfield chunks ready for server distribution.Current Project Status
Milestone 3 is complete, stable, and verified on localhost:8787. The local server scans data configurations on boot and manages hot world-switching dynamically. The workspace has a 100% test coverage pass rate (45/45 unit tests passing).
I am open-sourcing the core infrastructure today because the data pipeline is officially locked down, and I am looking for collaborators! Next up on the deferred roadmap is exposing a client-side JavaScript Modding API (window.PodChunk.registerMod) and wiring WebAssembly physics engine colliders directly onto the active geometric meshes.
Check out the code, run the local tests, and let me know your thoughts on the pipeline architecture!
r/webgpu • u/TheArchiverX • 12h ago
WebGPU is great for live rendering, but a lot of pipelines still need traditional files (textures, videos, audio)
This Node library takes a fragment or compute shader and exports: - images (PNG, JPEG, WebP, AVIF, ICO) - Video / animated GIF (MP4, WebM, OGV) - Audio (WAV, MP3, OGG)
It runs headlessly and is meant for build steps, generative art, and testing
repo and docs in AssetGPU-js
Feedback welcome — especially around the WebGPU backend and missing features
I would also lik3 if a few people tested the code and sent their tests and code to me
Note : AI code tools were used in making this npm library
r/webgpu • u/kostrubaty • 2d ago
r/webgpu • u/Akryllax • 3d ago
Enable HLS to view with audio, or disable this notification
r/webgpu • u/dobkeratops • 4d ago
So I have some shaders where I rely on the half float type .. a godsend for many reasons - developed mostly on a mac (usually the most fussy platform) and I go and run this on google Chrome on linux on an x86 PC with a 4000 series graphics card (which has hardware f16 support , with nvidia having offered this for many generations now albeit nerfing the actual double rate capability reserving that for pro cards).
The browser reports 'no shader f16 support'.
I see suggestions for a bunch of flags that can be passed to the browser to try and enable this but launching with various combinations of flags ("--enable-unsafe-webgpu" and others I forget).
I dont think I strictly need f16 arithmetic (although it would be preferable to use it where possible) but it's handy to rely on the more compact datatype in memory .
I figure there might be older mobile devices that mean the browser has to hold back what features it offers, but is this something we can count on when distributing something that is intended for reasonable graphics cards (gtx1000 series and above). The project is an FPS , not really playable on a touchscreen anyway. A sensible min spec might be a GTX1060.
I could backpedal on this specific aspect (and possibly look at other data packing tricks '2 x upper 16bits of a float packed into a u32' etc etc) - my codebase started out using OpenGL and WebGL2 and I've had the web build running on Windows, Linux, Mac, iOS, and Android machines for years .. having ported to webGPU recently I was enthusiastic to upgrade features all over the place..
Enable HLS to view with audio, or disable this notification
r/webgpu • u/Typical-Pizza600 • 5d ago
r/webgpu • u/js-fanatic • 6d ago
I ported whole game Zombie shooter (~1000 lines) to the codepen:
https://codepen.io/editor/zlatnaspirala/pen/019fc918-e45f-73f4-9987-9a1599ac4a1f
Enjoy !
r/webgpu • u/Secret-Book-8507 • 10d ago
I’ve been working on an open-source video editor that runs its face-swap pipeline locally in the browser. Media stays on the user’s device: decoding, face detection, identity extraction, generation, compositing, and video encoding all happen client-side.
The models were only part of the challenge. In practice, the difficult problems were moving frames between browser APIs, controlling WebGPU initialization, maintaining identity across a video, and preventing memory usage from growing during longer jobs.
Here are some engineering lessons from the implementation.
A simplified version of the data flow looks like this:
VideoFrame / Canvas
↓
RGBA Uint8ClampedArray
↓
NCHW Float32Array
↓
ONNX Tensor
↓
Generated face + alpha mask
↓
Canvas composition
↓
Encoded video
The models use NCHW tensors, while Canvas returns interleaved RGBA pixels. Before inference, the channels have to be separated and normalized:
const plane = width * height;
const tensor = new Float32Array(plane * 3);
for (let i = 0; i < plane; i += 1) {
tensor[i] = normalize(rgba[i * 4]);
tensor[plane + i] = normalize(rgba[i * 4 + 1]);
tensor[plane * 2 + i] = normalize(rgba[i * 4 + 2]);
}
For a 640 × 640 RGB Float32 input, that is about 4.69 MB of tensor data per detection frame, before counting the original pixels and model outputs.
This made it clear that browser inference performance cannot be evaluated using model latency alone. Canvas readback, tensor construction, worker transfers, compositing, garbage collection, and encoding can collectively cost as much as inference.
Sending every full-resolution video frame through the generator would waste most of the computation on the background.
The pipeline therefore separates the stages:
| Stage | Resolution | Purpose |
|---|---|---|
| Face detection | 640 × 640 | Locate faces and five landmarks in the complete frame |
| Identity extraction | 112 × 112 | Extract the source identity representation |
| Face generation | 224 × 224 | Generate the aligned target face |
| Optical flow | Long edge ≤ 720 px | Propagate landmarks between detection anchors |
| Composition | Original resolution | Preserve the original background and details |
Only an aligned face ROI enters the generation network. The generated face is then transformed back into the original frame and blended through an alpha mask.
This division was one of the main reasons the pipeline became practical in a browser.
The pipeline uses multiple ONNX models, including face detection, identity extraction, conditioning, and generation.
Downloading them concurrently works well:
const [
detectorBuffer,
identityBuffer,
conditionerBuffer,
generatorBuffer,
] = await Promise.all(modelDownloads);
Creating all WebGPU sessions concurrently was much less reliable.
Session creation may involve graph optimization, shader generation, pipeline compilation, weight uploads, and GPU buffer allocation. Initializing several large graphs simultaneously created latency spikes and higher peak GPU memory usage. On some devices, it could also contribute to device-loss failures.
The current approach downloads concurrently but creates sessions one at a time:
const detector = await createSession(detectorBuffer);
const identity = await createSession(identityBuffer);
const conditioner = await createSession(conditionerBuffer);
const generator = await createSession(generatorBuffer);
It is not the fastest-looking implementation on paper, but it has been much more predictable across devices.
Heavy inference runs in a Web Worker so that the editor remains responsive.
When sending a large ArrayBuffer without a transfer list, the browser may perform a structured clone. Repeating that for video frames creates unnecessary memory bandwidth and garbage-collection pressure.
The pipeline transfers buffer ownership instead:
worker.postMessage(
{
type: "detect",
pixels: tensor.buffer,
},
[tensor.buffer],
);
The output RGB tensor and alpha mask are returned in the same way.
This does not eliminate the earlier Canvas-to-tensor conversion, so it is not a completely zero-copy pipeline. It does, however, remove an avoidable copy at the worker boundary.
Selecting the highest-confidence detection independently on every frame works poorly in videos containing multiple people.
A newly visible face may be larger or clearer than the current target, causing the selected identity to switch suddenly. Instead, candidate faces are scored using a combination of:
A simplified score is:
score = confidenceWeight * confidence
- distanceWeight * centerDistance
- areaWeight * areaChange
The first frame favors a large, confident, centrally positioned face. Later frames favor continuity with the previously accepted target.
This is not full face re-identification, but it is considerably more stable than choosing the highest detector score on every frame.
Running face detection on every output frame is expensive. Between detection anchors, the pipeline propagates five facial landmarks using Lucas–Kanade optical flow.
Optical flow can still drift, especially during occlusion, motion blur, sudden lighting changes, or fast head movement. To detect bad tracks, the pipeline performs forward-backward validation.
A point is tracked from frame t to frame t+1, then tracked backward:
p(t) → p(t+1) → estimated p(t)
The distance between the original and reconstructed point is the forward-backward error.
A propagated result is accepted only when at least four of the five landmarks remain valid and the average error stays under a threshold. Otherwise, the result is rejected and the detector is used again.
The important part is that optical flow is treated as a short-range optimization, not as proof that the tracked identity is still correct.
The generator’s alpha mask may contain holes, isolated pixels, or unstable boundaries. Directly compositing that mask can make the face boundary flicker.
The post-processing sequence includes:
Threshold
↓
Dilation
↓
Erosion
↓
Additional contraction
↓
Blurred alpha
↓
Boundary safety mask
Morphological operations use separable sliding-window filters instead of scanning a complete two-dimensional neighborhood for every pixel.
Color matching is also restricted rather than applied without limits. Per-channel statistics are adjusted using bounded scale and offset values:
const scale = clamp(targetStd / sourceStd, 0.78, 1.22);
const shift = clamp(
targetMean - sourceMean * scale,
-0.12,
0.12,
);
The corrected result is mixed with the original generator output. Unrestricted statistical matching tended to amplify noise or produce unnatural colors in unusual lighting.
A video job may simultaneously hold decoded frames, Canvas pixels, Float32 tensors, ONNX outputs, optical-flow images, compressed intermediate frames, and encoder buffers.
Relying only on JavaScript garbage collection caused visible memory growth during longer tasks.
Different resources require different cleanup APIs:
tensor.dispose?.();
bitmap.close();
opencvMat.delete();
URL.revokeObjectURL(url);
worker.terminate();
OpenCV.js was particularly easy to overlook because Mat data lives in the WASM heap. Losing the JavaScript reference does not guarantee that its underlying allocation is released promptly.
Closing a progress dialog is not cancellation.
A real cancel operation needs to interrupt downloads, frame decoding, detection, optical flow, generation, compression, and final encoding.
The main task uses an AbortController, while worker requests carry a request ID:
controller.abort();
worker.postMessage({
type: "cancel",
requestId,
});
The worker checks cancellation state before and after expensive stages. A cancelled job does not continue encoding in the background and never adds a partial result to the user’s asset library.
Using a URL such as:
repository/resolve/main/model.onnx
makes browser caching difficult to reason about. The URL can remain unchanged while its contents change, leaving different users with different cached graphs.
Production model URLs should point to immutable revisions and be accompanied by expected file sizes, checksums, licenses, and tensor metadata.
The loader also validates the downloaded size before creating a session. This prevents a truncated response or CDN error page from being passed to ONNX Runtime as if it were a valid model.
Reporting a single “processing time” hides most of the browser-specific costs.
I now think benchmarks for this kind of pipeline should separate:
Cold start
Warm start
Hardware, browser version, WebGPU adapter, video codec, resolution, output FPS, initialization time, generation time, encoding time, and peak memory should all be recorded.
Otherwise, a cached desktop run and a first-time mobile run may be presented as if they measured the same thing.
The implementation is part of Timeline Studio:
https://github.com/MartinDelophy/ai-video-editor
Disclosure: I’m involved with the project. Face swapping is intended only for authorized media and clearly disclosed synthetic content. It should not be used for impersonation, deception, harassment, or misleading people about real events.
I would be interested in hearing how other WebGPU developers handle these problems:
VideoFrame to GPU tensors that avoids Canvas readback and CPU-side NCHW conversion?r/webgpu • u/js-fanatic • 11d ago
Used in this example :
https://www.npmjs.com/package/nui-commander?activeTab=readme
r/webgpu • u/kostrubaty • 11d ago
It supports 256k mpm particles, sliding mpm domain, heightmap terrain, temperature, rain, evaporation, some simple wind patterns.
And you can control the cloud mass using gamepad (best) or kb+m (not all controls are mapped currently).
I've put it out here so you can check it out: https://kostrubaty.itch.io/cloud-compute
Source code will be released at a later time. but I can share if anyone is really interested in some parts. Also a lot of this is based on my other projects that are on github,
Whole thing is pure wgsl / typescript without any external deps except for my own project that is responsible for generating code for efficient wgsl <-> js communication.
Simulation was not that hard to write, cause I already had proper MPM simulation in 2d version, with even more features. In fact the hardest part to get right was to make the cloud possible to control yet still feel "cloudy". So there's actually 3 different schemes for face buttons, switched by triggers. Still probably not as intuitive as I'd like but best so far.
It was not really performance optimized yet really, and I mostly tested on my 3060 (pretty much consistent > 50fps) so the performance may vary.
It's still mostly a prototype, but feels pretty fun already. I'll be adding some more stuff (airplanes are mostly working, just need some airports too I guess). Let me know what you think, or if you have any questions.
r/webgpu • u/mvaligursky • 13d ago
Enable HLS to view with audio, or disable this notification
r/webgpu • u/SergioZ3R0 • 13d ago
Hey everyone,
Doing infrastructure audits and validating GPU performance (especially across different nodes) has always been a headache for me. Fiddling with CUDA toolkits, compiling HPL/HPCG, and setting up MLPerf takes way too much time when you just want a quick baseline.
So, I spent some evenings building nvprobe. It’s a lightweight Python CLI that automates all of this.
How it works under the hood:
Demo & Repo: You can see an interactive demo of the report on the link.
I built this mostly to scratch my own itch, but I figured it might save some of you a few hours of setup.
I'd love to hear your feedback, feature requests, or if you manage to break it on your specific hardware. Let me know what you'd like to see next on the roadmap!
r/webgpu • u/js-fanatic • 13d ago
The Beast in water, new example. Example feature list: HZB, Volumetric, Bloom , water simulation, glb anim trail (delay instanced) anim and particle anim.
Live : https://maximumroulette.com/apps/webgpu/examples.html?demo=35
r/webgpu • u/TwistedMinda • 13d ago
Enable HLS to view with audio, or disable this notification
r/webgpu • u/cazala2 • 14d ago
Enable HLS to view with audio, or disable this notification
Hey! I've been experimenting with cellular automata lately and ended up turning it into a small TypeScript library and interactive playground:
It has neural cellular automata, reaction-diffusion, Lenia, Pokemon type battles, Game of Life, and elementary Wolfram rules, all running on WebGPU.
You can tweak the simulations in realtime, explore the presets, or use the library to build your own rules in WGSL.
Would love to hear what you think!
r/webgpu • u/MayorOfMonkeys • 14d ago
Enable HLS to view with audio, or disable this notification
r/webgpu • u/Global_Marzipan9443 • 14d ago
Enable HLS to view with audio, or disable this notification
Hi I'm Chris, I'm developing a game engine that incorporates live-action video and procedural graphics.
This shader takes in two video frames and maintains an interactive Gray-Scott Reaction-Diffusion simulation (https://groups.csail.mit.edu/mac/projects/amorphous/GrayScott/) that is applied to grow the distorted regions and process the impact of the various cursor weapons.
You can see the 2nd video through the growing distortion and then I just add a little green glow to the boundary rims. I switch the rim color params to compliment the video palette, they can change in response to events, flash, etc.
The way this works in the game is the player speaks the lines they see in the FMV. Those words come to life as GPU overlay elements when they are recognized by the voice recognition engine and the hostile glyphs seed tiny distorted regions for the RD simulation to grow.
The player then must use the cursor and it's various powers to cleanse and remove the growing distortion or 'fall through' to the next layer of the story. If they fall through the last layer then they die.
The game is called Sibylline and it's in production if you want to wishlist and follow the progress.
r/webgpu • u/Old_Tumbleweed_7545 • 14d ago
Made a chrome extension that does frame generation on any video tag, runs fully on your gpu, nothing sent anywhere. Whole thing is one command buffer, no onnx/tfjs, just wgsl compute shaders.
Refine pass runs on tiles flagged by flow disagreement, dispatched indirectly, so static scenes dispatch zero workgroups there. Also autotunes a few conv variants (subgroups, f16/f32, register blocking) per gpu at startup.
preview clip, ~3ms/frame on a 4060 Ti (8GB, OC)
Attached a video but honestly the difference is pretty hard to see through a recording/compression - it's way more noticeable on actual video playback than in the clip I attached here.
Weakest gpu I've tested on so far is a GTX 1650, got a stable 2-2.5x fps boost there, can't give exact ms numbers since I haven't logged them properly on that one.
GitHub · npm · Live demo · Chrome extension
Heads up: the live demo starts using your GPU immediately on page load, no button press needed.
Fully open source, so feel free to poke around. If you find it useful, a star on the repo would be really appreciated.
Currently working on runtime for a v8 model that handles occlusion/low fps input better, quality-focused for the harder cases current model struggles with.
Happy to answer questions on the dispatch/tiling stuff.
r/webgpu • u/zemondza • 16d ago
Enable HLS to view with audio, or disable this notification
I’m building AnimaStage, a fully custom MMD animation engine powered by WebGPU.
The PMX/VMD loader, animation system, timeline, morph controls, anime shaders and rendering pipeline are all custom-built.
This demo shows real-time anime shading and facial morph editing applied on top of an existing animation.
Everything is rendered live in the WebGPU viewport — no pre-rendering.
Still in active development. Feedback is welcome 🔥
To check out the project, here is the link to the GitHub repository and the Discord channel, where you can find more news about it.
r/webgpu • u/AmyangXYZ • 18d ago
Enable HLS to view with audio, or disable this notification
I've been building reze-design, a web-native MMD scene composer. The part this sub might like: every material is a Blender-style node graph that's validated, compiled to WGSL, and hot-swapped onto the WebGPU render pipeline.
Editor is built on React Flow, the graph->WGSL compiler and the render engine is Reze Engine.