GPU: Experimental WebGPU SDLGPU Backend#16020
Conversation
Currently only supports Wayland, and it's quite..... bad This is a DRAFT! Just a small proof-of-concept. I'll submit a draft PR to the SDL project to see if I should continue development. If this is greenlit, I might making consider a WGPU SDL_GPU backend if wgpu-native is in a good enough state (maybe Dawn if it isn't?) No promises though! Don't get angry at me if I don't! Current known issues: 1: Error handling is sparse. 2: It only supports the shared library version of wgpu-native, and it does that by just loading it whenever it needs to do something 3: wgpu-native is bad and doesn't implement wgpuGetProcAddress so we're just using SDL_LoadFunction instead. I'd much prefer using the native wgpuGetProcAddress but alas....
Removed webgpu.h and instead we're defining the types ourselves Thank you @HamdyElzanqali for pointing out my stupidity lol
wgpu_native really seems to like statically linking itself (as shown by it not implementing the functionality for dynamic linking), so I added an option to statically link it alongside SDL. How I implemented this almost certainly goes against some convention or guideline in SDL but I'm shooting blind here. I have no idea what to do.
Added Windows support for WGPU, although it is untested since I don't have a Windows machine to test it on.
Added support for Google's Dawn WebGPU implementation. You control which one's used via the option "SDL_WGPU_LIB" where it's either "wgpu-native" or "dawn".
Congratulations; you can now use WebGPU on the Web. I'll make an example eventually, but it's midnight in Sweden and I gotta go to bed.
I'm calling it that simply because it's quicker.
Oh my god, there's SO MUCH STUFF TO DO
Keep on buffering Denji I'm losing my mind
I am so confused here. This backend is effectively a port of the Vulkan backend, but just with WebGPU instead, but that means that I'm often including redundant functionality or attempt to create things that just don't work in WebGPU This backend will have to be polished, as right now it's about as smooth as 1 grit sandpaper.
Since WebGPU shader modules can have multiple types of stages (one shader can have a vertex, fragment, and compute stage in it), I had to make a workaround. I'm actually sorta proud of my solution! How it works is that every "SDL_GPUShader" is actually a "WebGPUShaderReference", which stores the entrypoint, what stage it is, and a hash of the shader source code. That hash is used as the key into a hash table in the renderer, which contains the "actual" shader. I'm bad at explaining things, so I'd just read the code. It's only two functions and I hope I made it easy to read.
YOU WILL GET A 200 LINE FUNCTION AND YOU WILL MERGE IT
Or, I mean; I actually started work on this three days ago. I just hate WebGPU bind groups so much that I've actively procrastinated on implementing them. I will be the first to say this: My implementation of bindings in WebGPU SUCKS. I will not deny that. I made this quickly, and badly, since if this is not done; I will be permanently stuck in a state of procrastination, since I cannot work on multiple things at once. Something something neurodivergence, something something ADHD. Sorry for the lack of commits in the past few days.
Uniforms'll require some extra work since WebGPU expects to receive a buffer while SDL_GPU only provides raw data on the CPU side
I've got it compiling, now I just gotta fix why it crashes.
Why's nothing showing up on the screen 😭
Sometimes my genius frightens me
Shit leaks like a sieve
tbf I do just hate WebGPU in general
I'm honestly just procrastinating bind group texture fuckery +1 to the "WebGPU sucks" counter
Only leaks now are from not destroying devices
Alright, we're actually leaking 928 bytes each device creation, but I can't figure out why and honestly I'm fine with leaving that
God I hate WebGPU
Next up: I'll be remaking the bind system for the third time. I'm planning on giving each bindable resource a "tag" which we'll use to prevent recreating the same bind group each frame.
I hate WebGPU bind groups.
+ some small bug fixes
Fuuuuuuuuuuuuuck dude this backend const so much money I'm so fucked
WebGPU is a garbage API for garbage people
Fuck this API it SUCKS
|
After you take a break, can you review the SDL GPU API feature set and see if there's anything that just can't be done with WebGPU? |
|
I have not looked at this code yet but I want to say that I admire that you've stuck with this. It's a challenging project! |
God I hate this API
I wrote down the things that instantly came to mind. There are almost certainly things I've forgotten but these are the ones that have traumatized me enough to where I see them in my nightmares. |
|
I haven't reviewed the PR yet but there are a handful things I wanted to mention real quick! First, it looks like something went wonky with whitespace and formatting in many of the source files, which makes the diff appear a lot larger than it should. Would you mind fixing that up? The repo root has a clang-format file you can use for this. And then regarding the incompatibilities you noted...
Writing to a uniform buffer is just a CPU-timelined memcpy on the other backends, so in theory we could do the same here? Maybe there's some gotcha with WebGPU buffer uploads that I'm missing though...
This is actually the case on other backends too! These R32 formats are the only ones that are guaranteed to be supported for simultaneous RW operations on D3D12, Vulkan, and Metal. (It looks like the wiki page for Also, and you may already be aware of this, but it's worth noting that SIMULTANEOUS_READ_WRITE is different from READ | WRITE. At least on desktop APIs, plenty of texture formats support both WRITE and READ, it's just that you can't read from and write to a given texture in the same shader, due to race conditions.
The reason is D3D12. (Though what their reasoning is, I don't know.) We have a workaround for this in the D3D12 driver, so maybe that could be adapted for WebGPU?
Like texture formats, multisampling capabilities vary significantly across devices, so users are expected to check the supported counts via SDL_GPUTextureSupportsSampleCount. So it's no problem if certain values aren't supported. |
|
@TheSpydog Thank you for the comment! When it comes to the weird whitespace that's entirely my fault. I've accidentally autoformatted them multiple times. I'll try to fix that ASAP! Addressing your comments about the incompatibilites:For uniform buffers:WebGPU is very pedantic about using staging buffers. So much so that if you want to map a buffer, it cannot have ANY other usage than mapping. Therefore, it is impossible to do a memcpy to the uniform buffer, as WebGPU hates puppies, rainbows, and the concept of love. However; I did figure out a workaround, although it is quite disgusting. For Read/Write textures:(Note: I am not 100% sure of this, WGSL has barely any documentation) WGSL does not differentiate between simultaneous read/write & regular read/write. For the BPR alignment (damn you D3D12):A staging buffer in WebGPU cannot have both
I considered doing that, but I decided that the additional overhead wasn't worth it, when you could just make the user pad the data before it gets uploaded. Although, if it's decided that the overhead isn't a concern, I'll change it so that it'll automatically pad it. |
|
Note: Currently, how the uniform buffers are set up is that there are 12 buffers created at device creation, (4 per stage), which are then used for all uniform buffer calls. This was a...... questionable design decision, I won't lie. |
Description
This is my SDLGPU WebGPU backend. I've been working on it for about 1 and a half months, and it's reached a level of "finishedness" where I need feedback on how it works.
As of right now it can run 27 out of the 34 SDLGPU examples*, and I've got it running on Windows, Linux, and the Web.
(*most of them need to be modified slightly since WebGPU sucks)
It currently supports most of the SDLGPU standard, however I'm making it a draft PR for a few reasons.
This is the first time I've ever contributed to any project that's not my own (my hubris knows no bounds), so please don't murder me when I do something stupid.
I'll be happy to help with any issues that'll inevitably be found.
(Note that I'm Swedish, so if you're in the Americas I'll be at least ~6 hours behind you.)
(Also, read the README-WEBGPU.md file. Please.)
(TLDR: WebGPU has tortured me and I will further inflict this pain upon others by forcing them to review my code.)
Before this can actually be considered for merging into SDL, we'll need to do a lot of things.
//!SDLGPU_COMPAT_F32_UNFILTERABLEsomewhere within your shader code to use non-filterable texture types. This is bad, as not only does it force unfilterable sampling for ALL samplers regardless of type, it is also confusing, as this is also needed for sampling depth textures.Anyways, I'm gonna go play CloverPit now. Have fun!
(Or don't; I'm not your dad.)
Existing Issue(s)
Resolves issue 10768.