@@ -90,6 +90,7 @@ use alloc::sync::Arc;
9090use batching:: gpu_preprocessing:: BatchingPlugin ;
9191use bevy_app:: { App , AppLabel , Plugin , SubApp } ;
9292use bevy_asset:: { AssetApp , AssetServer } ;
93+ use bevy_derive:: { Deref , DerefMut } ;
9394use bevy_ecs:: {
9495 prelude:: * ,
9596 schedule:: { ScheduleBuildSettings , ScheduleLabel } ,
@@ -99,7 +100,6 @@ use bevy_shader::{load_shader_library, Shader, ShaderLoader};
99100use bevy_utils:: prelude:: default;
100101use bevy_window:: { PrimaryWindow , RawHandleWrapperHolder } ;
101102use bitflags:: bitflags;
102- use core:: ops:: { Deref , DerefMut } ;
103103use globals:: GlobalsPlugin ;
104104use occlusion_culling:: OcclusionCullingPlugin ;
105105use render_asset:: {
@@ -260,25 +260,11 @@ pub struct ExtractSchedule;
260260/// This resource is only available during [`ExtractSchedule`] and not
261261/// during command application of that schedule.
262262/// See [`Extract`] for more details.
263- #[ derive( Resource , Default ) ]
263+ #[ derive( Resource , Default , Deref , DerefMut ) ]
264264pub struct MainWorld ( World ) ;
265265
266- impl Deref for MainWorld {
267- type Target = World ;
268-
269- fn deref ( & self ) -> & Self :: Target {
270- & self . 0
271- }
272- }
273-
274- impl DerefMut for MainWorld {
275- fn deref_mut ( & mut self ) -> & mut Self :: Target {
276- & mut self . 0
277- }
278- }
279-
280- #[ derive( Resource ) ]
281- struct FutureRenderResources ( Arc < Mutex < Option < RenderResources > > > ) ;
266+ #[ derive( Resource , Default , Clone , Deref ) ]
267+ pub ( crate ) struct FutureRenderResources ( Arc < Mutex < Option < RenderResources > > > ) ;
282268
283269/// A label for the rendering sub-app.
284270#[ derive( Debug , Clone , Copy , Hash , PartialEq , Eq , AppLabel ) ]
@@ -290,64 +276,31 @@ impl Plugin for RenderPlugin {
290276 app. init_asset :: < Shader > ( )
291277 . init_asset_loader :: < ShaderLoader > ( ) ;
292278
293- match & self . render_creation {
294- RenderCreation :: Manual ( resources) => {
295- let future_render_resources_wrapper = Arc :: new ( Mutex :: new ( Some ( resources. clone ( ) ) ) ) ;
296- app. insert_resource ( FutureRenderResources (
297- future_render_resources_wrapper. clone ( ) ,
298- ) ) ;
299- // SAFETY: Plugins should be set up on the main thread.
300- unsafe { initialize_render_app ( app) } ;
301- }
302- RenderCreation :: Automatic ( render_creation) => {
303- if let Some ( backends) = render_creation. backends {
304- let future_render_resources_wrapper = Arc :: new ( Mutex :: new ( None ) ) ;
305- app. insert_resource ( FutureRenderResources (
306- future_render_resources_wrapper. clone ( ) ,
307- ) ) ;
308-
309- let primary_window = app
310- . world_mut ( )
311- . query_filtered :: < & RawHandleWrapperHolder , With < PrimaryWindow > > ( )
312- . single ( app. world ( ) )
313- . ok ( )
314- . cloned ( ) ;
315-
316- let settings = render_creation. clone ( ) ;
317-
318- #[ cfg( feature = "raw_vulkan_init" ) ]
319- let raw_vulkan_init_settings = app
320- . world_mut ( )
321- . get_resource :: < renderer:: raw_vulkan_init:: RawVulkanInitSettings > ( )
322- . cloned ( )
323- . unwrap_or_default ( ) ;
324-
325- let async_renderer = async move {
326- let render_resources = renderer:: initialize_renderer (
327- backends,
328- primary_window,
329- & settings,
330- #[ cfg( feature = "raw_vulkan_init" ) ]
331- raw_vulkan_init_settings,
332- )
333- . await ;
334-
335- * future_render_resources_wrapper. lock ( ) . unwrap ( ) = Some ( render_resources) ;
336- } ;
337-
338- // In wasm, spawn a task and detach it for execution
339- #[ cfg( target_arch = "wasm32" ) ]
340- bevy_tasks:: IoTaskPool :: get ( )
341- . spawn_local ( async_renderer)
342- . detach ( ) ;
343- // Otherwise, just block for it to complete
344- #[ cfg( not( target_arch = "wasm32" ) ) ]
345- bevy_tasks:: block_on ( async_renderer) ;
346-
347- // SAFETY: Plugins should be set up on the main thread.
348- unsafe { initialize_render_app ( app) } ;
349- }
350- }
279+ let primary_window = app
280+ . world_mut ( )
281+ . query_filtered :: < & RawHandleWrapperHolder , With < PrimaryWindow > > ( )
282+ . single ( app. world ( ) )
283+ . ok ( )
284+ . cloned ( ) ;
285+
286+ #[ cfg( feature = "raw_vulkan_init" ) ]
287+ let raw_vulkan_init_settings = app
288+ . world_mut ( )
289+ . get_resource :: < renderer:: raw_vulkan_init:: RawVulkanInitSettings > ( )
290+ . cloned ( )
291+ . unwrap_or_default ( ) ;
292+
293+ let future_resources = FutureRenderResources :: default ( ) ;
294+ if self . render_creation . create_render (
295+ future_resources. clone ( ) ,
296+ primary_window,
297+ #[ cfg( feature = "raw_vulkan_init" ) ]
298+ raw_vulkan_init_settings,
299+ ) {
300+ // Note that `future_resources` is not necessarily populated here yet.
301+ app. insert_resource ( future_resources) ;
302+ // SAFETY: Plugins should be set up on the main thread.
303+ unsafe { initialize_render_app ( app) } ;
351304 } ;
352305
353306 app. add_plugins ( (
@@ -383,9 +336,17 @@ impl Plugin for RenderPlugin {
383336 }
384337
385338 fn ready ( & self , app : & App ) -> bool {
339+ // This is a little tricky. `FutureRenderResources` is added in `build`, which runs synchronously before `ready`.
340+ // It is only added if there is a wgpu backend and thus the renderer can be created.
341+ // Hence, if we try and get the resource and it is not present, that means we are ready, because we dont need it.
342+ // On the other hand, if the resource is present, then we try and lock on it. The lock can fail, in which case
343+ // we currently can assume that means the `FutureRenderResources` is in the act of being populated, because
344+ // that is the only other place the lock may be held. If it is being populated, we can assume we're ready. This
345+ // happens via the `and_then` falling through to the same `unwrap_or(true)` case as when there's no resource.
346+ // If the lock succeeds, we can straightforwardly check if it is populated. If it is not, then we're not ready.
386347 app. world ( )
387348 . get_resource :: < FutureRenderResources > ( )
388- . and_then ( |frr| frr. 0 . try_lock ( ) . map ( |locked| locked. is_some ( ) ) . ok ( ) )
349+ . and_then ( |frr| frr. try_lock ( ) . map ( |locked| locked. is_some ( ) ) . ok ( ) )
389350 . unwrap_or ( true )
390351 }
391352
0 commit comments