babble bin

learning webgpu or: How I Learned to Stop Worrying and Love the Render Pipeline

WARNING: this article is a stream of my consciousness, therefore wordy at times, and likely even incorrect, do not take these words as gospel!

for an ongoing gamejam, myself and other jammers are building games similar to conway’s game of life / falling sand games / cellular automata simulations

ALSO: this jam is ongoing, and this article currently does not end with any sort of resolution, a follow up post will be required to clue this up

while i’ve been intending to move towards using Godot for future jam entries, i felt like it would be a poor choice for this sort of jam, and that picking something more lower level would be both fun and (potentially) a requirement for a performant simulation

one of my own requirements as well, is to have the game easily playable via the web, hosted on a page no different than this one

i like games being accessible via a link, rather than requiring a download, especially if they’re a very short gamejam entry that honestly isn’t worth an entire install in the first place

i’m comfy enough with rust such that my initial choice was to use the Comfy engine, which i had seen before but never actually used

previously, i’ve mucked around with Bevy, a very popular rust game engine, but this style of game did not seem like something in which i would pick a full fat ECS for

after spending some time with comfy, i had a working basic game of life clone

it does the thing, and was decently performant! (at small grid sizes…)

fn update(state: &mut GameState, _c: &mut EngineContext) {
    let cells = &state.grid.cells;
    let size = state.grid.size as f32;
    draw_rect(splat(size / 2.0), splat(size), BLACK, 0);

    for (index, c) in cells.iter().enumerate() {
        if let &Cell::Alive = c {
            let y = ((index as f32) / size).floor() + CELL_SIZE / 2.0;
            let x = ((index as f32) % size) + CELL_SIZE / 2.0;

            draw_rect(vec2(x, y), splat(CELL_SIZE), PINK, 0);
        }
    }

    state.grid = step(&state.grid);
}

here is its very simple render loop, in which i iterate over each cell stored in a flat array with some floor division / remainder math to give me the proper x & y, and draw_rect the cell

the next step i took was to move from game of life to falling sand, which included:

here’s the link to this version

as you can see:

this is a biiit laggy already…

i’m most likely doing something stupid here that’s causing this to happen, and someone with more brains than i currently have in the graphics department can probably walk into this codebase and sprinkle a few lines here and there to make it much faster

but, i just want to make sand game, and make it quickly

running into issues like this, this early, did not feel great

my guess for the lack of performance, is that i’m having to draw_rect each cell every single time i want to draw the next step

so for example, if i have a full 512x512 grid, that’s potentially 262,144 draw calls…

while comfy does use wgpu under the hood, which itself does speak to the graphics card, i don’t believe my current code is able to make use of it much, and each draw_rect call must be processed on the cpu one-by-one

after briefly looking into the posibility of getting more hands on with the underlying code between comfy and wgpu, and/or writing a shader to offload the drawing logic, i decided it wasn’t a route worth looking into, given the timeline of the jam


funny sidenote, at the time of writing this article, the creator of comfy posted a lengthy blog post titiled ‘Leaving Rust gamedev after 3 years’ , which honestly while i don’t have a ton of the skin in the game, i seem to agree with basically all points brought up in this article, so its maybe a good thing i stepped away from rust…


so i’m not going the above comfy route, where else should i head?

if i want lower level gpu access, and also want to have whatever i create playable on the web, a potential answer is WebGL, which is what another gamejam pal of mine dan has already done, and is documenting on his own blog

i don’t want to copy him, but also i’d like to utilize similar tech to him, so…

its webgpu time


time for a little webgpu historical explainer

i say little, because if you’d like a longer better explainer, read this instead


graphics are hard

computers that did graphics before dedicated graphics cards, had to deal with cpus for pushing pixels to the screen

cpus are great for lots of things, but not built for being given a lot of simple tasks to complete within a very short period of time

the screen wants the frames to show the user NOW, the cpu is simply not built to deliver them if each one takes more than 16ms to render, and that doesn’t count time spent doing non-rendering tasks!

specific hardware to do graphics existed in the 80s, but it was a wild world of each device potentially having its own approach, needing software to be written specifically for it

it was not out of the question for a game/software package either to only be playable/usable on a single device, or require the programmer to have design multiple backends for each device


silicon graphics was a company in this space, and built their own higher level immediate mode graphics rendering api called IRIS GL, intended for use on their own workstations

they eventually released an open source package in 1992, called OpenGL, which was based on their previous proprietary api

eventually the Khronos Group was formed in 2000, a consortium which became the steward body behind opengl, and the breeding ground of many other graphics standards

there has been a succession of different opengl flavors / releases over the years, adding new functionality and attempeting to keep it relevant

opengl is epic, and has been used by many programmers over the years, and influenced other modern specifications

however… these days its considered a bit antiquated

i’m not saying its invalid to be learning / using it these days, since its still one of the more easier libaries in the space to learn, but:

libaries such as Vulkan, Direct3D 12, and Metal, have become very popular, with most major engines / games moving towards targeting them alongside, or straight up instead of opengl

they all hold your hand a lot less, permitting for much greater control for what the gpu is actually doing, therefore greater potential for performance and fidelity


as mentioned before this historical overview, one of my pals is using webgl for his entry

webgl started development as an experimentation around 2006, with a working group being formed under the khronos group in 2009, hitting a stable release in 2011

if you look at the postfix of webgl, you might guess that it’s related to opengl, and you’d be correct!

webgl is based off of the OpenGL ES api, and was exciting when it was released, since now browsers could speak directly to the graphics card without an intermediate high level api (html5 canvas), or needing an external plugin (flash/applets, shudders)

however, similarly to how there was an appetite from folks to move away from opengl to other modern approaches, it also follows that webgl would need to follow suit

as you might be guessing, this is where WebGPU comes in

WebGPU logo

webgpu started as an idea from google in 2016, presented during a webgl working group meeting, as webgl next

it eventually grew to be a proposal for a new api called webgpu, since aspects of it were different enough it should distance itself by name from its predecessor

webgpu targets vulkan, metal, and direct3d 12, meaning great cross platform support, alongside being directly accessible via javascript in the web browser, similar to webgl

what’s cool is that, unlike webgl, since its not just a rehash of another graphics library, its a viable choice as rendering backend for native applications that wish to target multiple platforms

a very cool non-web example is playbit, an operating system with webgpu as its only user-space graphics api

while doing a quick search for webgpu on youtube, i ran into this video, which is also a great watch if you’re interested in webgpu outside the browser


as of the writing of this piece, webgpu has yet to see a proper release, and is still considered a w3c working draft

however, support is increasing, and thankfully enough to the point that if you’re using chrome on windows or mac, you should already be golden!

firefox is lagging behind, and linux specifically is still a bit spotty, but with some flag finagling you can enable it (although i personally still ran into issues with firefox nightly, which forced me back to chrome on linux…)

while at the moment this does mean my game might not be as accessible to folks without webgpu support… it eventually will be, and that’s good enough for me!


while looking for a good webgpu tutorial, i ran across this one from google

its… a tutorial on how to build a game of life clone…

this does feel like cheating a little bit, but, since i’m in super uncharted territory, and i intend to yet again rip out the conway bits to replace with falling sand, i proceeded


now, i could take chunks of the above tutorial and place an abridged version of it here, but since i don’t have much to add ontop of what the tutorial already states, i’m just going to give my current opinion of webgpu, and outline my plan going forward for this jam


first, here’s what i have at the end of following tutorial:

its conway! its colorful, and if i crank up the grid size, its nice and snappy

quite happy the tutorial ended up teaching concepts such as instancing and compute shaders, each cell is actually the same 9 verts / 2 tris / 1 quad moving around the screen with some vertex shader trickery

@group(0) @binding(0) var<uniform> grid: vec2f;
// ...

@vertex
fn vertexMain(@location(0) pos: vec2f,
              @builtin(instance_index) instance: u32) -> VertexOutput {
  let i = f32(instance);
  let cell = vec2f(i % grid.x, floor(i / grid.x));
  // ...
}

to get proper types working, i had to install a package called @webgpu/types, but once i had that, tsc was nice and quiet

i picked Solid.js as what i have creating the canvas

while this currently seems overkill, once i have some falling sand game ui elements, this should be nice :)


while i want to say something about webgpu and sound really clever

i don’t have much to say!

its fun to write, for the little i have written, and i am excited to write more

the idea of learning something which does not limit where i can run it, is fun

and making color pixels pop up on a screen quickly is a blast


while this is a bit of an anticlimatic way to end this babble bin entry, i’m hopeful for using the stack going forward with the jam, and for using webgpu for future projects

fingers crossed webgpu lands with great support across all modern browsers, and also fingers crossed i follow up this post showing off a great sand game

only time will tell :)




any thoughts about any of the above?

reach out: