Open ShadowMarker789 opened 2 months ago
This is definitely something I want, but I reasonably doubt anyone will have time to work on this before SDL3 ships.
I'm going to assign this to myself and put it in the 3.2.0 milestone, though I believe both actions are delusional on my part.
Yeah, apparently development is happening here
https://github.com/klukaszek/SDL https://github.com/klukaszek/SDL3-WebGPU-Examples
@klukaszek
Sorry, could you post a screen shot? Twitter is banned in my country.
Sorry, could you post a screen shot? Twitter is banned in my country.
Video to the right shows a rapid flickering of various colors, like one is randomly picking a color and clearing the screen with it.
Hey! I’ve been working on this in my spare time and I’ve managed to get the driver entry working for the example test suite. I’m planning on getting to work on pipeline creation tonight after I do my homework lol.
Cycling between demos using A and D will result in failure due to missing function implementations for the GPU driver. I also had to kind of hack in a way to prevent mouse events from flooding the event queue, but I believe this has to do with the browser and not SDL itself.
The crashing mentioned in the earlier tweet was a result of a problem where any event would trigger a resize event causing swapchain recreation. This has been solved.
So far I’ve tested resize, mouse, and key events and they all work as if using SDL2 on web.
Sorry for the spam, I’m just writing from my phone waiting for class.
Talk all you want, this is awesome. :)
Something that may help move this along is migrating our examples repo over:
https://github.com/TheSpydog/SDL_gpu_examples/issues/12
Since we presumably need to make changes for Emscripten and the examples folder has automation for exporting web samples, doing these together seems like a good idea.
https://x.com/KyleLukaszek/status/1839631105646862343
https://github.com/user-attachments/assets/4636608d-25e4-498f-8f24-d9c6d9667549
I ended up DM'ing with @ beaufortfrancois (Google Chrome) and he told me that the SPIR-V support for Chrome was bugged and never worked properly. The team decided to scrap SPIR-V support altogether and will be removing it from Chromium as of the next release.
This presented an interesting problem. SDL uses SPIR-V as its shader type, but browsers will require a valid WGSL WGPUShaderModule to process the shader.
I ended up porting Google's Tint WGSL compiler with limited functionality to WASM and linking it with the Emscripten build of SDL. This allowed me to access the Tint C++ API and export wrapper functions to C for converting SPIR-V bytecode to WGSL.
This is not an elegant solution, but I did not feel like completely changing how shaders are handled in SDL.
Anyway, I am mostly concerned at this point about being 100s of commits behind the main branch now. Any tips for syncing?
Here’s a live demo to test the current status of the example suite.
For the WebGPU backend you'll likely end up adding a WGSL
value to the bitflags, so shaders can be passed directly to SDL without needing an extra compiler (that can be the app's problem).
This is not an elegant solution, but I did not feel like completely changing how shaders are handled in SDL.
SDL's shader policy is to expose the backend's native shader format. The right way to do it is to add a new SDL_GPUShaderFormat
constant for SDL_GPU_SHADERFORMAT_WGSL
and have users provide WGSL shaders. Converting SPIR-V into other backend-specific shader formats at runtime is a responsibility of SDL_gpu_shadercross, it shouldn't be done by SDL itself. The clients can choose to use that, or generate their shaders offline with whatever workflow suits them.
Anyway, I am mostly concerned at this point about being 100s of commits behind the main branch now. Any tips for syncing?
Use git rebase
. I advice enabling git rerere
before doing that to automate future conflict resolution. I'd also recommend squashing your small fixup commits and organizing them roughly by added functionality.
Yeah I’m gonna end up moving the shader cross-compilation to SDL_gpu_shadercross now that I know that the Tint compiled shaders run properly.
As for loading WGSL shaders, I’ll just add a new enum constant to SDL_GPUShaderFormat and pass the WGSL code as a Uint8* and convert it back to a string later. I’ll work on getting that working this weekend as well as rebasing.
Thanks for the help!
I managed to rebase and get everything working again with the latest commits!
Next, I'll work on removing the shader compilation from SDL and moving it to SDL_ShaderCross.
I have a few concerns about how Tint should be integrated in SDL_ShaderCross, but I'll stick to linking with a static library of a minimal Tint build + custom C bindings for compiling SPIRV to WGSL.
I moved all shader compilation logic over to ShaderCross and updated the WebGPU backend to have WGSL as the expected shader format.
I have tested loading WGSL from a file directly into SDL, as well as loading SPIRV from a file. SPIRV is passed through the ShaderCross layer, and then converted to WGSL. This is because ShaderCross recognizes the backend shader format as WGSL and converts accordingly.
This should follow SDL's shader policy much better now.
The current web demo is still converting from SPV to WGSL.
Is your work ready to be a PR and potentially merged? It would be nice to ship with WebGPU support out of the box in the upcoming preview release.
The demo is currently only working for the most basic of shaders so I’m not sure if it’s entirely ready yet.
My SDL fork should be good for a PR though if you want to add very rudimentary support for the time being. Might be a few commits behind but that’s not a big issue.
As for ShaderCross,
My current solution for loading Tint into ShaderCross uses a static library as opposed to using SDL_LoadObject() since WASM requires the use of static libraries, not dynamic ones.
Since we only worry about WGSL for browser builds (for the time being at the very least) I can serve a static WASM library from GitHub to avoid the nightmare of having to build Tint for WASM from source.
This is all handled by a Makefile that clones the lib repo, compiles our C wrapper functions to a .o file, adds the .o file to the existing Tint library, copies the lib to SDL_gpu_shadercross/, and finally deletes the cloned repo.
If you’re building for native, this should all be ignored.
The ShaderCross WGSL functionality currently only supports SPIR-V and WGSL. If you want to try and add other Tint backends, please do, but the static library size will be massive (and might actually not work whatsoever).
These changes to ShaderCross could most likely be PR’d to the appropriate repo if the inclusions seem acceptable.
Is your work ready to be a PR and potentially merged? It would be nice to ship with WebGPU support out of the box in the upcoming preview release.
I don't think there should be any rush to get this in, this is going to be a lot of work and I don't want to cram in WebGPU at the 11th hour and have clients expect it to be ready to use.
I agree, take the time to do it right.
These changes to ShaderCross could most likely be PR’d to the appropriate repo if the inclusions seem acceptable.
Sure, we can take a look.
Out of curiosity what kind of binary sizes are we looking at for a wasm-ified Tint? From my experience it's very heavyweight on Windows, but granted that's with more than just the spirv/wgsl systems enabled.
Out of curiosity what kind of binary sizes are we looking at for a wasm-ified Tint? From my experience it's very heavyweight on Windows, but granted that's with more than just the spirv/wgsl systems enabled.
GitHub says that the libtint.a static library is 37.5 Mb.
When compiled with the test suite, the resulting WASM binary that is produced is 12.5 Mb.
When this WASM file is served by GitHub Pages, Chrome network tools reports that the final WASM binary is 2.7 Mb (it's still 12.5 Mb in reality though).
This includes SDL, ShaderCross + Tint, and the example suite (+ the static content).
Vertex buffers are now operational! This means that examples 3 & 4 now work on the demo site.
Demo 4 is restricted to a 320x480 window so do not worry if the drawn output does not fit the canvas.
Haven't checked out what I have to do next but I've got two math midterms to study for so I might disappear for a bit. We'll see though.
I got stuck trying to get buffers working for quite some time, even though I could have sworn that my implementation was fairly sound... As it turns out, there is a WebGPU regression in Emscripten versions >= 3.1.65 responsible for my pain. I opened an issue in the Emscripten repo so hopefully it will get resolved soon.
Turns out there were more than just 1 WebGPU regression in the last few updates to Emscripten so for the time being I'll just stick to 3.1.64 and occasionally test the latest release.
You should provide the javascript glue code manually, you don't just shove emescripten and call it a day, it is platform and language specific, not portable
Respectfully, I don't think reimplementing existing JS bindings for WebGPU Headers would be a good use of my time (or anyone's).
I was planning on going through and removing most references to Emscripten-specific function calls, but if I was using it for the WebGPU bindings anyway, then there was no point in doing so.
Emscripten is not WASM, it is wrong to have it as a dependency, or to assume that's what everyone will use
The SDL repository already references Emscripten (CMakeLists.txt), so basing the WebGPU backend off of it is not my biggest concern at the moment.
SDL_gpu_webgpu.c references a total of 3 Emscripten-specific functions and 1 struct. 2 of those function calls are emscripten_sleep() which can be swapped out with SDL_Delay(). The other is wgpuDeviceCreateSwapChain(), which is an Emscripten abstraction used to create a WGPUSurface to use as the swapchain. So once everything seems stable, I can start picking away at the Emscripten-specific stuff.
As for Tint-WASM, I can look into that another time since (again) I'm already using Emscripten to compile SDL, so using it to compile the examples just works. I do agree that Tint-WASM should probably be tested with other WASM compilers to see if the output works as intended.
If you could point me to any other WebGPU JS bindings for WASM I would greatly appreciate it. I'd be more than happy to check them out, those links you provided seem very informative!
I finally managed to get textures to appear but there seem to be some issues that need to be ironed out.
BindGroups are very rudimentary at the moment and will be worked on over time to support more and more binding types. So far only textures, buffers, and samplers are supported. Storage variants are not yet supported.
As always, you can use an extension like WebGPU Inspector and check out the demo site to see what's happening under the hood. Some resources aren't cleaning up properly at the moment so I'll also have to go in and fix that.
I had some time recently to sit down and fix the texture issue. I can continue some more after I finish preparing for my term tests.
Ravioli in the browser!
Good luck with your term tests!
Issue created to track SDL3 GPU Backend, targeting WebGPU.
Extract from SDL_GPU Readme page
SDL3 GPU is a very exciting project, and it would be great to add WebGPU as a compilation target.
Many thanks to the SDL Team for their hard work and great accomplishments.