You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Supporting JS/webgpu as a backend for e.g. PyScript #407
With PyScript most of wgpu should be runnable in a browser. If we can translate out API to WebGPU calls, people can use WebGPU via Python in a browser, which seems like a pretty big thing!
Since we follow the WebGPU IDL spec quite closely, this should not be that hard, though there are some cases to take into account.
I briefly looked into this. Some hurdles to take are:
We must provide a wheel that pyscript can load. This must either be a none-any.whl or a wasm32.whl. Even though we don't have any wasm in it, having none-any.whl can accidentally be installed on a desktop and we don't want that.
Code must be async, since there is no way to synchronously wait for a Future in js, we cannot implement our sync version of the async method. I find this the scariest hurdle. (I hope I'm overlooking something that still allows us to do that.)
We must provide a jswebgpu backend. Can partially autogenerate this. I don't expect this to be the hardest part.
We must provide a jscanvas gui backend if we want to render stuff.
Sub-goals to achieve:
Support importing wgpu and displaying the version numer.
Perform compute tasks.
Perform rendering tasks.
Now it should be possible to just run pygfx examples.
Reacted by Kushal Kolar, Matt McCormick and Maic Siemering
This means that if you want to have the wheel installable with micropip inside pyodide from PyPi, the most specific you can get is cp311-none-any
This would still do the right thing in nearly all occasions, as it would prefer the more specific platform tag if available. The only gotcha is that cp311-none-any would be preferred over building from source if a specific match isn't available. I'm not sure that is a big issue though.
Until there is official platform support for emscripten/wasm as a platform in PyPi, the only other option completely in your hands is building the wheel for emscripten in CI per release, and tell people to host it themselves or use a GitHub release url as the source to micro pip from. Also a very acceptable option in my opinion.
I would not be surprised if the pyodide team would be happy enough to include it as part of their distribution when mature enough as it should be a very small python only wheel. They have a lot of infrastructure for this sort of thing already.
For the async issue: Can we not implement the sync versions by calling the async javascript function, and immediately awaiting in using pyodide's javascript interop/marshalling?
I haven't made my way through the entire spec yet, but I haven't come across anything that requires an action to happen in between an async method being called and it being resolved.
From our end this does not have priority. Although in the process of stabilizing/finalizing the API, we are also thinking about #391, which is (oddly enough) a crucial part to enable the path to the browser.
With PyScript most of wgpu should be runnable in a browser. If we can translate out API to WebGPU calls, people can use WebGPU via Python in a browser, which seems like a pretty big thing!
Since we follow the WebGPU IDL spec quite closely, this should not be that hard, though there are some cases to take into account.
I briefly looked into this. Some hurdles to take are:
We must provide a wheel that pyscript can load. This must either be a none-any.whl or a wasm32.whl. Even though we don't have any wasm in it, having none-any.whl can accidentally be installed on a desktop and we don't want that.
Code must be async, since there is no way to synchronously wait for a Future in js, we cannot implement our sync version of the async method. I find this the scariest hurdle. (I hope I'm overlooking something that still allows us to do that.)
We must provide a jswebgpu backend. Can partially autogenerate this. I don't expect this to be the hardest part.
We must provide a jscanvas gui backend if we want to render stuff.
Sub-goals to achieve:
Support importing wgpu and displaying the version numer.
Perform compute tasks.
Perform rendering tasks.
Now it should be possible to just run pygfx examples.
Any chance this is back on the roadmap given that async works now?
As an alternative, is there a way to dump a static scene and shaders into either javascript or webassembly? I'd be happy to implement that myself if it's even possible and someone can give me some pointers on how to go about it.
is there a way to dump a static scene and shaders into either javascript or webassembly?
I guess you could implement a backend (a sister-backend to wgpu_native), that would record all the commands being made, and serialize them. And then create something in JS that can replay these commands against webGPU.
for those following the issue:
I managed to get some examples to run in the browser by now. It's by no means complete and will definitely will take a more freetime to get ready. However with the API reaching stable and some async bypass tricks it doesn't seem like there is anything missing.
Activity
[-]Supporting JS / PyScript as a backend[/-][+]Supporting JS/webgpu as a backend for e.g. PyScrip[/+][-]Supporting JS/webgpu as a backend for e.g. PyScrip[/-][+]Supporting JS/webgpu as a backend for e.g. PyScript[/+]almarklein commentedon Nov 9, 2023
I briefly played with PyScipt and webgpu yesterday, and have some more insights into what's needed. Added notes in the top post.
Korijn commentedon Nov 9, 2023
We could consider creating a none-any wheel that packs all the binaries for all platforms... But it seems like a big concession
almarklein commentedon Nov 9, 2023
I wonder if we can create
wgpu0.12.0-py3-none-wasm32.whl, so targeted for wasm, but no specific python or emscripten version 🤔willemkokke commentedon Jan 2, 2024
Hi Almar.
I'm interested in contributing towards making wgpu-py usable inside pyodide. (which I think would make it work inside PyScript too)
I have to start somewhere, so decided to look into this question first.
Looking at the source code for micropip, it uses packaging.tags.sys_tags() to match against the allowed wheel names.
Running that in the pyodide repl at https://pyodide.org/en/stable/console.html gives me:
The
emscripten_3_1_45_wasm32platform tags makes sense as https://packaging.python.org/en/latest/specifications/platform-compatibility-tags/#basic-platform-tags defines that it is the result of sysconfig.get_platform() with-and.replaced with_.According to https://github.com/pypi/warehouse/blob/c6c4033477feca74aee226d9f3b27f445d1aa964/warehouse/forklift/legacy.py#L107PyPi only allows platform tags for windows, linux, macOS, or any
This means that if you want to have the wheel installable with micropip inside pyodide from PyPi, the most specific you can get is
cp311-none-anyThis would still do the right thing in nearly all occasions, as it would prefer the more specific platform tag if available. The only gotcha is that
cp311-none-anywould be preferred over building from source if a specific match isn't available. I'm not sure that is a big issue though.Until there is official platform support for emscripten/wasm as a platform in PyPi, the only other option completely in your hands is building the wheel for emscripten in CI per release, and tell people to host it themselves or use a GitHub release url as the source to micro pip from. Also a very acceptable option in my opinion.
I would not be surprised if the pyodide team would be happy enough to include it as part of their distribution when mature enough as it should be a very small python only wheel. They have a lot of infrastructure for this sort of thing already.
willemkokke commentedon Jan 2, 2024
For the async issue: Can we not implement the sync versions by calling the async javascript function, and immediately awaiting in using pyodide's javascript interop/marshalling?
I haven't made my way through the entire spec yet, but I haven't come across anything that requires an action to happen in between an async method being called and it being resolved.
willemkokke commentedon Jan 2, 2024
Implementing the js canvas should be pretty trivial using https://pyodide.org/en/stable/usage/api/js-api.html#js-api-pyodide-canvas
Mortezanavidi commentedon Mar 8, 2024
any progression on this?
almarklein commentedon Mar 8, 2024
From our end this does not have priority. Although in the process of stabilizing/finalizing the API, we are also thinking about #391, which is (oddly enough) a crucial part to enable the path to the browser.
anadodik commentedon May 21, 2025
Any chance this is back on the roadmap given that async works now?
almarklein commentedon May 22, 2025
It is on the roadmap, but there are other things that have a higher priority right now.
anadodik commentedon May 22, 2025
Thanks for such a quick reply!
As an alternative, is there a way to dump a static scene and shaders into either javascript or webassembly? I'd be happy to implement that myself if it's even possible and someone can give me some pointers on how to go about it.
Thanks again!
almarklein commentedon May 23, 2025
I guess you could implement a backend (a sister-backend to
wgpu_native), that would record all the commands being made, and serialize them. And then create something in JS that can replay these commands against webGPU.But that would still be a huge undertaking :)
Vipitis commentedon Sep 29, 2025
for those following the issue:
I managed to get some examples to run in the browser by now. It's by no means complete and will definitely will take a more freetime to get ready. However with the API reaching stable and some async bypass tricks it doesn't seem like there is anything missing.
#753
and also WIP the canvas #pygfx/rendercanvas#115