11use async_channel:: { Receiver , Sender } ;
2+
23use bevy_app:: { App , SubApp } ;
34use bevy_ecs:: {
45 schedule:: MainThreadExecutor ,
@@ -7,22 +8,19 @@ use bevy_ecs::{
78} ;
89use bevy_tasks:: ComputeTaskPool ;
910
10- #[ cfg( feature = "trace" ) ]
11- use bevy_utils:: tracing:: Instrument ;
12-
1311use crate :: { PipelinedRenderingApp , RenderApp } ;
1412
15- /// Resource to be used for pipelined rendering for sending the render app from the main thread to the rendering thread
13+ /// Resource for pipelined rendering to send the render app from the main thread to the rendering thread
1614#[ derive( Resource ) ]
1715pub struct MainToRenderAppSender ( pub Sender < SubApp > ) ;
1816
19- /// Resource used by pipelined rendering to send the render app from the render thread to the main thread
17+ /// Resource for pipelined rendering to send the render app from the render thread to the main thread
2018#[ derive( Resource ) ]
2119pub struct RenderToMainAppReceiver ( pub Receiver < SubApp > ) ;
2220
23- /// sets up the render thread and insert resource into the main app for controlling the render thread
21+ /// Sets up the render thread and inserts resources into the main app used for controlling the render thread
22+ /// This does nothing if pipelined rendering is not enabled.
2423pub fn setup_rendering ( app : & mut App ) {
25- // skip this if pipelined rendering is not enabled
2624 if app. get_sub_app ( PipelinedRenderingApp ) . is_err ( ) {
2725 return ;
2826 }
@@ -36,42 +34,38 @@ pub fn setup_rendering(app: &mut App) {
3634 app. insert_resource ( MainToRenderAppSender ( app_to_render_sender) ) ;
3735 app. insert_resource ( RenderToMainAppReceiver ( render_to_app_receiver) ) ;
3836
39- let render_task = async move {
40- loop {
41- // TODO: exit loop when app is exited
42- let recv_task = app_to_render_receiver. recv ( ) ;
43- let mut sub_app = recv_task. await . unwrap ( ) ;
44- sub_app. run ( ) ;
45- render_to_app_sender. send ( sub_app) . await . unwrap ( ) ;
46- }
47- } ;
48- #[ cfg( feature = "trace" ) ]
49- let span = bevy_utils:: tracing:: info_span!( "render app" ) ;
50- #[ cfg( feature = "trace" ) ]
51- let render_task = render_task. instrument ( span) ;
52- ComputeTaskPool :: get ( ) . spawn ( render_task) . detach ( ) ;
37+ ComputeTaskPool :: get ( )
38+ . spawn ( async move {
39+ loop {
40+ // TODO: exit loop when app is exited
41+ let recv_task = app_to_render_receiver. recv ( ) ;
42+ let mut sub_app = recv_task. await . unwrap ( ) ;
43+ sub_app. run ( ) ;
44+ render_to_app_sender. send ( sub_app) . await . unwrap ( ) ;
45+ }
46+ } )
47+ . detach ( ) ;
5348}
5449
50+ /// This function is used for synchronizing the main app with the render world.
51+ /// Do not call this function if pipelined rendering is not setup.
5552pub fn update_rendering ( app_world : & mut World ) {
56- // wait to get the render app back to signal that rendering is finished
57- let mut render_app = app_world
58- . resource_scope ( |world, main_thread_executor : Mut < MainThreadExecutor > | {
59- ComputeTaskPool :: get ( )
60- . scope ( Some ( main_thread_executor. 0 . clone ( ) ) , |s| {
61- s. spawn ( async {
62- let receiver = world. get_resource :: < RenderToMainAppReceiver > ( ) . unwrap ( ) ;
63- let recv = receiver. 0 . recv ( ) ;
64- recv. await . unwrap ( )
65- } ) ;
66- } )
67- . pop ( )
68- } )
69- . unwrap ( ) ;
53+ app_world. resource_scope ( |world, main_thread_executor : Mut < MainThreadExecutor > | {
54+ // we use a scope here to run any main thread tasks that the render world still needs to run
55+ // while we wait for the render world to be received.
56+ let mut render_app = ComputeTaskPool :: get ( )
57+ . scope ( Some ( main_thread_executor. 0 . clone ( ) ) , |s| {
58+ s. spawn ( async {
59+ let receiver = world. get_resource :: < RenderToMainAppReceiver > ( ) . unwrap ( ) ;
60+ receiver. 0 . recv ( ) . await . unwrap ( )
61+ } ) ;
62+ } )
63+ . pop ( )
64+ . unwrap ( ) ;
7065
71- render_app. extract ( app_world ) ;
66+ render_app. extract ( world ) ;
7267
73- app_world . resource_scope ( |_world , sender : Mut < MainToRenderAppSender > | {
68+ let sender = world . get_resource :: < MainToRenderAppSender > ( ) . unwrap ( ) ;
7469 sender. 0 . send_blocking ( render_app) . unwrap ( ) ;
7570 } ) ;
76- // frame pacing plugin should run here somehow. i.e. after rendering, but before input handling
7771}
0 commit comments