A simple blog post doesn't need super fancy design when its content can speak for itself.
Raw HTML definitely looks much uglier, sadly (“Reader mode” in most browsers makes websites without CSS easily readable, though!).
pretty much all HTML, with only the bare minimum CSS to make it somewhat responsive.
I guess if you want one tiny piece of feedback, based on the above site:
>A little less contrast
>Black on white? How often do you see that kind of contrast in real life? Tone it down a bit, asshole. I would've even made this site's background a nice #EEEEEE if I wasn't so focused on keeping declarations to a lean 7 fucking lines.
I agree with the advice, but I've definitely seen many a heated debate over raw black on raw white amongst designers. So take with a grain of salt and a handful of personal preference.
In books. If you have really high-end hardware where you have enough contrast to be painful, turn down your contrast setting. On regular-person devices, grey-on-grey is needlessly hard to read, and there's no way to turn the contrast up without introducing clipping.
I took the opposite approach, and it has cause great pain. I've been writing a metaverse client in Rust. Right now, it's running on another screen, showing an avatar riding a tram through a large steampunk city. I let that run for 12 hours before shipping a new pre-release.
This uses Vulkan, but it has WGPU and Rend3 on top. Rend3 offers a very clean API - you create meshes, 2d textures, etc., and "objects", which reference the meshes and textures. Creating an object puts it on screen. Rust reference counting interlocks everything. It's very straightforward to use.
All those layers create problems. WGPU tries to support web browsers, Vulkan, Metal, DX11 (recently dropped), DX12, Android, and OpenGL. So it needs a big dev team and changes are hard. WGPU's own API is mostly like Vulkan - you still have to do your own GPU memory allocation and synchronization.
WGPU has lowest-common-denominator problems. Some of those platforms can't support some functions. WGPU doesn't support multiple threads updating GPU memory without interference, which Vulkan supports. That's how you get content into the GPU without killing the frame rate. Big-world games and clients need that. Also, having to deal with platforms with different concurrency restrictions results in lock conflicts that can kill performance.
Rend3 is supposed to be a modest level of glue code to handle synchronization and allocation. Those are hard to do in a general way. Especially synchronization. Rend3 also does frustum culling (which is a big performance win; you're not rendering what's behind you) and tried to do occlusion culling (which was a performance lose because the compute to do that slowed things down). It also does translucency, which means a depth sort. (Translucent objects are a huge pain. I really need them; I work on worlds with lots of windows, which you can see out of and see in.)
The Rust 3D stack people are annoyed with me because I've been pounding on them to fix their stack for three years now. That's all volunteer. Vulkan has money behind it and enough users to keep it maintained. Rend3 was recently abandoned by its creator, so now I have to go inside that and fix it. Few people do anything elaborate on WGPU - mostly it's 2D games you could have done in Flash, or simple static 3D scenes. Commercial projects continue to use Unity or UE5.
If I went directly to Vulkan, I'd still have to write synchronization, allocation, frustrum culling, and translucency. So that's a big switch.
Incidentally, Vulkano, the wrapper over Vulkan and Metal, has lowest-common-denominator problems too. It doesn't allow concurrent updating of assets in the GPU. Both Vulkan and Metal support that. But, of course, Apple does it differently.
WGPU uses WebGPU and AFAIK no browser so far supports "threads". https://gpuweb.github.io/gpuweb/explainer/#multithreading https://github.com/gpuweb/gpuweb/issues/354
And OpenGL never supported "threads", so anything using OpenGL can't either.
But even more common is mapping memory in "OpenGL thread" and then letting another thread fill the memory. Quite common is mapping buffers with persistent/coherent flags at init, and then leave them mapped.
WGPU goes beyond WebGPU in many ways already, and could also support threads.
The first part is true, but the second part is not. Allocation and synchronization is automatic.
Metal is older than Vulkan. So really, Vulkan does it differently.
This is really helpful for me to learn about, this is a key thing I want to be able to get right for having a good experience. I really hope WGPU can find a way to add something for this as an extension.
OpenGL was never "easy" but it was at least something a regular person could learn the basics of in a fairly short amount of time. You could go to any big book store, buy some intro to graphics programming book, and get some basic stuff rendering in an afternoon or two. I'm sure Vulkan is better in some regards but is simply not feasible to expect someone to learn it quickly.
Like, imagine the newest Intel/ARM/AMD chips came along and instead of being able to write C or C++, you're being told "We are dropping support for higher level languages so you can only write assembly on this now and it'll be faster because you have more control!" It would be correctly labeled as ridiculous.
Generally, I feel OpenGL is the recommended route if you don't really aim for advanced rendering techniques.
There are plenty 2D /lowpoly/ps1-graphics games right now, and those don't need to use vulkan.
Vulkan is an example of how the AAA gaming industry is skewed towards rendering quality and appearance. AAA game studios justify their budget with those very advanced engines and content, but there is a growing market of 2D/low poly game, because players are tired and realized they want gameplay, not graphics.
Also if you are a game developer, you don't want to focus on rendering quality, you want to focus on gameplay and features.
One that stuck out to me: Don’t implement something unless you need it right now
This is a constant battle I fight with more junior programmers, who maybe have a few years of experience, but who are still getting there.
They are often obsessed with "best-practices" and whatever fancy new tool is trending, but they have trouble starting with the problem they need to solve and focusing on the minimum needed to just solve that problem.
the Vulkan driver is missing that ~20k loc of code that OpenGL driver does for you to set up the rendering pipelines, render targets etc.
This is all code that already exists in the OpenGL driver and has been optimized for +20 years by the best people in the industry.
So when you start putting together the equivalent functionality that you get out of the box with OpenGL on top of Vulkan doing it the naive way doesn't magically give you good perf, but you gotta put in some more work and then the real problems start stacking up such as making sure that you have all right fences etc synchronization primitives in place and so forth.
So only when you actually know what you're doing and you're capable of executing your rendering with good parallelism and correct synchronization can you start dreaming about the performance benefits of using Vulkan.
So for a hobbyist like myself.. I'm using OpenGL ES3 for the simplicity of it and because it's already good enough for me and I have more pressing things to matter than spend time writing those pesky Vulkan vertex descriptor descriptor descriptors ;-)
Btw this is my engine:
They all introduce another layer of abstraction on top of Vulkan even before giving you the simple case without it. Its always use vk-bootstrap, volk, vma or someother library.
Is there a single resource anywhere that gives an example of doing the memory management manually because I havent found one, it seems like its either use vma or go figure out the spec are the only choices you are given. Is it too much to ask to just get the most basic example without having to add any libraries other than the Vulkan sdk itself?.
One thing I found difficult is understanding how to use things in a real engine rather than a sample. A lot of samples will allocate exactly what they need or allocate hundreds of something so that they're unlikely to run out. When I was trying to learn DirectX, I found Microsoft's MiniEngine helpful because it wasn't overly complex but had things like a DescriptorAllocator that would manage allocating descriptors. Is there something similar for Vulkan?
Another thing I struggle with is knowing how to create good abstractions like materials, meshes, and how to decide in what order to render things. Are there any good engines or frameworks I should study in order to move beyond tutorials?
For descriptor set allocation, there is only one pattern that nakes sense to me: expect the pools to be rather short lived and expect to have many of them. Allocate a new one once allocation from the current one fails - don't keep your own counters for alocated descriptors. The standard allows for all kinds of pool behaviors that deviate from strict counting. Discard old pools after the the last command buffer referencing that pool is finished.
Pipeline barriers and image layouts are a big pain in the butt. It makes sense to abstract them away in a layer that tracks last usage and lat Format for everything and adds barriers as required. It can get complex, but ot's worthbitnonce you have optional passen or passes that can get reordered or other more complex things going on.
About neshes, materials, rendering order: this goes beyond what I can summarize in a single HN post. This depends a lot on the choice of rendering algorithms and I do not consider a very generalized solution to be worth the (enormous) effortto get this right.
Vulkan initialization and basic swapchain management is very verbose, but things get much better after you do it for the first time and make some handy abstractions around pipeline creation/management later.
I'd like to see them move nearly all 900-ish lines of SLOC back down into the near 90-ish you'd need to initialize OpenGL.
There's so much overlap in basically everyone's graphic usage of Vulkan that you realize after doing it yourself they should have done some simple optimization for the 99% use case, and allowed other people to write the full 900+ lines for GPU compute or other use cases.
For example, his quick sidebar to explain fundamental shader types was great even for me, as someone who is not that familiar with the topic (link goes to 11:20):
I can also recommend Arseny Kapoulkine YouTube channel[1]. It can get a bit too advanced at times, but his channel was one of my motivators of getting into Vulkan programming.
If you want to support those other devices you have to have a non-dynamic rendering path, and then at that point dynamic rendering is just more code. VK_EXT_shader_object is even better, but availability is that much worse.
Edit: If you are able to find a tutorial using dynamic rendering, learn with that. Render passes obfuscate what's going on, and with dynamic rendering you can see exactly what's happening.
In my experience being daunted ans not knowing where to start is a large part of the difficulty in doing difficult things.
Great write up. Inspiring.
I try to make my website to feel like “the old Internet” that we seem to be losing and it's great that it’s noticeable. :)
* Noita
* Teardown
They both do their physics on GPU which results in some impressive effects and the level of destruction/world interaction which wasn't seen anywhere before.
Here's an interesting Teardown engine overview by its devs: https://www.youtube.com/watch?v=tZP7vQKqrl8
OpenGL is only deprecated on MacOS, AFAIK, it will exist for many years to come.
I'm sure Vulkan is better in some regards but is simply not feasible to expect someone to learn it quickly.
Vulkan is often said to be more of a “GPU API” than a high level graphics API. With that in mind, the complexity of Vulkan is not surprising. It’s just a difficult domain.
Like, imagine the newest Intel/ARM/AMD chips came along and instead of being able to write C or C++, you're being told "We are dropping support for higher level languages so you can only write assembly on this now and it'll be faster because you have more control!" It would be correctly labeled as ridiculous.
IMO, it’s more like single threaded C/C++ vs multithreaded C/C++ programming. There is a massive increase in complexity and if you don’t know what you are doing, it’ll blow up in your face and/or give you worse performance. However, it’s the only practical path forward.
Anyway, OpenGL can basically be implemented on top of Vulkan. Perhaps it is regrettable that the OpenGL standard is no longer being actively developed, but nothing lasts forever.
It's abandondend by Khronos and GPU vendors, which is pretty much the same thing as deprecated unfortunately.
What I would have really preferred is Apple releasing Metal as a standard that anyone could use. Metal is a pretty nice API that's fairly fun and easy to use. I feel like if we need a "next gen" version of a graphics API, I would have had Vulkan for super low-level stuff, and Metal or DirectX for higher-level stuff.
This really doesn't mean much. The second cube (or another shape) isn't going to double the line count.
> OpenGL was never "easy" but it was at least something a regular person could learn the basics of in a fairly short amount of time.
The problem is that OpenGL no longer matches current hardware so the naive way to use it is very much suboptimal for performance. Once you move to zero driver overhead techniques for OpenGL then Vulkan is not that much harder.
> Like, imagine the newest Intel/ARM/AMD chips came along and instead of being able to write C or C++, you're being told "We are dropping support for higher level languages so you can only write assembly on this now and it'll be faster because you have more control!" It would be correctly labeled as ridiculous.
Except current Intel/ARM/AMD chips don't support C or C++ and you already have to write assembly ... or use a third-party tool to do the translation from C or C++ for you. That's also the goal for Vulkan - to provide a low level standard interface for GPUs on top of which more user friendly abstractions can be layered.
It's like the difference between "Hello World" in Python and "Hello World" in Java. Doesn't matter in the context of a serious software engineering project, but it's a significant barrier for beginners.
That's an absurd standard. "Writing an OS is easy, because once you've written enough code to get Doom to run, firing up a second copy of Doom is relatively straight-forward!"
It's those first 600 lines that are the problem. There's now a steep learning curve and lots of boilerplate required for even trivial use cases, where there wasn't before. That's a loss.
> The problem is that OpenGL no longer matches current hardware so the naive way to use it is very much suboptimal for performance. Once you move to zero driver overhead techniques for OpenGL then Vulkan is not that much harder.
Again, mad standard. "Writing Vulkan shouldn't be a problem for people who write complex zero driver overhead code for OpenGL." Great. What about the other 99% of people?
I'm not against Vulkan for those applications that truly do need it, but - frankly - most graphics programming does not need it. In giving up OpenGL we're giving up a sane, standard way to do graphics programming, and exchanging it for a choice between (i) making everyone write mad Vulkan boilerplate for control they don't need, or (ii) choosing between a bewildering array of engines and frameworks and libraries, none of which work at all similarly, many of which are still very immature.
And it's obvious which one will win - whichever proprietary, SaaS monolith emerges to clean up the mess. Losing OpenGL is a huge set back for open standards, honestly. The principal beneficiaries of depreciating OpenGL will be the shareholders of Unity, in the end.
The terrible terrible Vulkan API just kind of feels gatekeepey. They got rid of the only open easy-to-use graphics standard, made NO REPLACEMENT, and then said "oh you should just use this impossible API or let the outside world come up with a fix around it".
I don't know how this lie caught on so well, but it doesn't pass the smell test.
https://github.com/google/angle
several phones now ship ANGLE as their only OpenGL support on top of their Vulkan drivers.
If you want a modern-ish API that's relatively easy and portable use WebGPU via wgpu (rust) or dawn (c++).
- No global state
- You can select which GPU you want to use at runtime
- OpenGL error handling is terrible
- Validation layers!!
- Cool official artwork
- Fantastic documentation
- You can upload data to the GPU asynchronously from a second thread in a sane way
- Fancy GPU features - Mesh shaders, RTX
I think the driver here is more likely the financial reality of game development. High-fidelity graphics are incredibly expensive, and small game studios simply cannot produce them on a realistic timeline and budget. Would consumers reject indie games with AAA-quality graphics? I think not. It's just that few such games exist because it's not financially viable, and there is a large enough market that is fine with more stylized, lower-fidelity graphics.
With current hardware and tools, it becomes much cheaper to reach graphics quality that is 10 or 15 years old, so such game would be just enough and be profitable enough.
I think that high quality rendering is reaching a tipping point where it's mostly of diminishing returns, this means AAA studios could differentiate with good graphics, but this becomes less and less true.
Gameplay matters, and the innovation is not the on the side of AAA studios.
Firefox and Safari don't support it yet. And how would you even deploy it to Steam (edit: or rather, make a desktop or mobile game with it)? Can you wrap it in a webview?
Doesn't seem mature...
There's no end of frameworks and engines out there, most unfinished, and all extremely opinionated about what your code must look like. ("You will build scene trees that hold callbacks. Actually no, you will write entity and component classes and objects. Wait, forget that, everything is immediate mode and functional and stateless now!")
Add all the platform nonsense on top (push notifications for a mobile game? In-app purchases? Mandatory signing via Xcode?) and it's all just a hot mess. There's a reason Unity has the market share it does, and it's not because it's a fantastic piece of software. It's because cross-platform for anything more complex than a glorified web view (which is, to be fair, most non-game apps) is still a massive pain.
Vulkan is a great idea for a general game engine or backing something like OpenGL. It's a low-level abstraction that should allow you to do something like use OpenGL 8.0 on a GPU that has long lost support for from its manufacturer.
Performance isn't an issue either - with the advent of GPU-resident drawing ,meaning a compute shader filling buffers with draw parameters and drawing multiple objects with complex materials in a single draw call means there isn't much of a CPU bottleneck. Look up OpenGL AZDO if you are interested in this.
OpenGL is kind of a middle ground. That's if you want to get technical, but not micromanage every detail and write pages of boilerplate. It is also a great introduction to graphics programming. More than an introduction actually, there is a lot you can do with OpenGL.
Unfortunately, Apple is holding every OpenGL app and dev hostage. It's officially deprecated by Apple. So OpenGL is not a viable cross-platform solution moving forward. Eventually, it will be completely removed from macOS, at which point it will just be an OpenGL to Metal converter that everyone uses, just like Vulkan with MoltenVK. So I feel it's better to use something like WebGPU moving forward that directly takes the stance that each OS will implement its own (perhaps multiple) backends. Unfortunately, it doesn't have the tutorials and learning material that OpenGL does. (This is from an inexperienced 3D person that's been looking into this a lot.)
> Remember that you can always rewrite any part of your game/engine later.
This isn't the case in medium to large organizations. Usually you will just move on and rarely have the time to revisit something. This is unfortunate of course, but it means you need to build things properly the first time around and make sure it won't have a chance to create bugs or side effects. I have worked in too many codebases were people feel the need to rush new features, and then it creates a minefield of a codebase where you have to manually check every feature and have the entire application in context when changing something small.
yes! and this means you need to know everything about what you're building upfront! so now you have to do waterfall, but hide all the actual effort and pretend you're just figuring it out in the moment because agile.
There are two poles: On the one side is making everything an unmaintainable pile of quick hacks, on the other side is over engineering everything. You want to be somewhere in the middle.
Don't back yourself into a corner. If a solution will block you from doing the right thing later, maybe some additional engineering may be needed after all to ensure you can continue to iterate. In large companies, inertia is enormous. Once a solution is in place and gets replicated, backtracking may become a herculean task.
Tell them YAGNI is also a best practice :D
To be fair if held strictly to these principles their work would revolve mostly around gluing together various Apis, services and sometimes adjusting already written software to company's needs. So I'm not surprised they are using every possible opportunity to write something here and there, this menial digital plumber's work takes its toll and one needs to try to squeeze in something a bit more enjoyable from time to time just to keep sanity in place a bit longer
When I WAS the bane of my existence was senior and staff engineers hoarding all the fun, new work for themselves and forcing me into "bitch work" where I'm just cleaning up old, broken code and handling bugs. I finally got promoted because I explicitly ignored my manager to deploy changes that were needed for my company, and that was what finally got me promoted. Of course, at that point, I had been looking for a new job and just left instead of taking the shitty, bottom-of-band promo increase.
It's awful for promotion chances, and it forced me to quit.
Useful advice to start with. It’s a rule that experts are allowed to break though.
I’ve observed/experienced the same exact thing [0]. I think it’s due to a combo of (1) not knowing what “the right way” to do things are and (2) thinking it’ll make your peers perceive you as more knowledgeable or advanced if they see you writing “best practices” code. Not to mention that sometimes the simpler solutions are so simple, they make you feel like you’re not a real software engineer. I usually just do my best to help them understand that simple solutions are okay, especially since (1) I’ve been there myself when I was in their shoes and (2) I know they have good intentions.
But there’s a fine line between implementing things but the difficulty being understanding long term vision and making sure short term improvements don’t actively work against the ‘ideal’. Kind of hard for newer programmers to get a good sense of system design.
This can go both ways, as senior devs can just want to use what they know.
i've heard that vulkan allows bindless textures now, so the descriptor nonsense is a bit less awful that it used to be
vulkan is appealing, but there's a high initial cost that i don't want to pay
Then gradually we can replace that library with routines optimised for the use case?
in most games, there are about 3 "lifetimes": - permanent/startup - per-level - per-frame
and they're nested. so, you can use a single stack allocator for all of them. at the end of the frame/level, pop back to where it started
there are more complicated patterns, but this one will get you pretty far. you can use it on the CPU and the GPU
When you're corroborating some random person's third-party instructions on initializing Vulkan and comparing those notes to what's done in Khronos Group repositories and reading the Vulkan 1.3 spec and realizing you have to read the specification out-of-order to get anything done, it's clear that they failed.
They failed. It's bad work by any other standard. But you'll do the work once and forget about it for the most part, so professionals don't complain too much.
Read my other comment in this thread for a portion of source code annotated with the specification chapters and sections.
It's a generic implementation that can be used with SDL and others.
Edit: As of the time of writing, the standard approach is to use VMA and Volk, both of which are included with the official Vulkan SDK. That should tell you enough about the state of the art.
I started learning Vulkan as an experiment and it seemed to work out well, so that’s why I wrote this article. :)
I’m okay with using middleware/3rd party libraries for things which I don’t care too much about (e.g. physics), but graphics is such a core component that I want to handle it myself.
In a way, OpenGL drivers were such middleware libraries written for you by GPU vendors (or open source community). But now they stopped doing that and now you’re either writing your own graphics abstraction layer or using someone else’s.
In this case, I choose the hard way. And it seemed to have worked out so far. I definitely won’t recommend it to everyone (especially if they want to make a game in less than a year!), but as a learning experience it was fun.
Most of it is satire, but it's interesting that the position of "Chair of OpenGL" still exists to this day and a new person was assigned to it in 2024.
Also, Metal isn't generally a high-level API, it has low-level features which are pretty much like Vulkan or D3D12, you just don't need to use those low level features if not needed.
If you can write that OS in anything close to 600 lines then yes, it is easy.
The point is that more realistic OpenGL and Vulkan projects will have a much smaller relative size difference.
> Great. What about the other 99% of people?
They can use higher-level abstractions built on top of Vulkan. Or spend some time learning to use Vulkan directly.
> I'm not against Vulkan for those applications that truly do need it, but - frankly - most graphics programming does not need it.
Disagree.
> In giving up OpenGL we're giving up a sane, standard way to do graphics programming
Sane is not a word I would use to describe OpenGL. It has managed to collect many warts over the years and as I have already mentioned, what performs well is not at all intuitive.
> (i) making everyone write mad Vulkan boilerplate for control they don't need, or (ii) choosing between a bewildering array of engines and frameworks and libraries, none of which work at all similarly, many of which are still very immature.
"Oh no, so many options". A nice problem to have.
> And it's obvious which one will win - whichever proprietary, SaaS monolith emerges to clean up the mess. Losing OpenGL is a huge set back for open standards, honestly. The principal beneficiaries of depreciating OpenGL will be the shareholders of Unity, in the end.
Wild and unfounded speculation. You can already use ANGLE, which is open source, as your middleware today if you like the OpenGL API so much.
I cannot avoid thinking that this sort of argument was made for countless technological innovations, from steam engines vs. draft animals to boats vs. swimming.
I think the distinguishing thing here is that those technological innovations were all adopted voluntarily by people setting aside the previous technologies, for the advantages of the new technology were obvious. Here, people are clinging to the old tech despite being threatened with its constant depreciation (already done on Apple systems), for the simple reason that using the new tech is more work for no more gain. For the average use case, Vulkan feels more like a technological regression than an advance.
That's a loud minority, but it's not like the biggest games aren't selling more and more every year en large. So non-vocal gamers do seem to be drawn to it.
2-3 years seems to be where that valuable plumbing experience starts to plateu. I don't know how engineers these days that move companies every other year even get a chance to grow when you're doing a soft restart at every job hop.
Oh how I relate to this...
That's why these days I go out of my way to "save" interesting work for my junior colleagues and have them grow through it.
No.
wgpu is a safe and portable graphics library for Rust based on the WebGPU API.
...
and browsers via WebAssembly on WebGPU and WebGL2.
https://wgpu.rs/> WebGPU is not software, you can't use it
It's an API that you can use, like OpenGL, Vulkan, Metal, .... Here you can see the current Browser support: https://caniuse.com/webgpu
wgpu is an implementation of webgpu with the raw rust bindings rather than the C-API it also provides called by Firefox.
Unless you want to dig into the implementation details of the various subcrates.
Ah, sorry, I didn't know that, thanks. On Chrome it uses either WebGL2 or WebGPU.
When running in a web browser (by compilation to WebAssembly) without the "webgl" feature enabled, wgpu relies on the browser's own WebGPU implementation.
https://github.com/gfx-rs/wgpu?tab=readme-ov-file#tracking-t...Anyway after reading I still struggle. All these discussion is about game. I am more on simulation like Game Of life but in 3d (2d done using sdl and except iOS-mixer, one code base can run on most platform I care about). And possibly VR. May be back to unity and … learn so much using c/c++ using sdl especially just pass grenderer and gwindow around and just use function pointer. I guess 3d is out of reach based on reading your article. Very enjoyable reading nevertheless.
I don't even know how you get into the graphics industry these days. The bar is so high and I just don't see how you get the knowledge needed for it. I graduated years ago and don't feel any closer now than back in the mid 2010's despite having a lot more experience to point to in other parts of games.
but it's not batteries-included, and that's often to be a deciding factor at small scales
i think if you're going to dabble in engine dev, you pick which one you want depending on which part of the engine you find interesting. if you want to make a game, you pick up unity or godot or something
Sticking with OpenGL is understandable, but I can recommend learning some Vulkan as a side project (with the help of vkguide) without too much commitment. That's how I started and it turned out to be not as bad as I imagined! Uour mileage may vary, of course.
If your laptop got still GPU driver updates in 2022 or later, it should probably support Vulkan 1.3. You can install Vulkan SDK (or just extract the archive) and check your Vulkan version by running the supplied "vulkaninfo" program.
For example, my 5 year old Thinkpad T490 fully supports Vulkan 1.3 and it only has an iGPU! :)
https://docs.vulkan.org/guide/latest/index.html
Not to be confused with the tutorial you're referring to.
there's a section on memory allocation patterns
i believe casey muratori talks about allocation patterns in the handmade hero video series, too
edit: ryan fleury has a talk: https://www.rfleury.com/p/enter-the-arena-talk
And use some high level library like vk-bootstrap to do the boring init work.
Because once it's set up, Vulkan 1.3 is about as easy as OpenGL (if you stick with OpenGL-level stuff).
It is easier than WGPU because the RenderPass stuff required in Vulkan 1.0 (and hence WGPU) is gone, removing a lot of boilerplate code.
Pipeline barriers are the only "complex" thing remaining but even they are somewhat simplified with the right defaults (sharing mode) and simplifications (set stage masks to all commands, overhead is negligible on desktop devices).
Use push descriptors for "bindful" textures, set all your pipelines states dynamic (except blending), and timeline semaphores for sync.
For simple stuff (OpenGL level) it's a pleasure to work with, and you get rid of all the OpenGL quirks.
Complex stuff like bindless texturing and GPU driven rendering is still complex, but that's the same in all APIs.
It can still be a bit verbose and the init code is too much work (but you do it only once), but after it is set up it's quite okay.
And if you want OpenGL, use OpenGL. Zink (OpenGL on Vulkan) guarantees that it will be supported, even if GPU vendors stop keeping their GL drivers up to date (has not happened yet).
Why do you need Khronos to "bless" a particular library anyway?
Also they didn't get rid of OpenGL. You can still use it. It will probably be the most widely supported graphics API for a long time.
I guess we'll have to agree to disagree on that.
> There's no evidence they'd be good at it and if you look at their GitHub, they're not particularly good at maintaining actual codebases in the first place.
Well that's another complaint then, but it doesn't detract away from my initial complaints.
> Why do you need Khronos to "bless" a particular library anyway?
Because now we're going to have a million different wrapper libraries to do everything, or you're going to be stuck with the absurd Vulkan API. It was already annoying enough that you had to have different wrappers to abstract the GUI components, now people have to have another mediocre abstraction in addition to the GUI crap.
I suppose you could argue "that's fine", and you're free to have that opinion, but I think it's worse
> Also they didn't get rid of OpenGL. You can still use it. It will probably be the most widely supported graphics API for a long time.
They're not doing new versions of OpenGL. Yes, the drivers will support them for the foreseeable future but they will get increasingly out of date.
The more things change...
Fact is that most people will never directly touch such things unless they are a) a graphics programmer at a handful of companies or b) someone like this author doing something more for education than to produce raw business value. our "high level libraries" are Unity and Unreal if you're makinig a game (and some smaller engines), and BGFX et al. if you're making your own small engine. The work is already done without Khronos lifting a finger for implementation.
the recipients of a) are the ones who asked for more control. They are paid pretty well so they have plenty of time to grok the specs compared to a small time creator, so rapid prototyping isn't prioritized.
The "NO REPLACEMENT" is sidelining ugly OpenGL drivers and adopting leaner and more modern Vulkan drivers.
It seems to guarantee technical debt starts to build as soon as possible and as fast as possible!
(I.e. I'm referring to agile as it is practised, not the true scotsman's agile. We apply the same rigour towards socialism.)
(Edit: ah, I missed the bit in GP that you replied to.)
https://github.com/9ballsyndrome/WebGL_Compute_shader
https://github.com/9ballsyndrome/WebGL_Compute_shader/issues...
https://issues.chromium.org/issues/40150444
"Intel spearheaded the webgl2-compute context to provide a way to run GPU compute workloads on the web. At the same time, the WebGPU effort at the W3C aimed to design a new, lower-level graphics API, including GPU compute. The webgl2-compute approach encountered some technical barriers, including that macOS' OpenGL implementation never supported compute shaders, meaning that it wasn't easily portable. webgl2-compute has so far been used by customers for prototyping.
At present, WebGPU is close to shipment, and its shader pipeline is nearing completion. It's possible to run combined GPU rendering and compute workloads in WebGPU.
In order to reclaim code space in Chromium's installer that is needed by WebGPU, the webgl2-compute context must be removed."
Because webgl2-compute took soooo much space on the installer!
And it isn't as if Google isn't doing WebGPU compute on top of DirectX on Windows, but doing it on top of Metal on Apple, unthinkable!
By the way, where are the Safari and Firefox implementations of WebGPU compute, running on stable without browser flags?
D3D11 gives you both desktop platforms that matter for games, everything else will require multiple backends anyway so if you only care about desktop it’s a fair choice.
AFAIK the non-Xbox consoles either don't support OpenGL or we reportedly don't want to use their implementations.
This information is misleading because it includes old reports from years ago, before this feature existed. It does NOT mean that 28% of devices out there have support. You will need Steam hardware survey results and cross reference gpuinfo.org or Android hardware survey results which directly list Vulkan versions.
Dynamic rendering is available on all desktop GPUs (Intel, NV, AMD), on all desktop OSes (Windows, Macos, Linux) as long as you've got drivers that are up to date (no older than 2023).
For mobile devices, the situation isn't as good. Updating mobile GPU drivers is an unsolved problem.
I use a 2015 Skylake laptop for most of my graphics programming project and it's got full Vulkan 1.3 and wide set of features. The hardware doesn't do mesh shaders or Ray tracing but apart from that every new feature is available.
Not updating drivers is a problem, especially on mobile. Thankfully auto updaters are very common these days.
So if you're writing rust with wgpu and you target wasm and run it in firefox you will have a wasm program that calls the browser's implementation of webgpu which is the same wgpu crate you used just built in the other way.
If you run it in Chrome instead it will use Dawn.
And in native land wgpu and dawn are incompatible and have different C-apis. One uses uint32_t everywhere and the other size_t. So they're the same on 32bit platforms like WASM but not on modern native platforms
It's heavily influenced by Metal (based on original work by Apple and Mozilla).
People are talking about it because it's on the web and it's finally something modern to work with.
TBF, WebGPU is at least a decade behind too. For instance it implements a Vulkan-style rigid render pipeline model which even Vulkan is moving away from because it turned out too rigid. So once WebGPU becomes mainstream it may very well be the most "awkward" 3D API.
I'm literally writing native code running on linux with winit and wgpu right now.
But WebGPU in the browser is also an adapting layer between those technologies, it's just the browser that does the adapting instead of the wgpu library. For Firefox, WebGPU is adapted to those underlying systems by wgpu: https://github.com/gpuweb/gpuweb/wiki/Implementation-Status
† There are some "native-only" extensions beyond the WebGPU spec that gpu provides, so it does go a little beyond WebGPU. But for the most part, it's very similar.
wgpu is also not a graphics API, it's a library that abstracts the underlying graphics API.
[0]: https://gamefaqs.gamespot.com/boards/189706-nintendo-switch/...
[1]: https://www.nintendolife.com/forums/nintendo-switch/the_fram...
[2]: https://www.reddit.com/r/FortNiteBR/comments/gyn32c/seriousl...
But this is all tangential. They may have all these fancy hardware but they either have no understanding of hardware, or are simply tonedeaf. If you're expecting the same specs out of a 2017 smartphone compared to a PS5, let alone a top end pc build, there's simply not much more I can say. Learn that a handheld has more considerations than a towering console when it comes to being a proper handheld. It's a 720p specc'd screen, of course any 3d game trying to be modern won't bother going higher.
I never saw people complaining about a 3ds not having ps4 performance, so this to me seem like a recent sense of entitlement or ignorance amongst said enthusiasts. The Switch doesn't have a GPU dock (which would cost more than the console itself, even if it didn't include a GPU), so just because you project it to a screen doesn't mean it's suddenly console hardware. You could project a PSP to a screen back in the day. Nintendo just made it work out of the box.
Edit: wgpu is a reimplementation of the WebGPU api for use with desktop apps outside of browsers. See sibling thread by another poster for an explanation: https://news.ycombinator.com/item?id=40598416
_Vendors_ did it poorly, which is why everyone wanted to get away from them. You could argue they over-corrected and left _too_ much to the user, but better safe than sorry.
Sure users can write bad code as well, but at least it's _consistently_ bad, and fully under their control. There are so many fewer problems nowadays like "oh it works on my desktop, but on this older intel GPU for a user with outdated drivers it segfaults in the driver, and there's nothing we can do to fix it ourselves".
Implying that up to date Intel drivers don't segfault on perfectly valid OpenGL use.
We don’t need to speculate whether hardware vendors can ship bullet proof drivers and API implementations, they have already proven they can’t. Vulkan was built based on industry experience from organisations big enough to sit at the Khronos table. They were trying to give the vendors as little rope to hang themselves on by reducing the complexity of driver implementation because these stakeholders (large AAA studios) were collectively expending massive resources working around vendors inability to ship good quality drivers. This problem is still ongoing even with Vulkan.
Vulkan drivers on Android are a complete joke. They barely work and I’m debugging and working around a new driver bug or performance trap every few weeks at this rate. If we can’t rely on quality Vulkan drivers, an API designed to make drivers easier to implement, how will vendors fare with a much more complex to implement API like OpenGL? (poorly, look up the history of OpenGLES3).
Desktop PC is the exception because it’s the only GPU market where hardware vendors have real market pressure to deliver working drivers. Just look at Intel’s Arc launch, a product where it’s single biggest criticism and flaw citied universally is driver issues. There is no other market where this same pressure has been applied. Nobody bought a phone specifically because it had “good GPU drivers”. Unless the hardware market a vendor is selling to cares garbage drivers are the default. Qualcomm and Arm provide more than enough proof for that.
Some games are even shipping on it [1]
[1] https://www.gamingonlinux.com/2023/02/x-plane-12-now-uses-th...
The solution Vulkan came up with was "make everything as explicit and user-controlled as possible", and leave "implementing a more user friendly driver" up to user-space, so that it could be tweaked by users, wouldn't be tied to driver updates users would never do, would be consistent across platforms, etc.
Except that never really happened. There are some graphics-driver-as-a-library projects (daxa, nabla, etc), but none with a large amount of community support.
Meanwhile GPU's evolved over time (AMD RDNA1, Nvidia Turing, Intel Arc, Apple Silicon), and it turns out that some of the choices Vulkan 1.0 bet on weren't great (explicit extensive pipeline state, binding model, render passes).
Vulkan 1.2/1.3 cleaned up a lot of this (dynamic state, descriptor indexing, sync v2), which also happens to improve ergonomics a lot to the point that it's much less painful to use Vulkan directly nowadays, as long as you're ok dropping support for older platforms.
That's more on the community then, no? Same issue as OpenGL; most of the market is Windows or consoles, Windows/consoles have their own graphics api and professional suppport, the devs choose convinience over control and cross-compatibility.
Seems like a self-furfilling prophecy if devs relinquish their control to the corporations.
Many Rust programs are written against wgpu rather than Vulkan
The unfortunate reality is that wgpu does not have enough funding. Extremely valuable features like bindless, multi queue, and mesh shaders/raytracing are missing. CPU-overhead is fairly high. Things like debugging support are not great. Having to abstract over all of Vulkan/DX12/Metal brings difficulties.
I love wgpu, and don't begrudge the volunteer devs (they've done a lot of amazing work already), but I'm also frequently frustrated by its limitations.
And WebGPU still requires all the RenderPass setup code which is a lot of boilerplate that Vulkan no longer requires.
Subgroups may seem like a minor feature, but they can unlock huge performance. I recently had a 10x perf boost with a very basic subgroup trick to let neighboring pixels collaborate on some expensive operations in fragment shaders. And there's another 5x in there waiting for me to implement some subgroup quad tricks.
The CPU feeds commands (CommandBuffers) telling the GPU what to do over a Queue.
WebGPU/wgpu/dawn only have a single general purpose queue. Meaning any data upload commands (copyBufferToBuffer) you send on the queue block rendering commands from starting.
The solution is multiple queues. Modern GPUs have a dedicated transfer/copy queue separate from the main general purpose queue.
WebGPU/wgpu/dawn would need to add support for additional queues: https://github.com/gpuweb/gpuweb/issues?q=is%3Aopen+is%3Aiss...
There's also ReBAR/SMA, and unified memory (UMA) platforms to consider, but that gets even more complex.
Yes. This is the big performance advantage of Vulkan over OpenGL. You can get the bulk copying of textures and meshes out of the render thread. So asset loading can be done concurrently with rendering.
None of this matters until you're rendering something really big. Then it dominates the problem.
I haven't tried it yet, but will try soon for my open-source metaverse Substrata: https://substrata.info/.
Long version: https://github.com/gfx-rs/wgpu/discussions/5525
There's a lock stall around resource allocation. The asset-loading threads can stall out the rendering thread. I can see this in Tracy profiilng, but don't fully understand the underlying problem. Looks like one of three locks in WGPU, and I'm going to have to build WGPU with more profiling scopes to narrow the problem.
Very few people have gotten far enough with 3D graphics in Rust to need this. Most Rust 3D graphics projects are like the OP's here - load up a mostly static scene and do a little with it. If you load all the content before displaying, and don't do much dynamic modification beyond moving items around, most of the hard problems can be bypassed. You can move stuff just by changing its transform - that's cheap. So you can do a pretty good small-world game without hitting these problems. Scale up to a big world that won't all fit in the GPU at once, and things get complicated.
I'm glad to hear from someone else who's trying to push on this. Write me at "nagle@animats.com", please.
For a sense of what I'm doing: https://video.hardlimit.com/w/7usCE3v2RrWK6nuoSr4NHJ
Lots of people say that wgpu is lacking in comparison to vulkan (specially because it has gpu features from circa 2015), but how do you compare it to opengl?
OpenGL 4 has some more advanced features like bindless that WebGPU lacks (and Vulkan has), but I wouldn't use OpenGL because of that.
My recommendation is start with WebGPU if you're new to graphics programming. Once you're at the end point where you have a bunch of working features and have optimized your engine as much as you can, and are starting to push against WebGPU limits, then I would think about switching to Vulkan 1.3 / DirectX 12.
That and portability. The ergonomics are always up for debate, but I find it a much more modern and nicer interface than OpenGL which feels...quite dated. How it compares to something like Vulkan or Metal is up for debate.
But for portability if I write my code using directx, then I can only run it on systems with directx. If I write it for vulkan, I can only target systems with vulkan. If I write for metal, I can only target systems with metal.
However, if I use wgpu and the WebGPU API, I can target any system that has directx or vulkan or metal or OpenGL. I can also target wasm and compile my application for the web.
So, I can really easily write code that will run natively on linux, on osx, on windows and the web and will use the graphics library native to that platform.
(edit: thanks for editing your post. the revised version clears it up!)
wgpu is a regular library that uses the native APIs above and abstracts them from you. I don't like calling it a graphics API because it implies it's the same as the vendor-provided APIs - it's a completely different beast.
WebGPU and WebGL are Web standards that the browser implements, and you program them via JS. Similarly to wgpu, they're implemented on top of the native graphics APIs.
The relationship between wgpu and WebGPU is that they're basically made by the same people, and in Firefox WebGPU is implemented on top of wgpu.
But saying "WebGPU runs everywhere" is plain wrong - it's a browser-exclusive API, and on top of that, at the point of writing this it doesn't even run on all browsers (71% support according to https://caniuse.com/webgpu)
I think that’s understating the relationship a bit. The wgpu API follows the WebGPU spec quite closely. It’s like saying “taffy isn’t flexbox”. You can make a technical argument that it’s not identical, and to be flexbox it must be in a browser, but anyone working with taffy will recognize that it’s implementing flexbox and will find that all their understands of flexbox apply to taffy.
Similarly, most of what I’m learning working with wgpu (outside of, maybe, threading), is directly transferable to WebGPU. And vice versa.
I don't know about any conspiring, but I've thought about that comment often, because the result appears the same: The barrier to in-house game engine development has been risen further.
Not really a conspiracy so much as the fact that Unity/Epic have much more opinions on what a graphics library can/should be than a small engine developer. The former don't care if it takes longer to release games, they have staff around the clock working on the engine.
But the "knowledge is transferable to WebGPU" is key. Even when you're compiling your wgpu code to WASM, you're not using WebGPU directly - for every API call, you're going through generated bindings on the Rust side and then generated bindings on the JS side where the actual call is made. The JS wrappers aren't trivial either - Rust structs need to be converted to the nested JS objects required by WebGPU spec, numeric enums need to be converted strings, etc.
Considering that WebGPU is supposed to be the low-level graphics API for the Web, DX12/VK/Metal equivalent, all this is at least worth a mention, and "wgpu == WebGPU" brushes over a all that, to the point where we're now casually throwing statements like "[WebGPU] is guaranteed to run anywhere, including the browser".
Anecdote: A couple years ago I migrated a 1M+ LOC application from one database to another, cutting the cloud hosting costs practically in half. This was absolutely massive for the company. It took a bit less than a year, but was possible because the people who designed the application didn't write any hardcoded queries, and everything went through an ORM or a query builder. Everything was built to an interface, even though they all only had one implementation. This turned out to be absolutely critical when we had to add the second implementation (and because we needed to maintain compatibility for the original implementation at the same time due to some one-off contracts) and the migration would not have been worth it cost-wise if the proper architecture wasn't in place from the start.
Now take the same application. It has tons of complicated architecture stuff implemented in house. Parts of it are definitely overengineered. It's been apparent when doing other upgrades and finding out "oh... this doesn't work because it's using a custom JSON serializer" that the choice to do that was poor.
In the end, I think the right choice for that application was the complex design that allowed those big migrations. For others, they might never do that and only get hit with downsides.
What it needs is likely a good vision and someone smart to know what to abstract and what to not abstract such that it will have been a good choice 15 years down the road.
Your anecdote and reflections are all absolutely true in my experience, but I've found just as many problems with off-the-shelf ORMs.
The key is the clean boundaries/interfaces and keeping things simple - leaving the bridge intact so that your enemies may retreat.
Sure, build user-facing stuff cheaply and ready to be thrown away as requirements change. But libraries, tooling, and infrastructure that everything else is built on top of should have thought and care invested in it. This will return dividends.
We spend so much time as an industry worried that somebody might put five percent more effort into a project than it’s worth, that the overwhelming majority of engineers have no idea whatsoever of how to build something to be reliable, to be easily iterated on, and to last. And so we spend tens of times more effort trying to build on top of a mountain of crap.
This is how Access "databases" and Excel spreadsheets often become mission-critical in SMBs. "We'll deal with needing a database server down the road..."
I'm not sure I agree. I think you can write a simple-but-not-hacky implementation that does only what is necessary, and is also easy to maintain and extend later.
Of course, you never really achieve that ideal, but you can keep getting closer to it as you gain more experience.
Of course there's a tradeoff (there always is), I think my point was just that this option doesn't really seem like it fits between "quick and dirty" and "over engineered", though I suppose that probably depends on how you picture that continuum ;)
You either need to use OpenGL sync objects very carefully or accept the risk of unintended GPU stalls.
And the synchronization API isn't very awesome, it can only wait for all operations until a certain point have been completed. You can't easily track individual transfers.