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

Main/Render schedules be run at different real timing. #8976

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

B-head
Copy link
Contributor

@B-head B-head commented Jun 27, 2023

This pull request is stacked on #8961.

Objective

Allow the tick rate and frame rate to be configured to different values.

This PR supports the prerequisite that the Main schedule and the Render schedule be run at different real timings.

Note that tick rate and frame rate control will be implemented in a later PR.

Solution

Call SubApp::extract and SubApp::run in the exclusive system. Add that system to the Render schedule.

Moved the responsibility for running top-level schedules from App struct to the runner function. Within the runner function, call World::run_schedule to run schedules separately.


Changelog

Added

  • Added app::SubApp::main_schedule_label.
  • Added app::ScheduleRunnerPlugin::main_schedule_label.
  • Added winit::WinitSettings::main_schedule_label.
  • Added winit::WinitSettings::render_schedule_label.
  • Added app::App::update_sub_apps.

Changed

  • Moved render::Render to app::Render.
  • Moved render::Render::base_schedule to render::RenderSet::base_schedule. (Back in place?)
  • Added Sync bounds to app::App::runner.
  • Added Sync bounds to app::SubApp::extract.
  • If only RenderPlugin is used, the RenderApp instance will not be accessible after cleanup.

Removed

  • Removed render::pipelined_rendering::RenderExtractApp.
  • Removed app::App::update.
  • Removed app::App::main_schedule_label.

Migration Guide

The top-level schedules configuration has been moved from App to plugins for setting the runner function. See ScheduleRunnerPlugin or WinitSettings.

Replace the code that calls App::update in the runner function with the following:

app.world.run_schedule(Main);
app.world.run_schedule(Render);
app.update_sub_apps();
app.world.clear_trackers();

(The real timing for running top-level schedules has not yet been changed.)

@alice-i-cecile alice-i-cecile added C-Enhancement A new feature A-Rendering Drawing game state to the screen A-App Bevy apps and plugins labels Jun 27, 2023
@alice-i-cecile alice-i-cecile requested a review from hymm June 27, 2023 21:33
@github-actions
Copy link
Contributor

Example no_renderer failed to run, please try running it locally and check the result.

@B-head B-head force-pushed the separate_main_and_render branch 2 times, most recently from 5aab12f to c50c30d Compare June 27, 2023 22:53
@@ -896,19 +896,19 @@ mod test {
// asset is loading
assert_eq!(LoadState::Loading, get_load_state(&handle, &app.world));

app.update();
app.world.run_schedule(Main);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is worse: we're leaking internal details and making a very common operation more verbose.

Can we keep App::update around and just call this on the main schedule label?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not do any test code refactoring, so it is verbose. 😅

Generally, &mut World is passed in the exclusive system, so it is basically never used in that form. Probably in the form of runner functions and test code only.

And this PR will no longer be used in the engine code. So I think the maintenance will be forgotten and App::update will stop working somewhere.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following up on @alice-i-cecile 's question, can we keep App::update()?

It is used in tests and examples, and replacing it with the four-line stanza makes it more difficult to write tests that need to run schedules. Making testing more difficult should be avoided. I say this after adding easily a dozen app.update() calls in the stepping PR for an example demonstrating stepping.

I think the maintenance will be forgotten and App::update will stop working somewhere.

The same argument applies if we replace the dozens of the existing App::update() calls with four other lines. The difference is that we'll only need to fix App::update() when it breaks.

I think we do need for some function to exist on mut App that is the equivalent of "run everything".

Copy link
Contributor

@hymm hymm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the goal of this PR? Is it to make it possible to call the the main schedule and the render schedule separately in the runner?

}

// skip setting up when using PipelinedRenderingPlugin
if app.world.get_resource::<MainThreadExecutor>().is_some() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MainThreadExecutor may not exist after we remove non send resources from the world. Is there another way of detecting that PipelinedRenderingPlugin is in use?

Copy link
Contributor Author

@B-head B-head Jun 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that PipelinedRenderingPlugin can be detected using App::is_plugin_added.

But either way, if MainThreadExecutor is removed, plugin will either panic or fail silently. Might it be better to change code further and make plugin always panic?

Want to include `SubApp` in a system function,
but `ExclusiveFunctionSystem` requires `Sync`.
Moved the responsibility for running top-level schedules
from `App` struct to the runner function.
@B-head
Copy link
Contributor Author

B-head commented Jun 28, 2023

I made a mistake and did not stack correctly on #8961, so I restored it.
The force push just before can be ignored.

@B-head
Copy link
Contributor Author

B-head commented Jun 28, 2023

What's the goal of this PR? Is it to make it possible to call the the main schedule and the render schedule separately in the runner?

In terms of implementation, yes.

In terms of designs, I want to remove obstacles to good design. Current status:

  • To run a render, the runner function must know details of the render plugin.
  • Since the App struct is responsibility for running the top-level schedule, the runner function can only be controlled indirectly from the App.

@B-head B-head mentioned this pull request Jul 3, 2023
8 tasks
@JMS55 JMS55 added this to the 0.13 milestone Nov 23, 2023
@alice-i-cecile alice-i-cecile removed this from the 0.13 milestone Jan 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-App Bevy apps and plugins A-Rendering Drawing game state to the screen C-Enhancement A new feature
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

5 participants