Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider breaking bevy_core up #2931

Open
CAD97 opened this issue Oct 7, 2021 · 8 comments
Open

Consider breaking bevy_core up #2931

CAD97 opened this issue Oct 7, 2021 · 8 comments
Labels
A-Core Common functionality for all bevy apps C-Code-Quality A section of code that is hard to understand or change C-Feature A new feature, making something new possible

Comments

@CAD97
Copy link
Contributor

CAD97 commented Oct 7, 2021

What problem does this solve or what need does it fill?

bevy_core currently serves a number of different roles:

  • type registrations: math / std / ecs / time / misc
  • time
  • names / labels
  • FloatOrd
  • Byte conversion
  • task pool setup

I do think that it is worth revisiting bevy_core.

What solution would you like?

I think we can probably find a solution that satisfies everyone:

  • Byte conversion will be deprecated in favor of bytemuck and crevice once the new renderer gets merged
  • bevy_math might actually be able to define its own plugin / take a dependency on bevy_app. this forces bevy_math consumers to also consume bevy_app / bevy_ecs / etc, but maybe thats ok.
  • time stuff could be broken out into bevy_time
  • FloatOrd could be moved to bevy_utils (although its type registration cannot)
  • Type registrations could be moved somewhere else (maybe even the top level bevy_internal crate)
  • We could consider doing a task pool setup plugin in bevy_ecs or bevy_internal

In short, we might be able to do away with bevy_core entirely. I'd prefer to start doing this stuff after the new renderer is merged to avoid conflicts / allow us to remove the Bytes stuff entirely. These are all straightforward changes that won't take any real time investment.

What alternative(s) have you considered?

Status quo

Additional context

#2900 (comment); blockquotes are from @cart in linked comment.

@CAD97 CAD97 added C-Feature A new feature, making something new possible S-Needs-Triage This issue needs to be labelled labels Oct 7, 2021
@mockersf mockersf added A-Core Common functionality for all bevy apps C-Code-Quality A section of code that is hard to understand or change and removed S-Needs-Triage This issue needs to be labelled labels Oct 7, 2021
@mockersf
Copy link
Member

mockersf commented Oct 7, 2021

to be looked at after #2535

@colepoirier
Copy link
Contributor

@mockersf saw this just now and your note that you wanted to follow up on this issue after 0.6. So here is your reminder I guess :)

@mockersf
Copy link
Member

@colepoirier I didn't want to follow up on that, just that whoever wanted to should wait. Go ahead 😄

@colepoirier
Copy link
Contributor

Ah my bad! I thought I was being helpful lol.

@mockersf
Copy link
Member

As this start to be done, I wonder if it would need a more thorough examination before starting to split it. Maybe with a target dependency graph on the changes that could be done?

About the two with started PRs:

  • moving time stuff to bevy_time: this mean adding a new very small unit to compile, but reducing the number of crates depending on bevy_core. I'm not sure it would have a positive impact on compile time, but I think it would have a negative one when compiling on a machine without many parallel jobs to compile
  • moving FloatOrd to bevy_utils. This is reducing one pile of stuff to increase another. More crates depends on bevy_utils, so it wouldn't be a positive change

To be fair, the compilation impacts should be minimal as the code involved is very small and simple. But I think it makes sense to have "grab-bag" crates, and it makes sense to have a small one (current bevy_core) with the more basic components, and a larger one (bevy_utils) that is needed later in the compilation.

@CAD97
Copy link
Contributor Author

CAD97 commented Mar 13, 2022

it makes sense to have a small one (current bevy_core) with the more basic components, and a larger one (bevy_utils) that is needed later in the compilation.

This sentiment is reasonable, but incorrectly informed; in fact, reversed. Every crate which uses bevy_core also directly uses bevy_utils. In fact, bevy_core uses bevy_utils.

All of the below ignores development/test dependencies.

cargo tree -i bevy_core --depth 1
D:\repos\bevyengine\bevy [main ≡]> cargo tree -i bevy_core
bevy_core v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_core)
├── bevy_core_pipeline v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_core_pipeline)
├── bevy_diagnostic v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_diagnostic)
├── bevy_gltf v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_gltf)
├── bevy_internal v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_internal)
├── bevy_pbr v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_pbr)
├── bevy_render v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_render)
├── bevy_sprite v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_sprite)
├── bevy_text v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_text)
└── bevy_ui v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_ui)
cargo tree -i bevy_utils --depth 1
bevy_utils v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_utils)
├── bevy_app v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_app)
├── bevy_asset v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_asset)
├── bevy_audio v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_audio)
├── bevy_core v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_core)
├── bevy_core_pipeline v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_core_pipeline)
├── bevy_diagnostic v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_diagnostic)
├── bevy_ecs v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_ecs)
├── bevy_gilrs v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_gilrs)
├── bevy_gltf v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_gltf)
├── bevy_input v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_input)
├── bevy_internal v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_internal)
├── bevy_log v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_log)
├── bevy_pbr v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_pbr)
├── bevy_reflect v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_reflect)
├── bevy_render v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_render)
├── bevy_scene v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_scene)
├── bevy_sprite v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_sprite)
├── bevy_text v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_text)
├── bevy_transform v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_transform)
├── bevy_ui v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_ui)
├── bevy_window v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_window)
└── bevy_winit v0.6.0 (D:\repos\bevyengine\bevy\crates\bevy_winit)
crate uses core uses utils
bevy_app
bevy_asset
bevy_audio
bevy_core
bevy_core_pipeline
bevy_diagnostic
bevy_ecs
bevy_gilrs
bevy_gltf
bevy_input
bevy_internal
bevy_log
bevy_pbr
bevy_reflect
bevy_render
bevy_scene
bevy_sprite
bevy_text
bevy_transform
bevy_ui
bevy_window
bevy_winit

The bevy_time split pulls the timer functionality out of bevy_core; bevy_diagnostic no longer uses bevy_core, and uses bevy_time instead.

The FloatOrd move to bevy_utils means that five (5) crates on that list now no longer use bevy_core, and only use bevy_utils: bevy_core_pipeline, bevy_pbr, bevy_sprite, bevy_text, and bevy_ui.

The list of crates using bevy_core after these two PRs is just three (3):

  • bevy_gltf: bevy_core::Name.
  • bevy_render: bytemuck (cast_slice, Pod).
  • bevy_internals: duh.

Imho, bevy_utils should own Name; it already owns Label. The only reason I didn't make a PR for that already is that Name derives bevy_reflect::Reflect, and bevy_reflect uses bevy_utils. This looks to be an invertible dependency; bevy_reflect only uses bevy_utils::{AHasher, Duration, Entry, HashMap, HashSet, Uuid}, all of which are upstream reexports. Or Reflect could be implemented manually in bevy_reflect and keep the dependency edge the current direction. This is a bigger discussion/decision, so I haven't done it yet.

bevy_render can and probably should just use bytemuck directly. Or perhaps the bytemuck dependency and reexport should be lifted to bevy_utils rather than bevy_core.

And after that, all that remains is the CorePlugin, which does two things:

  • Creates the default task pools.
    • Imho, this feels like it should live in bevy_task (I have not looked into the practicality of moving this plugin functionality there).
    • Cart suggested it could go in bevy_ecs or just in bevy_internal.
  • Registers a bunch of types to the type registry: bevy_math types, primitive types, Range<f32>, String, Option<String>, HashSet<String>, Entity, and Name.
    • NB: FloatOrd isn't even type registered.
    • Imho, the primitive types should be inserted into the type registry by default upon creation in bevy_reflect.
    • The rest of the type registration I don't have a strong opinion on where they should logically go.

And because I installed the cargo plugin to generate these, enjoy some depgraphs (with transitive dependencies deduplicated to make it readable, and focused to the crates we're talking about):

[main ≡]> cargo depgraph --focus bevy_utils bevy_core bevy_time --dedup-transitive-deps

graphviz

[bevy_nore]> cargo depgraph --focus bevy_utils bevy_core bevy_time --dedup-transitive-deps

graphviz

(Note: any crate which doesn't transitively use bevy_utils does not show up in this graph, if any exist.)

@mockersf
Copy link
Member

nice, thanks for the great writeup!

bors bot pushed a commit that referenced this issue Apr 27, 2022
# Objective

Reduce the catch-all grab-bag of functionality in bevy_core by moving FloatOrd to bevy_utils.

A step in addressing #2931 and splitting bevy_core into more specific locations.

## Solution

Move FloatOrd into bevy_utils. Fix the compile errors.

As a result, bevy_core_pipeline, bevy_pbr, bevy_sprite, bevy_text, and bevy_ui no longer depend on bevy_core (they were only using it for `FloatOrd` previously).
exjam pushed a commit to exjam/bevy that referenced this issue May 22, 2022
# Objective

Reduce the catch-all grab-bag of functionality in bevy_core by moving FloatOrd to bevy_utils.

A step in addressing bevyengine#2931 and splitting bevy_core into more specific locations.

## Solution

Move FloatOrd into bevy_utils. Fix the compile errors.

As a result, bevy_core_pipeline, bevy_pbr, bevy_sprite, bevy_text, and bevy_ui no longer depend on bevy_core (they were only using it for `FloatOrd` previously).
@cart
Copy link
Member

cart commented May 25, 2022

Love the writeup! I like this general direction. Give that bytemuck is our go-to byte lib (and shows up in some of our user facing apis), I think it should ultimately be re-exported somewhere in bevy (the bevy crate should be usable "standalone" for most scenarios). Although that isn't really possible atm because we can't re-export the bytemuck derives without forking. Barring major UX hiccups I'm forgetting, I'm actually cool with removing the re-exports and just pulling in the crate manually when its needed (ex: in bevy_render). Then we can sort out the "right" way to re-export it, if we decide thats possible and necessary. In #4339 we've pioneered a new way to make upstream proc macros re-exportable from bevy. We might be able to convince the bytemuck authors to adopt that pattern.

CorePlugin currently fills the "setup random core bevy stuff" niche. I think we need something to do that, but bevy_core is the wrong place because it exists at the "bottom" of the dependency tree instead of near the "top". I think bevy_internal is worth considering for "random core bevy stuff" because it lets us unify "all" contexts. Ex: in #4745 the new camera bundles would benefit from having UI components in them, but right now they live in bevy_core_pipeline, which is lower in the dependency tree. They shouldn't live in bevy_ui because they are more "generic" than that. Defining the bundles in bevy_internal allows us to unify things arbitrarily in a global "bevy" context. The downside is that it makes those "unified" things only available if you take a dependency on bevy_internal, whereas before you could more easily pick and choose. An alternative is to just define new crates/plugins each time we have the need for a new unified context (ex: bevy_render_bundles, which could combine ui and core_pipeline components).

bors bot pushed a commit that referenced this issue May 26, 2022
# Objective

Reduce the catch-all grab-bag of functionality in bevy_core by minimally splitting off time functionality into bevy_time. Functionality like that provided by #3002 would increase the complexity of bevy_time, so this is a good candidate for pulling into its own unit.

A step in addressing #2931 and splitting bevy_core into more specific locations.

## Solution

Pull the time module of bevy_core into a new crate, bevy_time.

# Migration guide

- Time related types (e.g. `Time`, `Timer`, `Stopwatch`, `FixedTimestep`, etc.) should be imported from `bevy::time::*` rather than `bevy::core::*`.
- If you were adding `CorePlugin` manually, you'll also want to add `TimePlugin` from `bevy::time`.
- The `bevy::core::CorePlugin::Time` system label is replaced with `bevy::time::TimeSystem`.

Co-authored-by: Carter Anderson <[email protected]>
bors bot pushed a commit that referenced this issue Jun 3, 2022
# Objective

- Users of bevy_reflect probably always want primitive types registered.

## Solution

- Register them by default.

---

This is a minor incremental change along the path of [removing catch-all functionality from bevy_core](#2931).
MDeiml pushed a commit to MDeiml/bevy that referenced this issue Jun 4, 2022
# Objective

- Users of bevy_reflect probably always want primitive types registered.

## Solution

- Register them by default.

---

This is a minor incremental change along the path of [removing catch-all functionality from bevy_core](bevyengine#2931).
james7132 pushed a commit to james7132/bevy that referenced this issue Jun 7, 2022
# Objective

Reduce the catch-all grab-bag of functionality in bevy_core by minimally splitting off time functionality into bevy_time. Functionality like that provided by bevyengine#3002 would increase the complexity of bevy_time, so this is a good candidate for pulling into its own unit.

A step in addressing bevyengine#2931 and splitting bevy_core into more specific locations.

## Solution

Pull the time module of bevy_core into a new crate, bevy_time.

# Migration guide

- Time related types (e.g. `Time`, `Timer`, `Stopwatch`, `FixedTimestep`, etc.) should be imported from `bevy::time::*` rather than `bevy::core::*`.
- If you were adding `CorePlugin` manually, you'll also want to add `TimePlugin` from `bevy::time`.
- The `bevy::core::CorePlugin::Time` system label is replaced with `bevy::time::TimeSystem`.

Co-authored-by: Carter Anderson <[email protected]>
james7132 pushed a commit to james7132/bevy that referenced this issue Jun 7, 2022
# Objective

- Users of bevy_reflect probably always want primitive types registered.

## Solution

- Register them by default.

---

This is a minor incremental change along the path of [removing catch-all functionality from bevy_core](bevyengine#2931).
james7132 pushed a commit to james7132/bevy that referenced this issue Oct 28, 2022
# Objective

- Users of bevy_reflect probably always want primitive types registered.

## Solution

- Register them by default.

---

This is a minor incremental change along the path of [removing catch-all functionality from bevy_core](bevyengine#2931).
ItsDoot pushed a commit to ItsDoot/bevy that referenced this issue Feb 1, 2023
# Objective

- Users of bevy_reflect probably always want primitive types registered.

## Solution

- Register them by default.

---

This is a minor incremental change along the path of [removing catch-all functionality from bevy_core](bevyengine#2931).
ItsDoot pushed a commit to ItsDoot/bevy that referenced this issue Feb 1, 2023
# Objective

Reduce the catch-all grab-bag of functionality in bevy_core by moving FloatOrd to bevy_utils.

A step in addressing bevyengine#2931 and splitting bevy_core into more specific locations.

## Solution

Move FloatOrd into bevy_utils. Fix the compile errors.

As a result, bevy_core_pipeline, bevy_pbr, bevy_sprite, bevy_text, and bevy_ui no longer depend on bevy_core (they were only using it for `FloatOrd` previously).
ItsDoot pushed a commit to ItsDoot/bevy that referenced this issue Feb 1, 2023
# Objective

Reduce the catch-all grab-bag of functionality in bevy_core by minimally splitting off time functionality into bevy_time. Functionality like that provided by bevyengine#3002 would increase the complexity of bevy_time, so this is a good candidate for pulling into its own unit.

A step in addressing bevyengine#2931 and splitting bevy_core into more specific locations.

## Solution

Pull the time module of bevy_core into a new crate, bevy_time.

# Migration guide

- Time related types (e.g. `Time`, `Timer`, `Stopwatch`, `FixedTimestep`, etc.) should be imported from `bevy::time::*` rather than `bevy::core::*`.
- If you were adding `CorePlugin` manually, you'll also want to add `TimePlugin` from `bevy::time`.
- The `bevy::core::CorePlugin::Time` system label is replaced with `bevy::time::TimeSystem`.

Co-authored-by: Carter Anderson <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Core Common functionality for all bevy apps C-Code-Quality A section of code that is hard to understand or change C-Feature A new feature, making something new possible
Projects
None yet
Development

No branches or pull requests

4 participants