![]() |
|
![]() |
| The actual issue is not CPU-side. The issue is GPU-side.
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. |
![]() |
| It is possible but managing asynchronous transfers in OpenGL is quite tricky.
You either need to use OpenGL sync objects very carefully or accept the risk of unintended GPU stalls. |
![]() |
| Short version: hope, yes. Obtain now, no.
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 "[email protected]", please. For a sense of what I'm doing: https://video.hardlimit.com/w/7usCE3v2RrWK6nuoSr4NHJ |
![]() |
| > OpenGL is only deprecated on MacOS, AFAIK, it will exist for many years to come.
It's abandondend by Khronos and GPU vendors, which is pretty much the same thing as deprecated unfortunately. |
![]() |
| Vulkan is for writing OpenGL-type libraries against. It's advantage is largely that much of the library-level code is moved out of opaque and buggy device drivers and into user-space libraries. |
![]() |
| > but on this older intel GPU for a user with outdated drivers it segfaults in the driver
Implying that up to date Intel drivers don't segfault on perfectly valid OpenGL use. |
![]() |
| Yea, wgpu is basically an adapting layer between the WebGPU API and opengl, vulkan, directx. So it's the same† API.
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. |
![]() |
| Vulkan, Direct3D, Metal and OpenGL are graphics APIs - the implementation comes with your GPU driver, and they're as close as you can reasonably get to writing code "directly for the GPU". When you call a Vulkan function you're directly calling driver code.
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've heard the same thing about DirectX 12 vs DirectX 11. One book basically said that you will probably have worse performance in DirectX 12 vs DirectX 11 if you don't know what you're doing. |
![]() |
| Great writeup! I learned Vulkan myself so that I could write a scientific data visualization engine (https://datoviz.org/ still quite experimental, will release a newer version soon). I had some knowledge of OpenGL before and learning Vulkan was SO hard. The learning resources weren't that great 5 years ago. I took up the challenge and it was so much fun. It took me months to understand the role of the various dozens of abstractions. In the process I wrote a small wrapper around Vulkan (https://datoviz.org/api/vklite/) to make it a bit less painful to work with (it supports a subset of the features, those that are the most required for scientific visualization purposes).
|
![]() |
| That's what bothers me though; why not have an official higher level API that's less awful to use? Instead you get a bunch of third party libraries bolted on top of everything. |
![]() |
| Really nice article! I have some OpenGL familiarity and tried out Vulkan but bounced off of it due to all of the up-front complexity just getting something running. Might give it another shot now! |
![]() |
| Unfortunately, dynamic rendering didn't come about until "recently". Many devices are stuck on Vulkan 1.1. Go to http://vulkan.gpuinfo.org/listextensions.php and search for dynamic_rendering. It's only supported on about 28% of reports.
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. |
![]() |
| I get your point. But you might be surprised how many PCs are still in use that have pre-Skylake Intel IGPs. Some people just don't update their drivers, either. |
![]() |
| Thank you. The up-front complexity is still there and it might take quite a few days to see your first triangle. But I promise, everything will get much easier from that point. :) |
![]() |
| Thanks a lot, that’s a very touching comment.
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. :) |
![]() |
| reminds me a lot of http://bettermotherfuckingwebsite.com/
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. |
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.