Tracking issue: https://github.com/bevyengine/bevy/issues/15460
#no_std: Bevy on Toasters?!
704 messages ยท Page 1 of 1 (latest)
Just on consoles? But what about my fridge??
@crystal solar @harsh night @keen ocean We now have a no_std working group! I'll keep notifications on for this one and try and keep it updated with any progress info that's a bit too small to change the tracking issue over!
๐
I'm sure there's others but I don't want to spam too many people all at once haha
Anything particularly interesting I'll forward to #engine-dev so I'm sure people will eventually find the working group
I'll give the graph PR a good test on a 9950x
I'll also peek at the benches and see if any others factor in here and possibly create some new ones if required
That'd be fantastic! I still don't really believe the PR has such a positive impact on performance, but all the benchmarks we currently have seem to indicate that's the case
All I really cared about was not degrading performance lol
Feel free to bikeshed working group names BTW
This is y'all's space
I spent a minute trying to be witty
I still don't even know what emote to use for no_std, ๐ซ ?
Yeah I'd be worried about claiming such a generic emote haha
Maybe ๐ง?
To represent support for older hardware?

Yeah I think that wins
Might want to rename this to something a little less hype-ey. People will read this and think "xbox / playstation / etc"
no_std is a path to consoles, but so is "stubbed std"
Perhaps Back to Basics?
And most of the hard "console problems" aren't solved by making bevy no_std
"Bevy on WHAT?!" or "Bevy on a WHAT?!"
"bevy without standards"
But can it run Bevy?
โHardโ is a matter of perspective ๐
For some people the license, legal and political challenges to get bevy or any rust on gaming consoles might be not as โhardโ - we just donโt have those in this channel unfortunately. Or anyone cousin of Mr. Yoshida here by any chance? ๐
I don't think it is contentious to say the category of things encapsulated by "everything that isn't porting bevy to no_std" is significantly harder and full of more unknowns than porting bevy to no_std.
I will say porting bevy_app/bevy_ecs/etc. to no_std has been much simpler than I had feared. There's only really a handful of contentious decisions that SME's should weigh in on, and otherwise it's mostly book-keeping
no_std: Bevy on Toasters?!
Yeah, I've been really surprised by how easy it is
And once bevy_ecs is done, I reckon all the other changes will be far less controversial too. I'm kinda hoping that once that domino falls, the other crates just require some feature gates and then "just work"
I wonder why rustc doesn't implement CAS in software if the hardware doesnt support it
I suspect the answer is something like that you get hardware with interrupts and without CAS which means that CAS wouldn't actually be sound.
This is correct, everything I've seen in portable_atomics indicates that's the primary concern
(I literally ran into this issue with the Mega Drive toolchain. :P)
My hope is to get no_std working up-to bevy_app just as-is, so that end-users can go bevy { version = ..., default-features = "false"} and have something work on the existing targets Bevy supports, just without the standard library. Once that's achieved, I'd love to double-back and get Bevy working using portable_atomics, and then potentially look at the 16-bit support. Importantly, those two ideas can happen in parallel to porting the rest of the Bevy ecosystem to no_std once bevy_app is done
Since bevy_app is the last step in no_std plugins
PR build_schedule/1000_schedule ~770ms
Upstream ~1150ms
probably better if I were to march=native
build time pretty much the same
ditto binary size
once it shapes up I might try to mess around using the ecs in a toy OS kernel
I'm not sure if you saw it, but I had made some demos using the uefi crate with my WIP fork to have a Bevy application run on bare-metal
But so cool to have this be the kind of projects people can think about
I personally keep giggling at the idea of a Bevy Bootloader
I think just because Bevy Boot flows well
reminds me of Spring Boot
Just a smidge lower level haha
excited to buy a toaster now
I never dealt with no_std, isn't this very hard to combine with collections on the heap? How does that fit to all the internal storages of the ecs?
Excellent question! When making a no_std crate, you can choose to include the alloc crate, which has almost all the allocation types you're thinking about (Box, Vec, etc.)
oh I see. This is not a default thing because not all no_std targets can make use of alloc?
For Bevy, I'll try to avoid using the alloc crate where it makes sense (e.g., bevy_math can avoid it).
That's something that's interesting, you can use alloc on all platforms, since it's entirely implemented using the core crate. The problem is an allocator can be tricky on some platforms. Like embedded where you might only have 1kB of working memory
But even then, you can define an allocator, it's just that it'd be very small and would panic pretty quickly if you weren't very careful
But yeah for Bevy we can pretty liberally rely on alloc. Maybe one day we could have a static-memory ECS and avoid allocation, but that's a very big change for even less of a benefit than no_std on its own
I see, makes sense. It would not be wise to alloc there often enough. Thanks :)
Right bevy targets probably have more than a kb space
the ecs would also need to perform garbage collection to make memory constrained apps more tenable, but doesn't do any of that currently
Yeah exactly. no_alloc isn't impossible, but it's far too different to how Bevy currently works to be a simple change
How do assets work with no_std? I assume file system access is not possible?
Correct, the normal filesystem API is exclusively behind std::fs (we don't even get the Path type!). It's common to see assets embedded in the binary for other no_std projects (e.g., PlayStation One games, etc.), so I suspect a form of embedded assets would need to be upstreamed to support it.
That's a bit further down the road though, since we can't have bevy_asset until bevy_app is no_std
i'm curious, will there not be plugin in the future for specific platform to enable some feature like read asset for it's platform ?
if nostd work and people want to dev for x platform
tiny glade isn't on consoles yet, right? if this would help with the port then it's probably worth pinging h3r2tic
I think @blazing parcel was on the money there, this could be used as part of the path for modern console ports, but modern consoles don't really have the same concerns.
Yeah, it'll make the path mildly easier for some of the modern consoles
More realistically, if they did want to port Tiny Glade to console, the licensing shenanigans & platform APIs (like graphics) are going to be the big issue.
(and gamepad support)
(that's a platform API ๐ )
Yes definitely! In my demo project for UEFI that's pretty much exactly how I've structured it; a series of platform plugins providing input, basic rendering, the app runner, etc.
And yeah this could help with porting something like Tony Glade to console, but it's definitely not sufficient. They still need rendering and asset support, and their game logic probably relies on the standard library inadvertently (it's easy to do)
The biggest thing no_std can do for modern consoles is let you make a game using the console's existing toolchain (think extern "C" type stuff)
Understood
Currently it's my goal but some problems with my USB have occur so I have to install wsl, then qemu in it and finally test my basic UEFI program (really without logic) in the VM
Wow, there were a lot of naming problems so I couldn't just copy paste the tutorial, but finally, I'm so glad that it worked!!!!!
So uefi is working pretty well with your example, even if you have to update dependencies (actually I think it will be better to me to commit to your repo)
Nice!
Anyway, when I'll finish the bootloader, I'll make it open sourced, but if anyone needs it now, feel free to mention me or DM ๐
I have created a pull request to your no-std bevy example, feel free to modify/enhance it.
I'll have a look this weekend!
Also, is there a way to spawn a moveable sprite as you have done in [this example](#showcase message) ? Don't you need bevy_assets which are inaccessible for no-std for the moment (if I've understood it well) ?
I "cheated" by basically writing my own tiny asset loader and renderer that only supports drawing PNG sprites haha
Is it a personal project or can you share the code? If it's personal, are there some no-std alternatives?
Just messing around. I just threw it up on GitHub if you'd like to have a look. I don't know if it'll compile straight away since I think I hard-coded the Bevy path to a local folder
No problems, thank you!
Tested on hardware: working but freezes a little bit (unlike in the Virtual Machine), may be related to my PC. If you want to test it, make sure to disable secure boot, else it will say "could not execute an unauthorized file", or something like that.
Personally, I find that doing UEFI games using bevy is really awesome, like, with bushRAT's examples/templates, you can make a 2D complete game for UEFI which is handsome! I'll try to figure out why is there a performance lack on my laptop, but anyway, an unique experience to play games when your laptop boots ๐
Hoping that bevy will become even funnier to work with!
Update: I figured out that my laptop has 5fps when the game was running, and when I close the game by returning Success state to the App, a white pixel goes from left upper corner to the right downside corner (by making horizontal movements)
During my lunch break today I drafted up no_std support for bevy_reflect in #16256. Currently in draft as I need to do testing and polish up some of the changes. If you're familiar with the reflection side of Bevy I'd love your feedback!
thiserror finally added no_std support in version 2.0.0. Wasn't expecting a major version bump from thiserror any time soon. Does mean that Bevy could migrate back to thiserror instead of derive_more, but I don't think there's any real value in that at this point in time.
At least it happened eventually
Yeah it's good it finally happened. Would've been nice to have some communication sometime between June and now that Dtolnay was working on it. I would've been fine to delay moving Bevy off of thiserror by a couple weeks if I had any indication it was actually going to happen
Yeah I have no real preference for it, and derive_more is useful elsewhere
Had a little spare time this morning (slow day at work) so I've updated the tracking issue to hopefully be a little nicer to read through. In particular, I've tried to indicate what is blocking each crate from having a no_std PR made. The biggest blocker is bevy_core (since it's only some thin functionality on top of bevy_app and bevy_ecs I've lumped those two together with bevy_core). The pathway to opening the floodgates is basically:
bevy_tasksbevy_ecsbevy_appbevy_core
Once those 4 are done, every other crate can come largely in parallel. Roughly translates to two-thirds of Bevy crates having a pretty clear path forward for no_std compatibility.
https://github.com/bevyengine/bevy/pull/15772#discussion_r1833730555
Dtolnay has pointed out there might be a mistake in how I've translated some of the thiserror formatting arguments for derive_more. When I get home after dinner (date night!) I'll check the implementations and make a PR to fix them.
GitHub
Objective
Contributes to Tracking Issue: MVP no_std Bevyย #15460
Solution
Removed thiserror from bevy_gltf
It would have been caught if we had better testing for the error cases ๐ฉ
@hushed locust #engine-dev message
Is the renderer you made in its own repository? Maybe it can be upstreamed and improved.
It's currently extremely simple and quite purpose-built as I haven't had much time to work on it
But I am trying to figure out how to move the whole thing to use a persistent render world that runs on a different CPU core.
In general though, if we start working on something like that we should probably start from scratch lol
Forwarding here for visibility. Still a very low priority for me personally, but a 2D software renderer, which could work with the existing sprite types could be good, even just for demo purposes.
I know how to implement bevy_nostd_render which will be easy to extend (atm think about only sdl2 impl and I'll see if it's performant and good overall) but I don't have the required knowledge to directly split bevy_render for nostd graphics support
Thankfully it was quite an edge case, only found 4 instances of this occuring
For bevy_nostd_render, embedded_graphics seems much more adapted to the no-std 2D implementation needs (even for UEFI). this crate has a lot of extensions, such as uefi-graphics2 for UEFI, and more. It's easy to extend, and I think the main render logic will be able to be the core functionality of the crate, extended by its features (for instance: uefi-render feature) to support specific platforms, without modifying the existing core functionality, but by extending traits instead
This week-end, I'll try to do a working thing on UEFI using the embedded_graphics crate for rendering purposes with the bevy_app and bevy_ecs benefits
That looks really interesting. I reckon once we have no_std Bevy released, we should make a community crate based on this, with the aim of upstreaming if it's successful!
Forwarding here to keep track of the outcome. It appears to be generally agreed upon that crates like bevy_sprite should be usable without bevy_render, allowing for alternative rendering backends, some of which could be suitable for no_std for example.
bevy_ui is another one of these crates I would say could feature-gate bevy_render, but it would also have to feature gate accesskit and bevy_a11y since they're not no_std compatible
Those should be feature-gated anyways (on by default)
I'll make an issue then ๐
Is there a published version of the bevy fork you used to build this with? Even with the various PRs merged locally I wasn't able to get no_std support working.
Yeah I have this proof-of-concept fork. You have to manually import each of the ported crates though (e.g., bevy_app, bevy_ecs, etc. instead of just bevy)
It's not something I'm maintaining, since it was just to prove it was possible, just as a heads up
I thought embedded-graphics were more high level, my current implementation isn't even using embedded-graphics at all (difficult to have sprites in it) and globally sucks. Still extremely motivated on implementing that
Definitely a skill issue
But it's fun ๐
I had a look at it, I reckon embedded-graphics is a good choice honestly
Yeah, I like embedded-graphics
Have you some experience in it?
Yes, I am building my own little renderer for embedded and use embedded-graphics for it
Cool! I'd like to see it!
It's currently undergoing a rewrite and I don't have the time to work on it ๐ญ
But I hope I'll have time over the winter holidays
I'm working on adapting the Bushrat no-std UEFI renderer to support embedded-graphics for bevy_nostd_render (trivial name for my no-std render). This projectโs goal is to make it easy to swap rendering backends or build custom ones for Bevy in no-std environments. By using embedded-graphics, the project can potentially support a wide variety of 32-bit+ platforms.
I initially tried to make a universal solution for all targets, but I found this approach too complex to maintain, especially with my limited rendering experience. So, I'm rethinking it from scratch: Iโm building embedded-graphics as a standalone no-std plugin that loops over visible entities and renders them with simple queries. Each platform-specific module will then extend this basic functionality.
In the current structure, each platform can add its own run() function, which handles the platform-specific setup needed to refresh the display every frame. For instance, on UEFI (targeting x86_64-unknown-uefi), this function will manage necessary display updates, while platforms that donโt need extra work can leave run() empty. Hereโs an example setup:
#[cfg(target = "uefi")]
use platform_specific::UefiStruct as Struct;
...
app.add_systems(Update, Struct::run);
With this approach, the rendering plugin automatically runs target platformโs run() function once per frame, allowing for flexible, platform-specific rendering without overloading the core plugin. Iโd appreciate feedback on this structure to see if it aligns with the Bevy no-std goals and any suggestions to refine it. Thanks!
It's an interesting approach! I personally like the idea of Bevy providing a rendering crate based on embedded-graphics, which handles translating bevy stuff into embedded-graphics stuff. That would be one plugin, EmbeddedGraphicsPlugin for example.
Then individual platforms would have their own plugins in a totally separate crate. This does mean we'd possible add a lot of crates to Bevy if we support a lot of platforms, but it would also ensure that 3rd party platform crates would still be first-class-citizens. Additionally, we'll likely need platform plugins for more than just rendering. Like you said, there's the runner as well, but then there's also inputs, assets, all sorts of things a platform plugin might want to handle.
Since the whole embedded-graphics crate is generic over the type of display implementation your platform uses (the type implementing DrawTarget), I imagine we'd need to provide that type to our generic graphics plugin somehow (perhaps EmbeddedGraphicsPlugin<T> where T is the DrawTarget).
Really interesting stuff you're working on, experimentation is really important!
I totally agree! Another important point to consider: if we want to keep platform crates separate from bevy_nostd_render, we might want to expose the core Struct of bevy_nostd_render for the run function. Alternatively, we could define the run function within the main rendering crate itself, which might simplify things.
By centralizing run, we could avoid situations where multiple platform crates accidentally get included in a single build. This could cause confusing errors for users, but if bevy_nostd_render had a mechanism to detect multiple runner functions, we could generate a clear error explaining how to resolve it, perhaps linking to a documentation page. This way, the setup would be more robust and user-friendly, while still keeping platforms modular.
We also might implement traits, which platform crates will be able to use in order to produce another behavior, while keeping the clear bevy_nostd_render error system (hand-made and simple error system)
I imagine we'll require the user to explicitly include the platform plugins they need for the platforms they want to support. So they'd have something like:
#[cfg(target = "uefi")]
app.add_plugin(bevy_platform_uefi::UefiPlatformPlugin);
#[cfg(target = "raspberry_pi_pico")]
app.add_plugin(bevy_platform_pi::PicoPlatformPlugin);
(The above targets are made up for the sake of simplicity)
Yeah
Oh I get so much fun from implementing this render, just got Sprites working (in theory, render itself not implemented yet haha) with bmp (so you have to convert png in bmp)
And so I have an Asset Loader which works fine in no-std
I just destroyed everything
Transferring generic display through a Resource across plugins sucks. Can someone propose an idea of how to organize things? Even a little advice will be really helpful, about everything related to rendering/bevy/no-std
Here's what I reckon would work:
- Create a plugin
EmbeddedGraphicsPlugin<T: DrawTarget>. This plugin just sets up things like the draw target resource, which would also be generic over the same parameterT. - For each platform you want to support, create a plugin which creates the specific draw target type
T, and inserts the correctEmbeddedGraphicsPlugin<T>for that platform. For example, on UEFI, you'd create aUefiPlatformPluginwhich would have aUefiDrawTargetstruct (which implementsDrawTarget), so you'd insert theEmbeddedGraphicsPlugin<UefiDrawTarget>plugin.
You could think of it like we have two half-plugins: the platform plugin and the embedded graphics plugin. Platform plugin is responsible for helping embedded-graphics talk to your specific hardware, while the embedded graphics plugin is responsible for talking with the rest of Bevy.
Seems really nice, I've understood your structure and that was almost the structure I was implementing ๐. I'll retry tomorrow and finally use git to not break everything lol
Thanks for help!
No troubles
Hi there! Is it a problem that the user won't use the alternative render crate directly? Like it will use platform-specific crates instead:
#![no_std]
// This fiction crate uses my alternative
// render and adds support for Raspberry Pi 5
// WARN: CRATE DOES NOT EXIST
extern crate rs5;
fn main() {
// App declaration, setting runner, and other things
...
/// Here the default isn't really needed, but for showcase
/// (if the user want some setup, he can define it,
/// assuming the platform-specific crate (rs5) support config)
app.add_plugins(rs5::RaspberryPiPlugin::default());
}
And yeah even if the platform-specific crate supports config, you can implement Default trait to the plugin struct to avoid verbose ::default()
No that seems reasonable to me. Bevy already has crates like bevy_core which aren't used directly by users
Ok, and also in the example it's importing a plugin, idk why I've written resource, it may be because of issues hat I had with them lol
Hey so it's been a little bit since I last posted a progress update here, just thought I'd let everyone know what's happening! First off, the general sentiment around no_std Bevy has been really positive so far, which is awesome to see! Now that 0.15 is almost ready to release, I'm expecting the no_std PRs to start getting merged in the coming weeks. In the background, I've continued experimenting with Bevy and no_std and managed to confirm that, with a small amount of extra work, getting Bevy running on the Raspberry Pi Pico is achievable, and that the embedded_graphics crate is an excellent fit for this use case.
This is a small demo application running on a Pi Pico which just clears an E-Paper display and draws some diagonal lines using embedded_graphics. The code is very ugly at the moment so I shall hide my shame for now. The biggest blocker for the Pico was just adding portable_atomics support to Bevy so that it supported the ARM Cortex M CPU the Pico uses.
Adding this to arewegameyet
Oh yeah. Now it's coming together
Hell yeah!
Oh yeah, so you've implemented embedded-graphics for bevy?
If that's the case, it's just awesome 
Not quite! I've just used it directly, but it will integrate well. My big focus here was getting bevy_app working on such a limited device (and physically prooving it too!)
Nice!
I'm working on bevy-nostd-render but for the moment I only have theory and not enough time to develop it ๐ . I'm still very motivated but tired of mistakes & errors & mislogics (ex: startup schedule not working using your fork and update only sometimes, caused by weird things unrelated to your fork).
Of course you can implement the alternative render yourself, I will even be happy if you'll succeed into developing one, I admit that it takes time for me to understand concepts and think about implementing, so you may want to implement it yourself instead of waiting
I'll write a message here of everything I discovered, the structure, generics and other things (related to embedded-graphics impl using Resource) that can help.
Also you've made an impressive work! Really cool to see that no-std is that possible for bevy!
I MADE IT!!!!! The blue color is the background and the black rectangles are bevy Entities that have component DrawableEntity
But embedded-graphics draw/fill functions seem to work in a weird manner on simulators :/
Edit: fixed
So now we have a basic bevy_nostd_render
Most beautiful rectangles I've ever seen
Nice! Once we have bevy_app no_std compatible, I'd love to work on bevy_nostd_render as a way to have things like bevy_sprite "just work" in no_std contexts.
Nice to see you interested! I'll clean up the code and post it on GitHub (it's really hard to read & comments are outdated & unused Resources, ..... ๐ )
@astral trench here is the github repo. Feel free to do pull requests with assets included & examples of use (like main.rs, which is a basic program using this render with simulator). Don't hesitate to open issues or discuss about its bad things to fix them.
Wow, that's performant. I believe that wgpu has the same (or even better) performance but that's amazing that bevy and embedded-graphics can process/render more than 10 000 entities (each pixel you see is an entity that is rendered separately).
Really nice! Does your renderer have any sort of drawing optimizations? Like, does it automatically allocate a framebuffer and use DMA to batch draw the whole buffer? Does it support interlacing and/or selectively only redrawing dirty areas? I think those are all features we should look to implement if we want to have smooth rendering on actual embedded hardware.
Here is a resource on the stuff I am talking about: https://github.com/juj/fbcp-ili9341
I haven't added this at all, but yeah nice ideas, I have not too much time of implementing all these, so I'm focusing on having something that just works, but when I'll have an ergonomic (and generic) structure, I'll start to add optimizations.
Makes sense, thanks for all the work!
Now that 0.15 is released I'm hoping to get some of these PRs merged! bevy_math is merged already and bevy_reflect should be merged soon. I now also have a bevy_color PR published thanks to bevy_math. That one is quite nice at only +53/-15 including adding it to CI!
no_std for bevy_tasks is completely revamped and ready for some reviews here! It's a much smaller PR now and should be much easier to review and (hopefully) less controversial too!
Made a little mermaid diagram to help visualise progress on no_std porting. It's a bit messy because of the automatic layout, but it's something I can automatically update on the tracking issue, and helps illustrate just how important getting to bevy_app is. Once that's done, everything else can start being done in parallel.
Had a couple more merged today!
Ping me when you have more!
Just waiting for one or two more reviews on my bevy_tasks PR!
Link? ๐
Give docs plz :p
Once that's done I think we can merge this in
I've added the no_std job to the branch protection rules so we don't accidentally break that again ๐
Just published a draft PR for bevy_ecs no_std support here! Will mark as ready once I know CI is happy
It's passing CI: please review ๐
@astral trench do you have any desire of running Bevy's benchmarks on no-std?
I'm currently fixing Clippy lints for our benchmarks, and am thinking about disabling std_instead_of_core and family for them specifically
At this time no.the testing harness setup isn't as straightforward for no_std. Maybe one day, but not soon
Just did a review pass on https://github.com/bevyengine/bevy/pull/16758. It really wasn't that bad; please take a look so we can get this out of merge conflict hell
Huge ๐
Just a draft for now, but this one is much smaller than the ECS PR. Already have it working on my Pi Pico demo app and the UEFI one, so far so good!
This really is a really important milestone to hit IMO. Once this is done, 3rd party plugins can be made by the community which are no_std compatible by simply disabling default features, and then the rest of Bevy can be made no_std largely in parallel.
Might not look very different to the last time I posted this, but it's now running using bevy/main for bevy_ecs and the above draft branch for bevy_app. Very close to MVP!
(slow refresh rate is deliberate because this display isn't designed for constant updates haha)
what exactly is that display? repurposed ereader?
Yeah basically, it's a little Waveshare E-paper display. Too small for an ereader, probably used in smart labels (e.g., supermarket shelf pricing)
Bevy in grocery stores when??
I'm sure Cart would be happy about that ๐
e-ink text adventure arcade cabinet ๐ค
The Bevy book written in Bevy on an EReader
bevy editor written in bevy on ereader
@astral trench what does https://github.com/bevyengine/bevy/pull/16874 still need?
I don't think anything else? I've added the TODO you mentioned yesterday, and have gotten approval from @dull arrow already. Provided it's approved I think it's ready to go!
Compared to the bevy_ecs no_std PR this one is far less meaty as well. Didn't need any of the controversial things like spin, etc.
I'm so sorry I just realized I left the S-Waiting-on-Author ๐ A second review just came in so I'd say we're good to go @gaunt rapids
Ahaha that's what I was confused by!
Merging ๐
I thought about adding no_std support for bevy_mod_bbcode, but from the tracking issue I'm getting that its unlikely that bevy_render and hence bevy ui and text get no_std anytime soon.
I suppose the normal bevy text rendering isn't suitable for low res displays anyway?
For now yeah, the UI code is pretty intertwined with how bevy_render works. I want to try and decouple them just enough to allow an alternate no_std renderer to exist without reinventing all the UI components/systems, but that's a pretty hefty job
I'll support slowly decoupling this stuff purely for code quality reasons, FWIW
But yeah, big and messy job
I think everyone agrees that the bevy_render extended universe needs some refactoring regardless. I'm hoping with the rest of Bevy being no_std, it'll influence those refactors a little haha
What's the next big goal now with bevy_app merged?
I'm doing bevy_core next so we have the Name component and to unblock bevy_hierarchy and bevy_transform, as those are pretty fundamental. But a lot of this can now happen in parallel. For example, bevy_time would be really good to do (and is ready to go now!), since no_std doesn't have access to std::time::Instant, so Bevy's Time type would actually be really useful
This diagram gives a pretty nice overview of all the various crates on my todo-list
Arrows indicating the blocker preventing working on it right now
bevy_asset should be interesting (and powerful, if it works)
Yeah that'll need a lot of butchering to move away from Path just enough to make something useful
no_std work is going smoothly ๐
Yeah we're in the really comfy stuff at the moment; crates that only really need the rest of Bevy. Starting to get a nice little rhythm for adding the features and documentation too haha
How did you manage to create warnings in completed crates while working on bevy_transform?
bevy_math
Honestly, I'm not sure. I guess just feature flag combinations that haven't been hit before?
We really need to test against all flag combinations tbh
Maybe they did have warnings before and we weren't denying warnings in CI
It's really frustrating having stuff like this sneak by
The problem is CI only really checks all-features, when it needs to check almost every combination, especially since some code is not(...) gated
Thanks for the review btw
Maybe it would be a good compromise to have a weekly check that performs a flag frenzy so that it doesn't cause too much friction?
Reeeee, Windows 10 will cross compilex86_64-unknown-none with a f32::signum function, but Ubuntu wont
Maybe? If it was added as an optional CI command that I could run locally when I need to, and maybe run during the release candidate process that'd be nice
I want to balance the fact that flag frenzies take a long time to complete with not having to triage even more tiny issues and have tons of little trivial PRs for me to do
Eventually this protogen wants to graduate to more meaningful work lol
You're doing excellent work for what it's worth btw.
But yeah it's a tricky balance since it will unearth new issues to solve
But I think we have to rip this bandaid off at some point. Features are rarely documented, hard to discover, have massive implications for compile times and platform support, and can trivially hide massive bugs from CI as-is
I don't mind fixing a ton of simple stuff at once. That's something I can do while watching TV in Dutch (language learning)
I'm mainly concerned about treadmill work
I need to find out how long it actually takes to feature frenzy each crate so that I can find out how awful merging PRs would be if it were a required check
Maybe it isn't as bad as I think
Everything before bevy_render should be pretty fast
I don't want my biggest contribution to bevy to be "fixing this nit costs 4 hours of waiting for it to rebuild"
but it's so good
I think someone experimented with this before, maybe @thorn fox?
I feel like I remember it taking too much time but my memory is a a bit fuzzy so maybe it was something else
I definitely hit feature flag errors after multiple bevy releases though, so I support adding more checks for them
@astral trench ๐ฆ
Eugh, is this an issue on main?
Ah, yeah that'd do it. I'll have a look and see if there's a way to make those available without features
This works, though
PS C:\Users\BenjaminBrienen\source\bevy> cargo build -p bevy_asset --no-default-features
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.25s
here it is
PS C:\Users\BenjaminBrienen\source\bevy> cargo build -p bevy_tasks --no-default-features
Compiling bevy_tasks v0.15.0-dev (C:\Users\BenjaminBrienen\source\bevy\crates\bevy_tasks)
error[E0412]: cannot find type `ExecutorInner` in this scope
--> crates\bevy_tasks\src\executor.rs:40:25
|
40 | pub struct Executor<'a>(ExecutorInner<'a>);
| ^^^^^^^^^^^^^ not found in this scope
error[E0412]: cannot find type `LocalExecutorInner` in this scope
--> crates\bevy_tasks\src\executor.rs:50:30
|
50 | pub struct LocalExecutor<'a>(LocalExecutorInner<'a>);
| ^^^^^^^^^^^^^^^^^^ not found in this scope
error[E0433]: failed to resolve: use of undeclared type `ExecutorInner`
--> crates\bevy_tasks\src\executor.rs:56:14
|
56 | Self(ExecutorInner::new())
| ^^^^^^^^^^^^^ use of undeclared type `ExecutorInner`
error[E0433]: failed to resolve: use of undeclared type `LocalExecutorInner`
--> crates\bevy_tasks\src\executor.rs:64:14
|
64 | Self(LocalExecutorInner::new())
| ^^^^^^^^^^^^^^^^^^
| |
| use of undeclared type `LocalExecutorInner`
| help: a struct with a similar name exists: `LocalExecutor`
Some errors have detailed explanations: E0412, E0433.
For more information about an error, try `rustc --explain E0412`.
error: could not compile `bevy_tasks` (lib) due to 4 previous errors
bevy_tasks is borked
Yeah so the issue here is that bevy_tasks needs a backend executor, and that can either be async_executor or edge_executor based on whether you want the no_std compatibility or not
It's similar to how bevy_math will fail to compile if you disable default features and don't enable libm
One "fix" is to make edge_executor non-optional, and enabling std just switches to async_executor, but that'd increase compile times
Are crates supposed to compile with --no-default-features? I think they should.
The possible new in-house backend that @pulsar jay is working on would be another option to fix this though, since we could ensure that works in both contexts
IMO they should
But this is an existing issue from pre-no_std with bevy_math:
cargo check -p bevy_math --no-default-features
Fails
Can a feature be enabled depending on whether std is enabled?
A feature can be enabled if std is enabled, but not in the reverse
E.g., enable foo if bar is not enabled
Some crates will use compile_error! to provide a more useful error message, but that wouldn't work for bevy_math since the issue is with a dependency, so our compile_error! wouldn't get hit
yep, i'm convinced it's possible. i'm removing a bunch of arcs right now in favor of &'static which will help.
the main thing i need is an alternative to thread_local
so that functions can figure out if they are on a worker thread or not.
That's definitely the hardest thing. I was hoping we could use some kind of !Send key object as a way of tagging threads, but I'm still not sure yet
But atomics aren't too problematic if you have any you can't remove. We can use portable-atomic to shim any that remain without much pain
We might be able to do something with target_os = "none", but I haven't tried it before so I'm not sure how ergonomic it'd be
Likewise, not(target_has_atomic) (and some other checks for partial support) could be used to enable portable-atomic automatically...
Yeah, I setup flag-frenzy to test feature flag combinations for Bevy
bevy and each crate?
There wasn't really an issue with time or memory, a check over the entire project took about 6 hours split across 5 machines
The real issue was documenting the strange dependencies features had on each other, such as "you must pick x11 or wayland, but not both"
Unfortunately, whatever I created went out-of-date too quickly for it to be worthwhile
I archived flag-frenzy for the time being, due to the lack of time to maintain it, but an example of the configuration can be found in https://github.com/BD103/flag-frenzy/tree/main/config
Yeah it's really unfortunate that cargo doesn't have solid support for feature "enums"; sets of mutually exclusive features
I think if we ever want to resurrect flag-frenzy again, we need clear documentation on every feature in every Bevy crate
I also think we'd need to refactor features to be truly additive somehow
We need to group the XOR feature together, document which ones are just optional crates (like serde), and make feature-flagged code actually modular
I can't remember the details, but I believe some crates have resorted to using RUSTC configs for controlling mutually exclusive features as a way around this
But you'd still need to test those config variables too
Yeah, the behavior for running cargo check on each crate individually and cargo check --workspace is different, which is why sometimes individual crates would fail to compile by default
Eugh, Rust makes some things a lot better, but it clearly hasn't solve all my problems yet...
I made a CI script to check each crate individually, but it was in Bash so Franรงois knocked it down
I can understand why personally. I'd rather have stuff like this in the ci tool if possible
Yeah, though the ci tool is still difficult to use and extend
This is why on my whiteboard I have "Draft CI organization"
At some point I'd like to redo all of our CI, but until then we just have make small incremental changes
I love the mix of whiteboard pen and digital annotations haha
Lol, I haven't been back in the office since last Thursday, so I made due :D
I had this dumb idea in my head that the CI tool should probably parse a csv file instead of encoding in things like feature combinations directly.
csv is plaintext so it'd play nicely with Git at least
Interesting, what do you think it would look like?
No concrete thoughts yet, something like a row per configuration to test, columns for which tests to run, and then an unbounded set of columns at the end for features to enable/disable
At least it'd be a matrix you could open in Excel/Google Sheets to look at
Huh, I'd like to see what we could do with that. I never usually reach for spreadsheets as my first solution, but the tabular data format could be interesting
Yeah it's definitely not a normal solution haha. More generally, moving some of the tool configuration out of ci code and into toml/csv files would be nice
For example, compile-check-no-std could just read a list of crate/feature combinations rather than hard-coding them into the tool
We have a data-driven game engine, now it's time for a data-driven CI that isn't YAML!
CI as entities
Imagine it: we bootstrap bevy into the CI to build new versions of bevy
It's perfect
Can't build CI? Well, sounds like someone shouldn't be pushing that PR!
Bleach my hair and call me Einstein, there's never been a better idea! >:D
build artifacts as entities is kind of what I do for a living as a build engineer that works on an overcomplicated development sdk + build system
Rip cargo-cache PR ๐ฅฒ
Would it make sense to add a github label for no_std related things?
There are quite a lot of PRs associated with it, and I assume bug reports in the future as well
No, there won't be no_std conversions once the last few are done. It's a one-off thing for each crate. The tracking issue suits it well.
No_std isn't really an area
Yeah at best it's a platform, like O-Embedded perhaps.
@gaunt rapids if you have the time, could you make an O-Embedded tag? Thanks!
Or O-NoStd, whichever feels more useful!
I think Embedded looks better, but I am not 100% sure that embedded and no_std is 1:1
Yeah no_std should include all embedded, but not the otherway around
So O-Embedded is a more descriptive and targeted label
Embedded can be a broad term. My company has a whole embedded department, but the embedded devices are literally the size of an entire room and the machines run full linux with pretty normal specs lol
.NET Runtime on our "embedded" devices
Maybe we're just using the term wrong lol
O-Embedded has my vote unless someone with more insight has a point against it
I think O-Embedded is close enough for people to know what we mean, even if it isn't 100% accurate
But what about O-Embedded-Atomics
Now that is a more interesting problem, I even think it may be orthogonal to the existing O-* labels
Since you can have a full OS on a platform without full atomic support
Since we have labels like D-Shaders which I think are useful, O-Atomics would fit right in nicely
I assume you meant D-Atomics, but yeah I agree with that
Well D-Shaders implies that the difficulty is domain specific knowledge about shader programming
O- is about platform specific stuff and Atomics seems like a platform capability
Oh I see, yeah that is true
O- labels are good for picking out issues and PRs that you have the hardware to test
Very true
And testing an atomics cfg PR needs someone who has a device that doesn't support atomics ops I guess
Or an appropriate emulator setup. The interesting thing about these no_std targets is quite a few of them are easy enough to emulate on commodity hardware
And then there was the issue recently that was caused by an android emulator not properly selecting a graphics backend even though it works fine on a real device. ๐ซ
It's perfect
By the way, can anyone explain to me why the alloc import is needed on no_std but not normal Bevy? https://github.com/bevyengine/bevy/pull/17019#issuecomment-2565903371
Weird hardware was my nickname in college
Yeah I hate this. The issue is ToOwned, vec!, String, Box, etc. are all in the implicit prelude
So they're available even if you don't use them directly
Except on no_std

That's so silly
You get an unnecesary qualifications warning, but not an unused import warning ๐
There is apparently a lint to deny the implicit prelude, but I imagine that being another fairly large set of use ... changes
There's a reason many programmers disagree with the practice of using preludes
Although it probably wouldn't be a merge-conflict nightmare since nothing would be renamed at least...
I think it's actually an attribute like no_std
The no_implicit_prelude attribute may be applied at the crate level or on a module to indicate that it should not automatically bring the standard library prelude, extern prelude, or tool prelude into scope for that module or any of its descendants.
This attribute does not affect the language prelude.
So things like ToOwned will need to be imported in all cfgs, but not f32
Honestly, I might experiment with adding that to existing no_std crates, and if it isn't a pain, including it going forward for new ones
No point adding it to bevy_render, etc.
I think that aligns with bevy's direction. Especially if it makes it easier to catch that problem in the future.
Yeah absolutely. Catching more stuff early is definitely preferrable
Yeah, if this isn't a huge pain I like it for the no_std crates
I'm currently going back over the no_std crates trying to clean up warnings and generally just polish things. Once I've done that I'll try adding this and see what breaks
error[E0405]: cannot find trait `Send` in this scope
--> crates\bevy_tasks\src\iter\mod.rs:483:47
|
483 | S: core::iter::Sum<BatchIter::Item> + Send + 'static,
| ^^^^ not found in this scope
|
help: consider importing this trait
|
1 + use std::marker::Send;
|
Yeah I'm not sure about this one guys
Yeah it's a no from me I think. You need to extern crate ... every cargo dependency and put use core::prelude::rust_2021; in every module
Oh god
There's no way to just disable the std prelude?
Not that I can see
That sounds like too much of a pain then
Yeah it adds quite a bit of boilerplate
Yeah ๐ฆ
Low value boilerplate in every file when we can instead just put better checks in CI
I'd rather the computer have to put in the extra effort, not devs
Ok so with a bit of experimentation I think I have a way to disable the std implicit prelude while keeping the core implicit. Previously, to make a crate no_std, I would add this little incantation that is generally agreed upon by the no_std Rust community:
#![cfg_attr(not(feature = "std"), no_std)]
If we don't have the std feature, then this crate is no_std
This is actually what introduces the inconsistency, since #[no_std] also switches from std prelude to the core prelude. By doing this instead:
#![no_std]
#[cfg(feature = "std")]
extern crate std;
We maintain access to std when the feature is enabled, but always disable the std prelude.
It'll be a fairly sizable PR fixing all the use ... statements (especially in test modules) but I think this is worth it for the consistency. Importantly, it doesn't make anything worse than it already is. It just brings the std experience down to the same as core
I like it!
So this disables the std prelude if the author of a new module remembers to put that boilerplate at the top? If you forget to add the module, then you would indeed have the implicit prelude?
I wonder if there is a way to check in CI that this declaration exists in every module.
Even better, at the top of the crate, and it's inherited by every module automatically. So this is boilerplate on a once-per-crate basis
It's gonna be a battle to get CI to pass I can see. But this is much smaller than I thought it would be
Now we can count how many places we are using alloc!
New working group, no-alloc bevy? ๐ค ๐
I have been thinking about what a no_alloc Bevy would be. I think first we'd need archetype invariants so we can lock an entity to a particular archetype table. Once we had that, we'd need an API for creating a world within some static allocation (probably by creating each of the archetype tables statically and then giving them to the world, plus some extra memory for other stuff)
But those APIs might be useful outside of hypothetical no_alloc Bevy anyway. Basically a way of creating up-front memory arenas (all the rage in "I made my game from scratch using nothing but C!" style developers) so you'd have very predictable runtime performance
@astral trench is https://github.com/bevyengine/bevy/pull/17086 good to go?
Yes it is! Was just waiting for the latest CI run to pass
Yeah I was shocked it was so small, and it removes a fair few feature-gated imports too.
I'm currently writing a little PSA Reddit post saying that this discussion on the Rust forums misses a pretty crucial detail in how implicit preludes work
Agreed!
Kicked out of the merge queue
Fixing it now
3rd try was the charm! Thanks @gaunt rapids !
You have fought with CI today and won
I think that's the most struggle so few lines in a diff has ever caused me haha
RA has some funny issues with conditional compilation
it happened when i restarted the extension host and it went away after a bit
Yeah I often consider just making an RA restart part of my workflow at this point haha
Damn, nice work @astral trench https://github.com/bevyengine/bevy/pull/17223
I was shocked how easy this upstream was considering the crate is very mature
Helps that the fix didn't require any "real" code changes, just some selective cfg(...) attributes
Yeah, them being like "yeah sure I'll publish a v2.0" was really surprising (and great)
It's so nice when a crate has nice maintainers like that
Does anyone have any thoughts on how multi-core usage is gonna work? I would love to run the render world on a separate core on my ESP32 but I am running into a ton of roadblocks
It'll really depend on how Nth's new multithreading backend looks once it starts getting integrated into Bevy. I imagine what'll happen is I'll add a manual API to the threadpool where you ask the threadpool for a worker runner, and it's your responsibility to execute it on a separate thread. This could then be streamlined with something like embassy.
let mut app = App::new();
let worker_functions = app.create_workers_manual(4);
for func in worker_functions {
my_platform_specific_threading_api(move || func());
}
app.run();
(totally hypothetical API)
I didn't know a new multithreading backend is in the works, nice!
It's still very early days I believe, but once this is integrated I can look into how to make it open enough for embedded use
Awesome
Yep, the main thing will be replicating some of the internals without std. need a replacement for thread locals and to use portable atomics. Itโs honestly extremely tractable.
For a Bevy game targeting no-std or resource-limited environments, Iโm trying to implement a scripting strategy: using dynamic Lua (mlua) during development for fast iteration, then converting the Lua scripts to static Rust via build.rs for release builds. The goal is to balance scripting accessibility and performance in embedded gamedev. Is this approach realistic? Thoughts?

It's an interesting idea, I don't see why it couldn't work, other than just the usual concerns around complexity
I would personally pursue a heavily asset-driven-logic approach over the complexity of scripting in general
Especially when you're attempting to re-export back into Rust
Yeah little procedures which act on assets will definitely give you better performance and simplicity
And they'll play nicer with all sorts of tooling
While still being about as accessible to modders
Hey, you asked earlier what makes bevy stand out competitively and what advantages it has over other engines. What other engine supports that use case?! I think it's awesome.
You're not wrong! Bevy's flexibility is definitely one of its strongest selling points
You really can do anything ๐
And it's ability to target any platform including embedded or wasm, plus all the stuff you can do at compile time thanks to being in rust
I mean if we're talking about crazy ideas, here's mine.
So we have rust-gpu, which lets us write Rust code and compile it as a SPIRV shader suitable for GPUs. And Francois pointed out to me the crate euc, which is a software renderer that lets you run shader-like Rust code on the CPU, and is fully no_std compatible.
With enough spit and duck tape, I think some magic could come from these two combined haha
bevy_yveb: run all your code on the wrong processor!
It pairs nicely with bevy_lag which sets up a RAMdisk for your assets and provides an allocator which allocates all memory in swap space
I perfectly see where this could be going
This release includes the first wgpu no_std changes I submitted, starting with wgpu-types! Can look at updating crates like bevy_color with this new-found compatibility
Everyone will have to keep a very close look at their crates or before you know it @astral trench will have no_std-ified them
Just reserved bevy_platform_support
Currently working on a PR that moves all the hash/hash_map/etc. stuff out of bevy_utils and into bevy_platform_support too. I'm taking the liberty of restructuring it to match std rather than just having everything in the crate root. It makes the imports a little more verbose, but it's much easier to see what parts of the standard library we do and don't have replacements for this way
It's fine if this ship has already set sail, but would it instead make any sense to put the hash_map stuff in a new bevy_collections a la https://doc.rust-lang.org/std/collections/index.html / https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html ?
It could, I'm not against that. Right now I'm putting all this into a collections module in bevy_platform_support. My motivation for this as opposed to another crate is just that bevy_platform_support is structured to just be std but with Bevy's opinionated replacements
I like this design
Once the PR is up I'll link it here, I think that's a valuable alternative to consider
I think that mimicking std is a good way to go
A really nice benefit to aiming for a mimick of std is it puts a clear ceiling on the features bevy_platform_support will have. Once "all" of std is replicated, the crate is "done". That'll never actually happen, since things like creating files can't be done in bevy_platform_support, but that's the philosophy
Got you. Yeah so your plan is more or less what I said except just not a new crate for each sub-module that would be in bevy_platform_support.
Yeah exactly. So the hashing stuff from bevy_utils I've moved into bevy_platform_support::hash, etc.
Once I have replacements for RwLock and Mutex they'll go in bevy_platform_support::sync, and so on.
I think this also works well with the idea of bevy being modular. Think about how std doesn't include tokio or whatever. Bevy applications can define their own async implementation if needed, but the ecosystem is intercompatible via bevy_platform_support.
Native UI per platform is another thing that sounds like it might be a platform support thing, but I don't think that it is within the scope.
Anyway, thanks for entertaining the discussion, let you get back to it!
Yeah these large import changes suck to review
Small CI error on there
I was looking for a reasonable no_std mpsc channel implementation, and saw that crossbeam-channel is no_std. Well, except for the fact that everything is gated behind feature = "std" lol. Interesting way to make a crate no_std compatible I guess.
How old are the feature gates? Maybe it's the first small step in an initiative so that functionality is released sooner and more frequently?
Maybe they are busy working upstream to unblock things
Could be! It's not the worst strategy. For one thing it gives you much nicer compiler errors ("This item requires thestd feature" vs "CANNOT FIND STD WHERE IS IT")
With PRs for bevy_time and bevy_input_focus opened, the next major hurdle is going to be bevy_asset, which I expect to require a couple of PRs to avoid making something too monolithic. After bevy_asset, the remaining non-rendering Bevy crates should be pretty straightforward.
We're not done by any stretch of the imagination, but it's getting awfully close already. Once these are done, I think I'll be taking a break from no_std Bevy temporarily to work on upstream changes to wgpu further (thankfully they already have a couple people interested in and leading the charge!). With that done, there may be a world where bevy_render and it's subsequent crates can become no_std (even if only to support wasm32v1-none).
Who knows, might even finally work on that bevy_mod_agb crate that started this whole mess XD
Maybe I missed it in this channel, but what's your current idea for making bevy_asset no_std compatible?
I'm thinking I'll carve out the embedded_asset parts which should work on every platform, and hopefully I can keep enough of the traits and other stuff to allow defining real asset loaders using platform specific APIs too
Rapidly running out of low-hanging fruit for no_std again. My list is:
- bevy_asset
- bevy_scene
- bevy_image
- bevy_mesh
- bevy_remote
- bevy_log
- bevy_diagnostics
After that it's waiting forno_stdwgpu(which I can't believe is actually a possibility now)
I think we'll have everything but rendering done for 0.16 ๐
It shouldn't be too bad for "normal" no_std (tracing is supported on no_std for platforms with full atomics). For the atomically challenged, I will need to be more creative, if it's possible at all
I've just been replacing/gating tracing to maximize no_std's reach. It's technically supported, just not as much as it should be
platforms without atomics seem unlikely to have things to print traces to
debugging bevy over a serial bus seems... complicated.
You'd be surprised!
That's actually exactly what I'm hoping to do in a no_std bevy_remote lol
neat neat
Sending burps over serial
https://github.com/tokio-rs/tracing/pull/3199
Hoping to improve tracing's no_std support so we can just use it without worrying anymore. It is nicer than log, I'd love for to be able to use it lol
We're leaking!
Very clean and straightforward! Well done.
Thanks! I get concerned when it's quite so simple...
I'm realizing that this working group is going to keep going after all the crates are no_std because the support can keep expanding scope by contributing upstream.
Yeah I've been thinking once 0.16 releases with no_std support (I'm hoping that will include bevy_asset and it's friends like bevy_scene) that I might mark this working group as "done" and close the tracking issue as completed, and potentially open a new issue for the bevy_render side of no_std support.
As much as I'd like to keep this going until the whole Rust ecosystem is no_std, I think it'd be good to keep the WG and issue somewhat focussed
Especially since that tracking issue is already so huge haha
Yeah, if we think certain features should be available with no_std, we can open an issue for it specifically and what blocks it.
Exactly my thinking, it'll move away from this hypothetical problem to a more concrete O-Embedded issue
Do we have a design for ensuring performance characteristics, soundness, and usability of no_std features of bevy? Do we just feature gate entire unit tests and make sure that we run cargo test/bench/miri with no_std features?
At the moment all I'm guaranteeing is compilation for no_std, but I would like to get more useful tests added to CI once we can write actual examples in no_std.
Maybe it would involve just testing bevy_platform_support specifically
The onus lies on that crate to provide bevy with sound support
(Also a good justification to have the crate in the first place)
Agreed, adding benchmarks and unit tests to bevy_platform_support makes the most sense. I do also want to add an example which compiles a Bevy app into a simple pub extern "C" fn my_app(). Because we can then use FFI to execute that app in a normal Rust test for the sake of benchmarking. I imagine it would involve compiling for x86_64-unknown-none (no-OS x86) and then running it on native x86 (Mac, Linux, whatever)
It would be fun to add some more...novel...tests though. Like compiling a GameBoy Advance ROM and benchmarking it in an emulator lol
But that's probably a bit much
Sounds like a good idea for a separate bevy project used to dogfeed development
Idk, maybe it wouldn't be so complicated to do that in CI similar to the screenshot tests.
Maybe, but one day I'll make my bevy_mod_agb crate and have GameBoy Bevy games lol
One day
We would need an emulator that is perfectly reliable and deterministic and accurate
I think that's easier to find than you'd think, since a lot of emulation nerds want perfect emulation so that hacks and glitches still work
Yeah, just highlighting it for discussion. We could do fun things like comparing save states (again, like how we do screenshots) if the emulator is reliable.
You know, that might even be possible in x86 with qemu
Not super familiar, but I imagine it might be
It sounds similar, but I wonder how much x86 processors can be trusted to behave deterministically.
Are you planning on having the serial transport within the bevy remote crate or just making the core of bevy remote no_std compatible (should be very easy) and having the transport as a 3rd party crate?
I imagine transport being 3rd party for the sake of simplicity. Especially because I doubt I'll be able to implement it generally enough to cover all the wacky platforms I'd like haha
Where is my GB to USB cable so that I can debug my romhack of Pokemon Yellow on real hardware?
But, with that typo resolved...
Bevy on the GameBoy Advance!
Obviously we can move all our testing infrastructure to just producing GameBoy ROMs lol. Why bother with a WASM build when we can just ship a gba and let the users run a WASM GameBoy emulator! /s
YESSSS
Once I have something more game-like that just a debug log I'll post the ROM lol
Bevymon when
The technical challenge of the small hardware would make for some interesting creativity
this is incredible!
I'd love to take all the credit, but the team working on the Rust agb crate have done an exceptional job making this approachable. I will take the Bevy credit though ๐
of course, but time to add the GBA as a distinct outlier to the "supported platforms" ๐
O-GameBoy I'm sorry the what?
And seriously, Bevy's abstractions make writing this stuff so nice:
#[agb::entry]
fn main(mut gba: agb::Gba) -> ! {
App::new()
.add_plugins(AgbPlugin(gba))
.init_resource::<FrameCount>()
.add_systems(
Update,
(
increment_counter,
log_counter.run_if(resource_exists::<MgbaInstance>),
)
.chain(),
)
.run();
loop {}
}
Out of curiosity, are there any better alternatives to review PRs other than Github's UI?
I've heard some people like Kraken, but I haven't used it personally
I usually review using the mobile app or the website
combined with gh pr checkout 12345 and testing stuff
I haven't looked into alternatives because I haven't felt the need for one
Yeah I've made do with GitHub so far so I haven't looked into it much
Interesting, I'll check it out along with GitLens!
I've been using this when testing stuff locally, but I don't do it too frequently
Thanks!
PRs with tons of files changed crash Chrome for me T_T
Curious - do modern consoles like the Switch, PS4, and PS5 have libc? ๐ค
Just wondering if it's just rust missing support due to NDA or there are technical challenges.
I don't have any of the NDAs required to know for certain, but I'm sure they do have libc, or at least a major subset. My thinking is that the less libc Bevy needs to work (none in the case of no_std) the easier it would be to stub out a shim.
I can't remember where I saw it, but I believe this is how the 3DS (or maybe the Switch I'm unsure) got major crates working; they stubbed out some of std and just panic on the unsupported items
Thanks for the info!
Switch ๐
And yeah, there's various bits of wiring to connect
no_std is likely to be useful to reduce the pain of maintaining forks
But overwhelmingly the challenge is "platform blessing to ship a weird language that isn't just transpiled to C"
Y'all should be able to experiment with Xbox today tbh
I wonder if that guy who's getting a Rust-to-C compiler working as a part of his .NET backend could save the day here haha
God that would be so terrible if that's the route we take
The last resort "Fine, have your C code!"
Isn't this fixed?
https://github.com/bevyengine/bevy/issues/16877
Oh yeah I reckon that can be closed now!
Possibly the easiest way to develop mobile games for Android and iOS lol
Well, now that iOS allows emulators at least
How does it handle things like sprite slot limits?
It's kinda neat actually! The agb crate provides an iterator to get the slots, so once you run out it just returns None
So I have a Query for Sprite and just fill the slots
Found a very interesting little hack with target dependencies while working on portable-atomic for smol_str. Since atomic support is actually signalled by rustc through target_has_atomic flags, we can use this to entirely hide and remove the portable-atomic feature that's virally spread across Bevy. I have a PR here that implements this little hack.
This has a bunch of little quality of life benefits, but a key one is you will always use standard library types if they are available, there's no way to enable a feature and miss-out on the first-party types
Sadly there isn't a similar flag for other areas of Rust. If there was a target_has_std flag (for example) then the entire std feature could be removed as well
Also just noticed that atomicow needs the no_std treatment, so I've done that too lol
I wonder if we can have no_std networking ๐ค
ESP32 networking is superb, I don't see why not
This would maybe even allow things like Bluetooth transport layers
(Or maybe even custom 2.4ghz transport layers)
Interesting!
I'm one of the authors of https://github.com/projectharmonia/bevy_replicon which depends only on Bevy and don't provide any I/O. We already have integrations with popular networking backends, but I wonder if we can have a little no_std treatment and backends for no_std environments ๐ค
For what it's worth, Bevy's app, ECS, math, state work on the playdate with no patches
And Bevy's time works with a minor patch https://github.com/bevyengine/bevy/pull/17577
GitHub
Objective
Make working with bevy_time more ergonomic in no_std environments.
Currently bevy_time expects the getter in environments where time can't be obtained automatically via the inst...
Network stacks in embedded are highly dependent on the chip and there are no standard interfaces afaik
I found this: https://docs.rs/embedded-nal/latest/embedded_nal/
embedded-nal - A Network Abstraction Layer for Embedded Systems
But haven't seen it implemented anywhere so far
So you would probably need different backends for each chip vendor and maybe abstract it away inside of the transport layer library
And for more custom stuff like raw 2.4ghz you are 100% bound to specific chips (or their vendor frameworks like esp-idf)
Yep, I'm aware!
This could be a solution as well, but I were thinking about just having different backends for different hardware (since replicon itself is already abstracted).
Yeah, I imagine it would be cool to make a renet-esque crate that implements everything needed for some of the major chip vendors
And then replicon can add a backend for that
I agree, it would be nicer ๐ค
Yeah there's a whole ecosystem built around Embassy that can provide things like multithreading, filesystems, networking, all sorts of things. In the embedded world it's very widely supported (less so on retro consoles but that doesn't really apply here anyway lol) so something like bevy_replicon could definitely offer an embassy-backend feature (for example)
Thanks for the info! I didn't know about embassy!
so something like bevy_replicon could definitely offer an embassy-backend feature
In case of Replicon, backends provided via separate crates. Otherwise it would be a pain for me to maintain all backends ๐
So if anyone is interesting or need any assistance - ping me in #1090432346907492443.
Ah yeah makes sense, that's kinda what I want Bevy to have as well; little bevy_mod_gba-like crates to add integration with various platforms
Embassy would definitely be one of them
Async/await in Rust has a unique design compared to other languages that offers much lower-level control. This makes it surprisingly well suited for use in microcontroller-based embedded systems with no operating system, little memory (down to kilobytes!) and no heap. Embassy is an async runtime that makes that possible: it includes an executor ...
Postcard is a binary wire format, a crate providing a serde backend, and a growing ecosystem of tools for getting computers, even small embedded ones, productively talking to each other. This talk explores where postcard came from, how it is used today, and how you can use it for building quick, pragmatic, and effective communication protocols...
A+ talks
I watched the Postcard talk in person and it was great
Oh wait, right, I completely forgot about embassy. Do they offer network abstractions for all the chips they support?
Yeah I believe everything goes through embassy-net
At least the Pico W does for sure
That's nice to hear, that could be a perfect fit then!
is there a no_std alternative to std's Path and Pathbuf? Think we'll need it
For Playdate String and &str have been a good alternatives to me (you do have to code some of the utility functions on PathBuf and Path yourself though)
There might be a package you can use instead let me see 
i tried looking for some, no luck though
Yeah canโt seem to find anything from a quick search either
https://docs.rs/unix_path/1.0.1/unix_path/ this one does have no_std support but it uses โUnix Stringsโ while on Playdate I think UTF-8 strings would be fine
Unix path manipulation.
Idk if this is relevant but I'll leave this here
https://crates.io/crates/camino
You can pretty confidently use str and String in purely no_std code. But in mixed code like Bevy internals it's a whole nightmare, since Path has a heap of custom methods and internally is an OsStr which itself has more methods. It's crazy in there
Yeah I looked at this, it theoretically could work but it looks like they rely heavily on std
Utf8PathBuf is just a wrapper around PathBuf
So unless the whole library was rewritten it wouldnโt work
yeah, and OsStr/OsString isn't a 1 to 1 relationship with str/String cause OsStr(ing) doesn't have to be valid utf-8, so you can't really suggest it as a full-on replacement
@dense condor what command are you using to build/run your bevydate repo on a device? I have it working in the emulator but when I cargo playdate run --device I'm getting some pointer issues from playdate-sys
Think that issue is resolved with latest playdate package
I was running:
cargo +nightly-2024-11-01 playdate run --release --device
Because it broke on a future nightly version
am i hearing you have a playdate ๐
thanks! the specific nightly version was the missing piece
yesyes, and running bevy games pretty quickly too!
Would recommend you two to join the playdate squad discord, they have a rust channel and there are also some panic employees in there https://discord.gg/vW8am8vS
Hopefully I'll have something for this week in bevy soon ๐ค
Trying to update bevy_internal to be no_std compatible so we can just use bevy is not as fun as it sounds, and it didn't sound fun at all ๐
Oh no
Good luck
Iโll say itโs probably fine
If we start making bevy_gba and so on
We wouldnโt need to use regular bevy
Maybe we can enable certain crates only if std is enabled? ๐ค
I.e. without std only subset will be available.
can't compile bevy_ecs on xtensa target with portable-atomic :(
Checking bevy_ecs v0.16.0-dev (https://github.com/bevyengine/bevy?rev=644efd6b0396df8fdcfd9962336114bd7982a4cf#644efd6b)
error[E0308]: mismatched types
--> /home/boris/.cargo/git/checkouts/bevy-f7ffde730c324c74/644efd6/crates/bevy_ecs/src/component.rs:2104:52
|
2104 | let boxed: Intermediate<Constructor> = Intermediate::new(
| ________________________-------------------------___^
| | |
| | expected due to this
2105 | | move |table,
2106 | | sparse_sets,
2107 | | change_tick,
... |
2131 | | },
2132 | | );
| |_____________^ expected `Arc<dyn Fn(&mut Table, &mut ..., ..., ..., ...)>`, found `Arc<{[email protected]:2105:17}>`
|
= note: expected struct `bevy_platform_support::sync::Arc<(dyn for<'a, 'b> Fn(&'a mut table::Table, &'b mut sparse_set::SparseSets, component::Tick, table::TableRow, entity::Entity) + 'static)>`
found struct `bevy_platform_support::sync::Arc<{closure@/home/boris/.cargo/git/checkouts/bevy-f7ffde730c324c74/644efd6/crates/bevy_ecs/src/component.rs:2105:17: 2110:65}>`
#[cfg(feature = "portable-atomic")]
type Intermediate<T> = Box<T>;
#[cfg(not(feature = "portable-atomic"))]
type Intermediate<T> = Arc<T>;
let boxed: Intermediate<Constructor> = Intermediate::new(
move |table, // ...
the CI that checks no_std compatibility - does that also check portable-atomic?
my bad nvm, I only enabled portable-atomic for bevy_platform_support, not also the ecs crate!
I'm running into something strange on esp32s3 xtensa:
unsafe {
bevy_platform_support::time::Instant::set_elapsed(elapsed as *mut _);
}
let now = bevy_platform_support::time::Instant::now();
fn elapsed() -> Duration {
let raw = esp_hal::time::now().duration_since_epoch();
Duration::new(raw.to_secs(), (raw.to_nanos() % 1_000_000_000) as u32)
}
This always fails with Exception occurred 'InstrProhibited', which I have no clue what causes it. And I'm not super familiar with embedded, so any ideas?
ok
think I may have found why, but it's weird as well
this fails with InstrProhibited:
let ptr = elapsed as *mut fn() -> Duration;
let ptr = AtomicPtr::<fn() -> Duration>::new(ptr);
let ptr = ptr.load(core::sync::atomic::Ordering::Acquire);
let now = (*ptr)();
this works just fine, but clippy complains about the transmute:
let ptr = elapsed as *mut fn() -> Duration;
let ptr = AtomicPtr::<fn() -> Duration>::new(ptr);
let ptr = ptr.load(core::sync::atomic::Ordering::Acquire);
let ptr = core::mem::transmute::<*mut fn() -> Duration, fn() -> Duration>(ptr);
let now = ptr();
asking claude:
This is actually a really interesting quirk of how ESP32 handles function pointers and indirect calls!
When you do
(*ptr)(), it generates assembly that tries to do an indirect memory load (to get the function address) and then jump to it. On ESP32, this pattern can cause problems because of how it handles memory access permissions and instruction fetching.When you use
transmute, you're basically telling the compiler "treat this raw pointer value AS the function pointer itself" - there's no memory load/dereference step. The pointer value (0x42...) IS the function address, and the CPU can jump to it directly.This is why Clippy complains - on most platforms, transmuting from
*mut TtoTis nonsensical and dangerous. But in this specific case with function pointers on ESP32, it's actually what we want because we're avoiding the problematic indirect memory access.This is a good example of where the usual rules about pointer handling have to be adapted for specific embedded architectures. The ESP32's memory and execution model requires some patterns that would be considered incorrect on other platforms.
so this ends up working just fine:
unsafe {
let p: Box<fn() -> Duration> = Box::new(elapsed);
let p: &'static mut fn() -> Duration = Box::leak(p);
bevy_platform_support::time::Instant::set_elapsed(p);
}
let now = bevy_platform_support::time::Instant::now();
info!("now = {now:?}");
Isnโt elapsed as *mut fn() -> Duration trying to cast a function pointer to a pointer of a function pointer?
Could you instead cast to a usize and store that in an AtomicUsize? Or just cast directly to a raw pointer rather than to a function pointer?
You might not need to do any casting at all
Or I guess that doesnโt avoid the transmute. But that should be fine anyways
Instant::get_elapsed now takes a function pointer
The transmute is completely safe
I think if you try this without the as *mut _ it should just work
(If youโre using latest version on main at least)
Ok after a little hiatus, I've re-done the no_std for bevy PR. The replacement can be found in #17955. I wasn't happy with how many changes the old PR made which in hindsight it didn't need to (I tried reorganizing some of the features when that just made it harder to see what actually changed).
I also still want to fix-up and get #17570 merged so that portable-atomic can be removed from the boilerplate of features.
And finally, I would like #17499 to get merged as well, so that wasm32v1-none can get proper support too.
Sadly, I'm still waiting for a response from rust-analyzer/smol_str and tokio-rs/tracing for better no_std support (portable-atomic to be specific), which does mean things like bevy_window are no_std compatible, but can't be used on embedded platforms
Not a deal breaker for Bevy's no_std efforts, but annoying.
I'll try and hunt folks down at RustWeek ๐
Oh right, the maintainers are real people you can just see sometimes ๐
It's very OP
Imagine you are walking around at RustWeek, then there is a rat ambushing you asking you about no_std support in one of your lib
a rat with a hat
conference in bevy VR would actually be really cool
I think this has been implemented, right?
https://github.com/bevyengine/bevy/issues/15338
Oh yeah I'd say so
Super tiny PR here to fix some of the features on bevy_reflect so they can be used on no_std. Would love a second review so it can be merged into 0.16!
I wonder how much smaller the Wasm binaries would get once we can build web apps with no_std 
The wasm32v1-none PR I have open would be the one to test this on, but from memory it dropped empty down to 600kB
๐ that potentially makes Bevy useful in threejs-type scenarios (rendering boids on a canvas, showing models, etc for regular websites)
last I checked it was kinda tough to get bevy down to a size useful for blog post visualizations, etc
That is missing bevy_render and such though
yeah but the alternative is dropping down to wgpu
which is uh, missing bevy_render ๐
True! And with wasm32v1-nome as a target we should support in 0.16, it should be much easier to support all browsers
Day 168 of no_std support for Bevy: I am currently adding no_std support to codespan-reporting so that Naga can be no_std so that wgpu can be no_std so that I can use Bevy's Sprite on a Gameboy
Bevy's CI has hands. I think #17955 is ready to merge now, and it is nicer having gone through CI's extensive review process (edge_executor feature is now gone, can use bevy with no-default-features still, etc.)
But what a struggle
That's why we do it ๐
But yeah, this sort of thing is 100% better to let the robots test for us
catching these errors by inspection is brutal
Absolutely, I can't imagine working on a project without CI testing anymore
Alright, re-merging ๐
Hopefully for the last time!
And we're a go!
@astral trench, is there anything else you'd like to do with this working group?
Honestly I think we can bring this WG to a close. There's plenty of other stretch goals to work on, but the primary objective is complete IMO
