First Public Working Drafts: WebGPU and WebGPU Shading Language
w3.org
w3.org
The upside is that it's very pleasant to program compared with existing APIs, and is portable. Even when the GPU doesn't quite meet the requirements, it's possible to polyfill compute shaders with SwiftShader. As this standard becomes more mature, it will be reasonable to expect that it will be correct and performant pretty much everywhere.
Note that both web and non-web implementations are viable.
The biggest drawback is that the "MVP" covers the basics of compute shaders but not the advanced features. It's roughly equivalent to DX11 / Shader Model 5, which is of course good for compatibility on pre-Windows 10 devices. It's missing subgroup operations, scalar types other than 32 bits, an explicit memory model, and some other goodies. This potentially leaves quite a bit of performance on the table, but that will depend on the exact workload. For example, machine learning inference workloads will probably suffer considerably due to the lack of f16. Thus, if you want to ship something based on compute shaders today, it makes sense to build your own portability layer on top of existing APIs such as Vulkan, DX12, and Metal.
I do think WebGPU is an excellent on-ramp to learning compute shader programming, as it will get stronger over time, and concepts will transfer to other APIs as listed above.
Watch my Twitter feed for more depth on the points I listed above.
Would those limitations still apply with SPIR-V?
wgpu historically accepts SPIR-V, but the latest version released ~a month ago has moved to WGSL as much as it can in the examples. Have you upgraded yet?
In the game world, it is very common to write shaders in HLSL because of good support on Windows, and then use the tools mentioned above to translate into other shader languages. I explored this for my own work but ultimately settled on GLSL because it allows access to advanced features.
Fans of shader languages should also be aware of rust-gpu, which promises to be considerably higher level; most existing shader languages show their clear lineage to C (through Cg).
The official shader language for WebGPU is WGSL, and that will almost certainly be the only language supported for web deployment. Originally this was going to be a textual representation that had exactly the same semantics ("bijective") as SPIR-V, but that's been diverging a bit[1]. Only very recently have atomics been added to the spec, and implementations are still catching up.
Because WGSL is still under construction, for native deployment, wgpu supports SPIR-V shaders as well. On Vulkan, those are passed pretty much straight through to the GPU driver (with some validation). On DX12 and Metal, those are translated into HLSL and MSL, respectively. Until recently, in wgpu, all those translations were handled by spirv-cross. More recently, the new naga crate is doing those translations. Again, this is under construction and not everything works yet.
[1]: https://kvark.github.io/spirv/2021/05/01/spirv-horrors.html
I don't know if this is a good place to ask. But I was interested in wgpu because of the interest in building a cross-platform non-web UI library. I read a few of your articles and also looked at druid. I am pretty new to it and there seems to be no books on this topic. Do you have any recommendations?
More seriously. There is very good reason to be encouraged about wgpu as a cross-platform low-level GPU drawing interface for UI work. There are already successful UI toolkits using it, of which probably the most impressive is iced.
For 2D graphics in general, a good starting point is Diego Nehab's 2D graphics course. It has links to a bunch of resources including papers on GPU rendering.
Of course, I'm working on my own stuff, which in time I hope will become a very strong foundation for building things such as UI toolkits, but it's not ready yet, and of course you're already aware of it.
Yes, I agree building a UI library from scratch is hard and probably not worthy doing (too many people tried and gave up in the middle; probably better to channel that enthusiasm on improving existing ones). I should state that more clearly. I was looking at something more modest, like a canvas implementation based on wgpu that enables others to build their UI libraries on top.
I guess it would be something like Skia, but it also sounds like a tremendous effort, and I could probably just use Skia instead. However, I guess I am not going to match what Skia has (maybe what HTML canvas has is enough?). Also, I have played with skia-safe crate but I personally feel the dev experience could be better (not to blame skia-safe, it's wonderful and even provides a build process that automatically downloads a precompiled skia library).
Thanks for pointing out Iced. I didn't know they are using wgpu under the hood. I will take a good look at their code. I have been reading nannou's code to learn how to work with wgpu. If we skip my last paragraph, I think building a UI library on top of nannou is pretty doable.
> When writing SPIR-V, you can’t have two integer types of the same width. Or two texture types that match. All non-composite types have to be unique for some reason. We don’t have this restriction in Naga IR, it just doesn’t seem to make any sense. For example, what if I’m writing a shader, and I basically want to use the same “int32” type for both indices and lengths. I may want to name these types differently
This doesn't really make sense for IR. IR is not meant to be human writeable. It's meant to be generated by a compiler. So, having a one to one mapping between concept and name in the IR is a feature, not a bug.
Honestly, WGSL just repeats the JavaScript mistake: where we should have started with something like WASM instead of JavaScript. And JS could have been just one of the many languages that targeted WASM.
We were this close to not repeating this mistake by adopting an IR language (SPIR-V) for WebGPU, but then that got abandoned mostly for political reasons. Too bad. Now we get to write transpilers and hacks for decades to come, just like web people have been trying to paper over JS problems for decades.
Do you consider the name for a type to be a part of the concept? SPIR-V doesn't. Overall, if you wanted one-to-one mapping, at least that would be consistent. But SPIR-V decided to require this only for simple types, while you can still have duplicate composite types.
> Honestly, WGSL just repeats the JavaScript mistake: where we should have started with something like WASM instead of JavaScript. And JS could have been just one of the many languages that targeted WASM.
We don't know if Web would be nearly as successful if it started with WASM instead of JS. The ability to just open a text editor and make a web page has served well in the early days.
> We were this close to not repeating this mistake by adopting an IR language (SPIR-V) for WebGPU, but then that got abandoned mostly for political reasons.
Look at the situation today: the very same people who were rooting for SPIR-V are currently introducing features the diverge WGSL away from SPIR-V, further and further. It's quite telling, I think. The moral of the story is: regardless of reasons (which we can argue a ton), WG members admit that what we ideally need is not SPIR-V, and this is supported by the way WGSL is shaping.
And you would be able to do that just fine. All you'd need to do is include the JS compiler (helpfully hosted at http://cdn.google.com/ecmascript-2015.wasm) in the <head> of the HTML file's script tag, open a text editor and type away. Or, you know, include a more sane language like typescript, or python. Heck even lisp if you're so inclined. Or, and this is like totally crazy, but say you need performance, and want tight control over memory layout and allocations, then go for C or rust! Oh and no need to minify your JS. Just ship the WASM precompiled. Save on browser compilation time and network bytes at the same time. So long as you generate WASM that the browser understands use whatever lang makes you happy. Type it right into a text editor and include the compiler in the head of the HTML. Easy peasy.
It's without question that JS has held back web development for decades. Of course, people didn't know any better back then, and really JS was added as almost an afterthought, so we can't really blame them for getting it wrong.
We do know better now though. And still we get WGSL. Looking forward to 2041, when we finally get WGASM. The hottest new thing in web gpu technologies.
In restrospective I wasted a couple of years of my life beting on OpenGL, and keep seeing the same errors in all Khronos related APIs.
It is not only WebGPU, check how many extensions Vulkan has already.
Then there is OpeCL C++ versus SYSCL, OpenCL 3.0 is actually 1.2 rebooted,...
Now that basically all relevant browsers are evergreen (sit down, IE11) I wonder whether an API roadmap could take advantage of that in a way that's less pesky than the traditional approaches.
Note that not even with the same browser version there are any guarantees regarding GPGPU support.
A big difference between browsers and native 3D APIs is the blacklisting of client hardware/drivers, so one never knows what is actually being accelerated.
It is a ray caster that I plan to evolve into a nonlinear ray caster where the viewing rays travel along a vector field which thus distorts the image. You can enable the nonlinear mode by setting the "linear_mode" constant in "src/compute.wgsl" to false. I also implemented hot reloading for the shaders, which made experimenting a lot easier. The project doesn't have any non-Rust dependencies, so giving it a go is as easy as "cargo run" in the repository directory. For an idea of what I'm aiming for, see the "Visualizing Strange Worlds" paper by Eduard Gröller from 1995: https://www.cs.drexel.edu/~david/Classes/Papers/Groller95.pd...
You can also drag&drop .obj models to load them, but I advise you to only use small models (500 triangles max) in linear mode and completely avoid it in nonlinear mode right now, as the performance is really bad at the moment. :) I'm looking into acceleration structures next, so hopefully this will improve.
I'm curious if such catastrophic behaviour is inherent to the WebGPU API as specified, or of the current implementation is failing to provide the level of safety that it should according to the spec?
It's worth noting here that the Python wgpu library (which I'm assuming is the one GP is referring to?) is a WebGPU-inspired API to wgpu. wgpu is the library that Mozilla created as a native graphics abstraction layer to build WebGPU on top of. It's possible that Mozilla has implemented (or intends to implement) the security/validity checks between wgpu and the JavaScript interface exposed to the browser, in which case they would not automatically apply to the Python bindings.
Was it a Mozilla-originated project that has been moved to gfx-rx, or has if always been separate?
The long term plan is to remove all support for any kind of kexts.
As presented at WWDC, after a kext gets a userspace alternative, its support is removed on the following OS release.
Working Drafts are essentially just "drafts with stable URLs for review purposes and historical interest".
First Public Working Drafts also have consequences under the W3C Patent Policy, primarily starting a timer under which any participant of the group has to say they wish to exclude any patents they hold from the W3C royalty-free grant.
I do think WebGPU can be a great cross-platform compute shader framework outside of the web. My experience with compute shaders is that they're really really platform specific: you need not just the right OS, but also the right graphics chip. It would be nice to write cross-platform high-end 3D apps without relying on Unity or Unreal.
Also, hopefully WebGPU has better debugging tools (if they're even possible). I tried GPU programming before but it's a mess: almost every example I tried to run crashed terribly (e.g. system reboot), and even at best, I couldn't get much debugging output other than "code = problem".
Who is saying that? Genuinely curious. It has strong buy-in from Apple, Google and Mozilla, and all 3 are implementing the spec right now (and updating implementations as the spec changes). Seems very doubtful that it'd take anywhere near 10 years to be supported by major browsers. I guess it depends on what subset of graphics/compute features you need for it to be viable for your specific use case.
> Development of the WebGL 2 specification started in 2013 with final in January 2017
Moreover, WebGL2 support was only added to Edge since January 2020, and as of now it's still not supported in Safari (excluding Safari TP) (from https://caniuse.com/webgl2).
GPU drivers are really buggy, especially if you try to cope with what is installed vs prompting users to upgrade their os or drivers.
During last week's meetup from Khronos the only suggestion was the native tooling like PIX.
Some examples:
- The fullscreen and pointerlock APIs show popup warnings which behave entirely differently between browsers.
- Timer precision has been reduced to around 1ms post-Spectre/Meltdown, and jittered on top. This makes it very hard to avoid microstuttering (we don't even need a high-precision timer, just a way to query the display refresh rate... but guess what, there is no way to query the display refresh rate)
- WebAudio is ... I don't even know what... all we need is simple buffer streaming but we got this monstrosity of a node-based audio API. And the only two ways to do this in WebAudio are either deprecated (ScriptProcessorNode) or not usable without proper threading (audio worklets), and guess what, threading is also disabled or behind HTTP response headers post-Spectre.
- Games need UDP style non-guaranteed networking, but we only get this as a tiny part of WebRTC (DataChannels).
...and the list goes on. In theory there are web APIs useful for gaming, but in practice those APIs have been designed for entirely different and very specific high-level use cases (such as creating an audio synthesizer in a webpage, or creating a video chat solution for browsers), and those rigid high-level APIs are not flexible enough to be reassigned to different use cases (like games). The web needs a "game mode", or better a "DirectX initiative", a set of low level APIs and features similar to WASM and WebGL/WebGPU, and if not designed specifically for games, than at least low-level and generic enough to be useful for games.
This isn't a new idea, see the Extensible Web Manifesto:
https://extensiblewebmanifesto.org/
(backup: https://github.com/extensibleweb/manifesto)
But the ideas presented there didn't seem to have much of an impact with the web people (with the notable exception of WebGPU).
> threading is also disabled or behind HTTP response headers post-Spectre
It seems like you've written a long-winded complaint that you have to add a http header (like this[0]) to your server's response? Though it's true that the Spectre stuff broke everything for a little while there (and there are still ergonomics-related teething problems with headers that are being worked on).
> Games need UDP style non-guaranteed networking, but we only get this as a tiny part of WebRTC (DataChannels).
WebRTC DataChannels work fine though? Does it matter that it's a small part of the whole WebRTC spec or that server-client use is a bit of a hack? Either way, WebTransport hits origin trial in Chrome in about a week, and it's specifically designed for UDP-like client-server communication, so the WebRTC approach can be swapped out once that is stable.
So how does this work on Github Pages or other hosting solutions where the user has no control over the web server configuration?
> WebTransport hits origin trial in Chrome in about a week
How long until this shows up in Firefox, and will Safari ever support this before it's deprecated in Chrome again because another better solution shows up?
Spectre called for some drastic measures, and it'll be up to Github/Netlify to decide how they react. Developers who want simple hosting solutions for their little projects will host elsewhere (e.g. replit.com, glitch.com) if they need to. This isn't exactly a massive obstacle if you've set out to build a complex game in the browser. It's just a couple of headers...
>How long until this shows up in Firefox
WebRTC data channels work fine in the mean time. Have you seen games like krunker.io and dotbigbang.com et al? It's perfectly possible to create real-time games in the browser using WebRTC.
More generally things get a lot simpler if you’re “web first”. It’s a lot easier to just be pragmatic about it and build when you’re not straight jacketed by existing designs reliant on common low level OS APIs.
It is an obstacle (at least a massive annoyance) for library authors (like this: https://github.com/floooh/sokol). Those libraries can be used for extremely simple and small WASM snippets embedded in blog posts (like here: https://floooh.github.io/2019/01/05/wasm-embedding.html), or in "proper" games hosted through "proper" hosting services which allow to set the response headers.
Right now the choice is to either support WASM threading, but tell library users that the library will most likely not work on the hosting solution of their choice, or not support WASM threading and work everywhere. At least to me it's clear that "works everywhere" is better than "it's complicated", so I'll ignore WASM threading until the problem is solved somehow (either most hosting services turn on those response headers, or there's another way to enable threading without requiring control over the web server configuration).
Yeah that's a completely fair point. Ruffle dev makes a similar argument up-thread: https://news.ycombinator.com/item?id=27199260
Netlify already allows full control over headers even on their subdomain, including COOP/COEP.
In our experience the average webmaster does not know how to configure proper HTTP headers and should not be expected to for a basic web library. So any web API that will not work with the standard web server configurations of Apache, nginx, or IIS is a non-starter for us. (Not to mention that the site isolation headers have non-trivial implications for sites that use iframes...)
I noticed this update on the https://web.dev/coop-coep/ article recently:
> We've been exploring ways to deploy Cross-Origin-Resource-Policy at scale, as cross-origin isolation requires all subresources to explicitly opt-in. And we have come up with the idea of going in the opposite direction: a new COEP "credentialless" mode that allows loading resources without the CORP header by stripping all their credentials. We are figuring out the details of how it should work, but we hope this will lighten your burden of making sure the subresources are sending the Cross-Origin-Resource-Policy header.
Overall, WebRTC is a poorly designed protocol which will be quickly obsoleted.
If I understand it correctly, WebRTC requires you to open a range of thousands of ports and kubernetes load balancers are designed to forward individual ports to individual services.
https://github.com/pion/webrtc/issues/639
https://github.com/pion/webrtc/wiki/Big-Ideas#single-port-mo...
It's not just very hard to avoid microstuttering. It's quite literally impossible. And it's not just the timer precision. Chrome's `requestAnimationFrame` actually provides a full precision frame start time, but even if all your page does is render a single solid-color triangle (that alternates between cyan and magenta every frame), you still cannot avoid microstuttering, because the compositor will periodically drop frames. Ironically, the browser engines on mobile phones seem to do better, presumably because of limited multitasking.
Source: I've spent more hours than I care to admit trying to avoid dropped frames in https://sneakysnake.io . To see how bad it remains, check out the triangle in the bottom left corner of https://sneakysnake.io?dev=true . If it looks anything other than grey, then the browser is dropping frames.
It is quite telling that the cloud gaming efforts rather render everything server side with video streaming for the browser than fixing the games APIs on the browser.
[1] https://deno.com/blog/v1.8 https://news.ycombinator.com/item?id=26323600
It's a successor to WebGL, along the lines of newer graphics APIs like Metal/Vulkan/DirectX 12. Google and Mozilla are also developing a C-compatible library that should be available as an OpenGL alternative for native code.
So if successful it might end up as the most convenient cross-platform graphics library (across desktop/mobile/the web). Currently the alternatives in this space are:
- OpenGL (which Apple has deprecated and is stuck on an older version on their platforms)
- Vulkan, which is the lowest level and most difficult to get started on of the APIs, and also doesn't work on the web, but is supported on Apple systems by using the MoltenVK library to translate it to Metal
- some non-standardized libraries written by third party developers like bgfx and Oryol.
For the shading language they settled on a text based language designed to be easily translatable to/from Vulkan SPIR-V bytecode, with the goal of being able to re-use existing shader compilation toolchains (and most of the work put in to SPIR-V), while still having the ability to write/read shaders without a shader compiler. Also SPIR-V files are fairly large and apparently don't compress well with standard algorithms (see SMOL-V) so the text based format should probably be more efficient to transmit on the web.
There's basically zero uncertainty around this. It would break the internet. As you probably know it's extremely difficult to make even tiny backwards-incompatible changes to features that have become web standards and have been implemented on all major browsers.
To clarify, Google and Mozilla are both developing separate libraries: Dawn (in C++) and wgpu (in Rust) respectively. Both are designed to be usable behind the same native C API - https://github.com/webgpu-native/webgpu-headers
> For the shading language they settled on a text based language designed to be easily translatable to/from Vulkan SPIR-V bytecode
Going from SPIR-V has been anything but easy for us (in Naga/wgpu land), so far. Raph posted this link in the comment above - http://kvark.github.io/spirv/2021/05/01/spirv-horrors.html
Does this mean WebGL development/support has stopped?
At this point, I'm not even waiting for a new OpenGL version anymore. The good stuff has been mostly Vulkan exclusive for a while now.
With Vulkan Khronos keeps the OpenGL tradition of leaving as rite of passage to learn everything from scratch, while hunting for libraries, because community.
Don't expect Vulkan SDK to provide the confort of Metal Kit, DirectXTK, Playstation PhyreEngine, ....
WebGPU still isn't at the same comfort level as the frameworks provided by platform owners for their APIs.
Do you mean they're thinking "this can easily be translated to other graphic interfaces" or "we're going to convince vendors to ship products with WebGPU driver built-in like OpenGL"? I'll be so happy to see WebGPU on driver level, but can't find evidence on if anyone is interested in providing.
Looking at the various rendering backends for our product, the OpenGL backend is the most byzantine one. The Vulkan backend has more code, but all of that is fairly sane. It doesn't have accidental complexity like having to pick the right GL function to upload a specific texture out of about a dozen possibilities depending on the texture type and target OpenGL version/extensions.
The only thing that saves Vulkan is that it isn't as old as OpenGL, with a similar timeframe it will get just as bad, or even worse given its complexity for the average graphics programmer that doesn't hold a master on GPGPU hardware design to understand the nuances of all those extensions.
[[stage(fragment)]]
fn main() -> [[location(0)]] vec4<f32> {
return vec4<f32>(0.4, 0.4, 0.8, 1.0);
}---
That is very ugly and full of noise, c'mon people, that's one thing to like rust, but let's not import its ugly and noisy cluttered syntax..., it took me few seconds to understand what's going on there
---
var<private> x: f32;
---
let's not confuse things even more, we have vec4<f32> already, C'MON PEOPLE
https://github.com/bschwind/simple-game/tree/9de179085a04dd4...
If you combine it with a quick build step to give you shader compilation errors before your program runs, it becomes a pretty nice shading language. There are still a few rough edges but it's not _that_ bad to work with.
Potential misuse should not stop WebGPU from moving forward, but isn’t there a concern that the make JavaScript injection attacks more attractive? Rather than buying and operate a crypto mining setup it now becomes more attractive to attempt to utilize the GPUs of unsuspecting web users. Or am I misunderstanding how much of the GPU this will grant you access to?
Neither WebGL nor WebGPU will today give you 100% of native (e.g. CUDA) performance for applications like coin mining or machine learning. And even WebGPU may never get all the way there, at least in a form that can be exposed in browsers, because top performance requires deep knowledge of the user's specific hardware configuration and specialized hardware-specific code paths. Exposing that to the web raises legitimate fingerprinting and portability concerns.
That said, I think there is a lot of promise for WebGPU as a portable graphics API for native applications outside of browsers, where said fingerprinting and portability concerns are much less of an issue. In a native context, hardware-specific extensions could easily be exposed and there's no reason in theory why you couldn't have the best performance possible on any given hardware.
Mine isn't. Disabling WebGL is DEFINITELY on the checklist for a new browser profile
GPUs are way too complicated, way too opaque, and way too privileged to be safely exposed to the Web. We're not talking about some Web page using your machine to mine crypto here. We're talking about some Web page owning your kernel.
Kill it with fire.
I don't know of any other browser feature with that track record.
For what it's worth, the overall WebGPU spec draft (rather than the shader spec) has a section on security/malicious use: https://gpuweb.github.io/gpuweb/#malicious-use
GSL and WGSL are completely unrelated, apparently time to rewrite shaders.
And in what concerns debugging, better get good at understanding what is the actual application code and browser own rendering engine, as the best solution keeps being to use native GPGPU debuggers.
Failure #1: to get operating systems to ever agree on a truly common API for most modern computing
Failure #2: to implement a write-once, run-anywhere language capable of being used for the majority of software development (mostly because the main efforts at doing so all rely on VMs that come with their own costs and benefits)
Conclusion: just give up. Postulate the existence of a virtual machine inside a web browser. Spend a decade or three slowly extending the scope of that virtual machine. Put in a little bit of effort to persuade people that this new, evolving VM is the new key to "write once, run anywhere".
Result: a new platform, distinct from all the rest (i.e. "native") with its own costs and benefits.
Whoo-hoo.
A WebGPU miner will be coming out the same second it is adopted.
You can turn off local storage, cookies, sound and javascript itself in per page permissions, you think every web page is going to have an unavoidable crypto currency miner embedded in it when webGPU becomes more common?
Do you think that people won't be able to see that a specific iframe is using 99% of their GPU or do you think people will just live with it and won't care?
I don't even think that you really believe this.
But seriously, why do they reinvent the wheel? Either make javascript work on the GPU (because that's the language of the web, just like C++ and Cuda go hand in hand), or just stick with HLSL.
Allegedly GLSL and HLSL do not come with enough protections / guarantees for anyone to have felt comfortable porting them to the web. That rules them out cleanly.
Also, these are both fairly legacy technologies, both predating Vulkan by a good bit more than a decade. WebGPU at it's core is a remake of Vulkan for the web. Then there's a shading language that works with this base. My understanding is this is a far more competent, capable means of setting up & orchestrating work, so that it can happen & flow effectively on GPUs. Doing less than WebGPU sounds supremely unappealing.