bevy icon indicating copy to clipboard operation
bevy copied to clipboard

Tracking Issue: MVP `no_std` Bevy

Open bushrat011899 opened this issue 1 year ago • 17 comments

This is a tracking issue for progress on a no_std compatible subset of Bevy. The tasks are ordered roughly in sequence (bevy_app can't be no_std until bevy_ecs is for example).

Core Tasks

These tasks must be completed for a no_std Bevy to become usable at all.

Prerequisites ✅

  • #15281

bevy_ptr

Done prior to initiative.

bevy_utils

  • #15463

Provide an appropriate Instant type which can be controlled by the user in no_std contexts, or avoid its use. Move web-time into wasm32-only dependencies (doesn't need to exist outside web anyway!). Make thread_local optional.

Done!

bevy_tasks 🚧

  • #15464

Awaiting merge.

bevy_macro_utils

  • #15465

Update derive_label to use Box from alloc (requires wrapping the quoted impl in a const _: () = { ... } so that extern crate alloc wont conflict with the outer namespace).

Done!

bevy_ecs 🚧

  • #15519
  • #15774
  • Add std/alloc features

Blocked on bevy_tasks.

bevy_app

  • #15779
  • Add std/alloc features

Blocked on bevy_ecs.

bevy_core

Blocked on bevy_app.

bevy_internal / bevy

  • Thread std / alloc features from sub-crates through to the final bevy crate.

Blocked on bevy_core.

CI 🚧

  • #15843
  • Once the other core tasks are completed, a no_std example should be created and tested in CI as well.

Bonus Features

These tasks aren't strictly required, but should be completed to close the gap between no_std and std Bevy. The more functionality we can provide in no_std, the more the community can develop for it.

bevy_a11y

This crate ~~is~~ was blocked on AccessKit's lack of no_std support. @DataTriny pointed out AccessKit 0.17 now supports no_std! This should now be quite straightforward to add no_std support to once the other internal blockers are resolved (bevy_app, etc.)

bevy_asset

  • #15778

Reliance on filesystem operations will make this interesting, but a lot of the asset functionality exists outside of files and folders (processing, etc.). It's reasonable to consider that a no_std platform could have a custom AssetSource (and accompanying AssetReader/Writer/etc.).

bevy_color 🚧

  • #16633
  • #15777

Awaiting merge.

bevy_derive

Should work as-is, but need to test.

bevy_diagnostic

Blocked on bevy_core.

bevy_hierarchy

Blocked on bevy_core.

bevy_image

  • #15771

Blocked on bevy_asset. Would also require some substantial feature-gating to isolate out the no_std compatible subset.

bevy_input

  • #15770

Blocked on bevy_core.

bevy_log

Blocked on bevy_ecs.

bevy_math

  • #15810
  • #15769

Done!

bevy_mesh

  • #15768

Blocked on bevy_image, bevy_transform, and hexasphere. hexasphere would need upstream changes, but on a first-glance looks like to could be no_std.

bevy_mikktspace

  • #15528

Done!

bevy_reflect 🚧

  • #16256
  • #15766

Awaiting merge.

bevy_remote

Blocked on bevy_hierarchy and a design. Currently built around networking, but could support serial commands instead, and would make debugging on embedded much easier too.

bevy_scene

  • #15764

Blocked on bevy_hierarchy and bevy_asset.

bevy_state

Blocked on bevy_hierarchy.

bevy_time

  • #15759

Blocked on bevy_ecs, but also needs some design work, since Instant is a part of std and not core. Providing an unsafe method for manually updating Time's based on a Duration would be sufficient.

bevy_transform

  • #15761

Blocked on bevy_hierarchy.

bevy_window

Currently blocked on bevy_a11y.

Not Planned

These crates can't be ported to no_std because they are highly platform specific. If you see something on this list that could be ported, please let me know!

bevy_animation

Blocked by bevy_render.

  • #15780
  • Replace petgraph with a no_std compatible alternative.

Currently only using the DiGraph type with no edge data and only a single node type AnimationGraphNode (and a serializable alternate SerializedAnimationGraphNode).

bevy_audio

Currently undergoing a major re-write so this is subject to change. I suspect even with the re-write no_std support would be blocked on a fundamental dependency such as cpal. Like rendering, audio is very platform dependent so there likely isn't a viable API Bevy could provide that would be simultaneously feature-rich enough for use on common platforms (PC, etc.) while being low-level enough for no_std ones too.

bevy_core_pipeline

  • #15775

Blocked by bevy_render.

bevy_dev_tools

Blocked by bevy_render.

bevy_dylib

Unfamiliar with the dynamic linking this crate provides. I don't see any reason why it couldn't be supported in no_std, but I would definitely require an SME to assist with getting it working.

bevy_encase_derive

Exclusively used with encase, which is a part of the rendering side of Bevy.

bevy_gilrs

  • #15773

Built around gilrs which does not currently have any no_std support. There might be a way to upstream no_std support by relying on something like SDL, but I'm not familiar enough with the project to make a fair assessment on the viability here.

bevy_gizmos

Blocked by bevy_render.

bevy_gltf

  • #15772

Blocked by bevy_render. It may make sense to find a way to break this dependency, since gLTF can be used independently of wgpu (e.g., with a user-created OpenGL renderer backend), but this would need an SME for sure.

bevy_pbr

  • #15767

Blocked by bevy_render and wgpu. Without support for WGSL shaders there's no real point in having this crate supported in no_std.

bevy_render

  • #15765

Massive crate very deeply integrated with wgpu, which is not just std reliant, but also platform dependent too. I don't think it will ever make sense to have a no_std bevy_render. Maybe could have value in splitting out some abstractions, but I don't know.

bevy_sprite

  • #15763

Blocked on bevy_render.

bevy_text

  • #15762

Blocked on bevy_render.

bevy_ui

  • #15760

Blocked on bevy_render.

bevy_winit

Blocked on winit. Likely couldn't be made no_std upstream either since it's entirely platform dependent.

General Notes

thiserror

thiserror is currently not available in a no_std form due to its use of the ::std::error::Error path for Error (which it continues to use for MSRV backwards compatibility). There is a PR to add no_std support to thiserror which preserves that MSRV requirement, but it's unclear if/when that will be merged and released.

One alternative is to link against the PR instead of the published version of thiserror:

thiserror = {
  git = "https://github.com/quartiq/thiserror",
  rev = "515bd36da54dbc346250026ddc349c88851e4bb1",
  default-features = false,
}

Another alternative is to switch to using derive_more. This would require adding explicit calls to derive(From, Display) as well, which adds to the noise. Additionally, it isn't already in the dependency tree, so its inclusion may be contentious.

Due to delays in thiserror's no_std support, we have decided to use derive_more.

portable-atomic

Certain platforms, such as the Raspberry Pi Pico, could run Bevy once no_std support is added, but can't due to Bevy's use of certain atomic features. To work around this issue, Bevy should employ portable-atomic and its sibling portable-atomic-util. These crates provide suitable replacements for the various AtomicX types and Arc.

This adds cfg(...) burden to the project, but would be limited in scope to bevy_ecs and bevy_tasks (the largest users of atomic types), at least initially. Additionally, there is issue with coercion since portable_atomic_util::Arc is a 3rd party smart-pointer, so you cannot, for example, create an Arc<dyn T> directly from an Arc<impl T>. There is a simple workaround, but at a small performance cost for unsized types. However, this will be resolved once #18598 stabilises.

Platform Support

Being no_std is necessary for certain platforms, but it is not always sufficient. Below is a table of platforms that I have tested:

Name Target Builds Notes
UEFI x86_64-unknown-uefi Runs Boots on emulated and real hardware, supported by the uefi crate.
GameBoy Advance thumbv4t-none-eabi Partially The platform does not support all atomic operations (e.g., CAS), which Bevy directly and transiently relies on. Moving from tracing to log, and using portable_atomics is sufficient to make this platform compile.
Nintendo Switch aarch64-nintendo-switch-freestanding Compiles I cannot test the binary produced by cargo nx on real hardware or an emulator to confirm it actually works.
PlayStation One mipsel-sony-psx Partially The platform does not support all atomic operations (e.g., CAS), which Bevy directly and transiently relies on. Moving from tracing to log, and using portable_atomics is sufficient to make this platform compile.
MSP430 msp430-none-elf No This platform is 16-bit, which breaks too many assumptions made by dependencies like zerocopy.
Playdate thumbv7em-none-eabihf Runs Runs but requires a patch to fixedbitset to disabled SIMD. Could potentially be fixed from within Bevy without the patch though.
Raspberry Pi Pico thumbv6m-none-eabi Runs Runs but requires adopting portable_atomics within Bevy, since the Pico doesn't support the atomic CAS instructions required.

I have a prototype of no_std compatible Bevy available on this branch. It's not being actively maintained, as it is a proof of concept for upstream no_std support (use at your own risk, etc.). However, if anyone has a particular platform they'd like to use Bevy on, please feel free to test using this branch and let me know what kind of compatibility you have. In general:

  • You must be able to compile a Rust project for this platform. (I hope this goes without saying!)
  • You must have alloc and core available.
  • Your platform must support Atomic CAS (hoping to relax this in the future!)
  • Only the bevy_app, bevy_ecs, bevy_utils, and bevy_tasks are compatible in this branch, and must be imported directly (e.g., you can't use bevy;, instead use bevy_app;). Additionally, you must disable default features for no_std compatibility.
  • Your platform must be 32-bit or higher due to safety concerns in bevy_ecs. For further information, see #4736.

bushrat011899 avatar Sep 26 '24 23:09 bushrat011899

Looks like there is some effort to make thiserror support #![no_std] in https://github.com/dtolnay/thiserror/pull/304. Looks like it's on hold until the author responds, though.

BD103 avatar Sep 27 '24 00:09 BD103

Yeah that's where I got the (temporary) fix from:

thiserror = {
  git = "https://github.com/quartiq/thiserror",
  rev = "515bd36da54dbc346250026ddc349c88851e4bb1",
  default-features = false,
}

I'm hoping the PR is merged sooner rather than later, but there's a similar issue with petgraph where there does exist a no_std compatible version, but it's waiting in the wings.

In both cases we have options for how to proceed. Either waiting for those crates to get updated, replacing them with something equivalent, or developing a replacement based on these prior efforts.

bushrat011899 avatar Sep 27 '24 00:09 bushrat011899

After some discussion on the Discord, I'm going to open PRs to replace thiserror with derive_more for at least bevy_ecs and bevy_app in the near-term. A quick experiment on bevy_ecs made the change look pretty minor, and the crate does offer more functionality than thiserror does on its own.

bushrat011899 avatar Oct 09 '24 00:10 bushrat011899

Can cargo-deny work on "our" dependencies only? If so, please add a line for thiserror, since derive-more tackles everything we need.

alice-i-cecile avatar Oct 09 '24 14:10 alice-i-cecile

Can cargo-deny work on "our" dependencies only? If so, please add a line for thiserror, since derive-more tackles everything we need.

Unfortunately no. Currently cargo deny treats direct and transitive dependencies identically. We could make a CI job that uses a crate like toml to check if thiserror is present in the dependency table for each Cargo.toml in the crates folder. I suspect we would want to do something like this anyway as a part of a broader no_std CI task.

In the interim, if a user adds thiserror back into Bevy inadvertently we at least have derive_more in-tree ready to go to fix it.

bushrat011899 avatar Oct 09 '24 21:10 bushrat011899

I got @bushrat011899's no_std branch's bevy_app + bevy_ecs working on the Playdate Simulator!

The one change I had to make to get it to run was disabling fixedbitset's simd support. For whatever reason, vec![SimdBlock::NONE; 1] (being called from bevy_ecs's Schedule) was causing a segmentation fault when SimdBlock was avx2::Block. I solved this by pulling down fixedbitset, commenting out all of the simd support, and overriding the dependency in my cargo.toml.

My Playdate won't arrive until December so it's currently unknown if it will run on hardware. I assume the above jank is to do with the Playdate Simulator and wouldn't happen on hardware (since I assume the Playdate's processor doesn't support avx2), but of course that is to be seen.

Link to discussion on discord: https://discord.com/channels/691052431525675048/691052431974465548/1302002362432487486

Niashi24 avatar Nov 01 '24 20:11 Niashi24

Can you open an issue upstream to feature flag the SIMD support?

alice-i-cecile avatar Nov 02 '24 00:11 alice-i-cecile

I believe there's an existing issue around runtime-detection of SIMD features that is likely related to this error the Playdate exposes.

bushrat011899 avatar Nov 02 '24 19:11 bushrat011899

@heydocode suggested using the Embassy crate as a part of offering multi threading and Async execution to Bevy. This is a good suggestion that I'm making note of here for future follow-up.

bushrat011899 avatar Nov 02 '24 19:11 bushrat011899

Yeah, to avoid confusion, this is my GitHub account.

heydocode avatar Nov 02 '24 20:11 heydocode

@Niashi24 thanks for testing! Care to publish a minimal hello-world repository so we can replicate and test on hardware? Thank you!

CarlosMendonca avatar Nov 02 '24 21:11 CarlosMendonca

@CarlosMendonca Here you go, hope this helps! https://github.com/Niashi24/bitset-simd-min

I do want to emphasize that this is running on the Playdate Simulator on my computer, not the actual Playdate hardware. From what I understand running it on the simulator means that the game is actually running on the hardware that runs the simulator, i.e. my computer.

It's possible that it could just be a fault with the simulator. I can't test it on the actual Playdate hardware since I don't have one (mine won't arrive until Christmas).

The crash occurred running the simulator on both Windows and Linux (running through WSL2). My processor does have support for avx2.

Niashi24 avatar Nov 02 '24 22:11 Niashi24

Hello, I just notice that "thiserror" 2.0 now support no_std.

https://github.com/dtolnay/thiserror/releases/tag/2.0.0

jatimix avatar Nov 07 '24 09:11 jatimix

Hello, I just notice that "thiserror" 2.0 now support no_std.

https://github.com/dtolnay/thiserror/releases/tag/2.0.0

We have already switched off of it, and we don't see value in switching back. See the working group for no_std on the bevy discord for more info.

BenjaminBrienen avatar Nov 07 '24 10:11 BenjaminBrienen

The core of AccessKit (that is, the accesskit crate) is no-std compatible since 0.17.0.

DataTriny avatar Nov 24 '24 14:11 DataTriny

The core of AccessKit (that is, the accesskit crate) is no-std compatible since 0.17.0.

That's awesome to hear, thanks for pointing it out! I've updated the roadmap to include bevy_a11y, since AccessKit was my only real concern here.

bushrat011899 avatar Nov 24 '24 20:11 bushrat011899

@bushrat011899 You might also want to update the section on bevy_window, since a feature is probably not needed anymore here?

Having bevy_a11y run on as much devices as possible is important for us. We are aware that game consoles don't ship with an accessibility layer, but we still want developers to be able to rely on AccessKit to create their own assistive technologies. For this purpose, the accesskit_consumer crate, which contains the logic needed by platform adapters, also supports no-std as of its latest version.

DataTriny avatar Nov 24 '24 20:11 DataTriny

I think the thiserror note can be updated now that it supports no_std.

TimJentzsch avatar Dec 30 '24 15:12 TimJentzsch

I think the thiserror note can be updated now that it supports no_std.

Agreed! I've added a little preface note indicating that the below information was written prior to version 2 of thiserror.

bushrat011899 avatar Dec 30 '24 22:12 bushrat011899

Playdate seems to no longer need any patches for fixedbitset see: https://github.com/Mathspy/bevydate/blob/1b4f02adcde079cf9757fd3c7d20331c9ab04513/Cargo.toml

Mathspy avatar Jan 28 '25 14:01 Mathspy

The playstation portable might be another interesting platform to test on. It has a decently active homebrew community so there's a good chance of people familiar with the platform being interested and having the bandwidth to actually use bevy. https://github.com/overdrivenpotato/rust-psp

ayrtonm avatar Feb 07 '25 21:02 ayrtonm