1
1
use async_channel:: { Receiver , Sender } ;
2
+
2
3
use bevy_app:: { App , SubApp } ;
3
4
use bevy_ecs:: {
4
5
schedule:: MainThreadExecutor ,
@@ -7,22 +8,19 @@ use bevy_ecs::{
7
8
} ;
8
9
use bevy_tasks:: ComputeTaskPool ;
9
10
10
- #[ cfg( feature = "trace" ) ]
11
- use bevy_utils:: tracing:: Instrument ;
12
-
13
11
use crate :: { PipelinedRenderingApp , RenderApp } ;
14
12
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
16
14
#[ derive( Resource ) ]
17
15
pub struct MainToRenderAppSender ( pub Sender < SubApp > ) ;
18
16
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
20
18
#[ derive( Resource ) ]
21
19
pub struct RenderToMainAppReceiver ( pub Receiver < SubApp > ) ;
22
20
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.
24
23
pub fn setup_rendering ( app : & mut App ) {
25
- // skip this if pipelined rendering is not enabled
26
24
if app. get_sub_app ( PipelinedRenderingApp ) . is_err ( ) {
27
25
return ;
28
26
}
@@ -36,42 +34,38 @@ pub fn setup_rendering(app: &mut App) {
36
34
app. insert_resource ( MainToRenderAppSender ( app_to_render_sender) ) ;
37
35
app. insert_resource ( RenderToMainAppReceiver ( render_to_app_receiver) ) ;
38
36
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 ( ) ;
53
48
}
54
49
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.
55
52
pub 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 ( ) ;
70
65
71
- render_app. extract ( app_world ) ;
66
+ render_app. extract ( world ) ;
72
67
73
- app_world . resource_scope ( |_world , sender : Mut < MainToRenderAppSender > | {
68
+ let sender = world . get_resource :: < MainToRenderAppSender > ( ) . unwrap ( ) ;
74
69
sender. 0 . send_blocking ( render_app) . unwrap ( ) ;
75
70
} ) ;
76
- // frame pacing plugin should run here somehow. i.e. after rendering, but before input handling
77
71
}
0 commit comments