From db79899d1887ddd2ab17451ea37db48130ad38af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sat, 3 Feb 2024 08:31:42 +0100 Subject: [PATCH 1/5] split main-thread mandatory part into its own system --- crates/bevy_render/src/view/window/mod.rs | 96 +++++++++++++---------- 1 file changed, 56 insertions(+), 40 deletions(-) diff --git a/crates/bevy_render/src/view/window/mod.rs b/crates/bevy_render/src/view/window/mod.rs index 7f0e7d2f61a76..2344f3717b8a9 100644 --- a/crates/bevy_render/src/view/window/mod.rs +++ b/crates/bevy_render/src/view/window/mod.rs @@ -43,7 +43,8 @@ impl Plugin for WindowRenderPlugin { .init_resource::() .init_resource::() .add_systems(ExtractSchedule, extract_windows) - .add_systems(Render, prepare_windows.in_set(RenderSet::ManageViews)); + .add_systems(Render, prepare_windows.in_set(RenderSet::PrepareAssets)) + .add_systems(Render, create_surfaces.in_set(RenderSet::ManageViews)); } } @@ -213,7 +214,7 @@ impl WindowSurfaces { } } -/// Creates and (re)configures window surfaces, and obtains a swapchain texture for rendering. +/// (re)configures window surfaces, and obtains a swapchain texture for rendering. /// /// NOTE: `get_current_texture` in `prepare_windows` can take a long time if the GPU workload is /// the performance bottleneck. This can be seen in profiles as multiple prepare-set systems all @@ -236,13 +237,9 @@ impl WindowSurfaces { /// later. #[allow(clippy::too_many_arguments)] pub fn prepare_windows( - // By accessing a NonSend resource, we tell the scheduler to put this system on the main thread, - // which is necessary for some OS's - #[cfg(any(target_os = "macos", target_os = "ios"))] _marker: Option>, mut windows: ResMut, mut window_surfaces: ResMut, render_device: Res, - render_instance: Res, render_adapter: Res, screenshot_pipeline: Res, pipeline_cache: Res, @@ -251,40 +248,9 @@ pub fn prepare_windows( ) { for window in windows.windows.values_mut() { let window_surfaces = window_surfaces.deref_mut(); - let surface_data = window_surfaces - .surfaces - .entry(window.entity) - .or_insert_with(|| { - let surface_target = SurfaceTargetUnsafe::RawHandle { - raw_display_handle: window.handle.display_handle, - raw_window_handle: window.handle.window_handle, - }; - // SAFETY: The window handles in ExtractedWindows will always be valid objects to create surfaces on - let surface = unsafe { - // NOTE: On some OSes this MUST be called from the main thread. - // As of wgpu 0.15, only fallible if the given window is a HTML canvas and obtaining a WebGPU or WebGL2 context fails. - render_instance - .create_surface_unsafe(surface_target) - .expect("Failed to create wgpu surface") - }; - let caps = surface.get_capabilities(&render_adapter); - let formats = caps.formats; - // For future HDR output support, we'll need to request a format that supports HDR, - // but as of wgpu 0.15 that is not yet supported. - // Prefer sRGB formats for surfaces, but fall back to first available format if no sRGB formats are available. - let mut format = *formats.first().expect("No supported formats for surface"); - for available_format in formats { - // Rgba8UnormSrgb and Bgra8UnormSrgb and the only sRGB formats wgpu exposes that we can use for surfaces. - if available_format == TextureFormat::Rgba8UnormSrgb - || available_format == TextureFormat::Bgra8UnormSrgb - { - format = available_format; - break; - } - } - - SurfaceData { surface, format } - }); + let Some(surface_data) = window_surfaces.surfaces.get(&window.entity) else { + continue; + }; let surface_configuration = wgpu::SurfaceConfiguration { format: surface_data.format, @@ -451,3 +417,53 @@ pub fn prepare_windows( } } } + +/// Creates window surfaces. +#[allow(clippy::too_many_arguments)] +pub fn create_surfaces( + // By accessing a NonSend resource, we tell the scheduler to put this system on the main thread, + // which is necessary for some OS's + #[cfg(any(target_os = "macos", target_os = "ios"))] _marker: Option>, + windows: Res, + mut window_surfaces: ResMut, + render_instance: Res, + render_adapter: Res, +) { + for window in windows.windows.values() { + let window_surfaces = window_surfaces.deref_mut(); + window_surfaces + .surfaces + .entry(window.entity) + .or_insert_with(|| { + let surface_target = SurfaceTargetUnsafe::RawHandle { + raw_display_handle: window.handle.display_handle, + raw_window_handle: window.handle.window_handle, + }; + // SAFETY: The window handles in ExtractedWindows will always be valid objects to create surfaces on + let surface = unsafe { + // NOTE: On some OSes this MUST be called from the main thread. + // As of wgpu 0.15, only fallible if the given window is a HTML canvas and obtaining a WebGPU or WebGL2 context fails. + render_instance + .create_surface_unsafe(surface_target) + .expect("Failed to create wgpu surface") + }; + let caps = surface.get_capabilities(&render_adapter); + let formats = caps.formats; + // For future HDR output support, we'll need to request a format that supports HDR, + // but as of wgpu 0.15 that is not yet supported. + // Prefer sRGB formats for surfaces, but fall back to first available format if no sRGB formats are available. + let mut format = *formats.first().expect("No supported formats for surface"); + for available_format in formats { + // Rgba8UnormSrgb and Bgra8UnormSrgb and the only sRGB formats wgpu exposes that we can use for surfaces. + if available_format == TextureFormat::Rgba8UnormSrgb + || available_format == TextureFormat::Bgra8UnormSrgb + { + format = available_format; + break; + } + } + + SurfaceData { surface, format } + }); + } +} From 871521c3fdd37c8296a56bed04c3e086e0317054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sat, 3 Feb 2024 08:49:37 +0100 Subject: [PATCH 2/5] add the linux-only parameter --- crates/bevy_render/src/view/window/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/bevy_render/src/view/window/mod.rs b/crates/bevy_render/src/view/window/mod.rs index 2344f3717b8a9..b294a3f222a5c 100644 --- a/crates/bevy_render/src/view/window/mod.rs +++ b/crates/bevy_render/src/view/window/mod.rs @@ -245,6 +245,7 @@ pub fn prepare_windows( pipeline_cache: Res, mut pipelines: ResMut>, mut msaa: ResMut, + #[cfg(any(target_os = "linux"))] render_instance: Res, ) { for window in windows.windows.values_mut() { let window_surfaces = window_surfaces.deref_mut(); From 95af8fec5722299263970cca81ced3aaa53c0589 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sat, 3 Feb 2024 08:53:04 +0100 Subject: [PATCH 3/5] bad any --- crates/bevy_render/src/view/window/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_render/src/view/window/mod.rs b/crates/bevy_render/src/view/window/mod.rs index b294a3f222a5c..b0ae008f3799b 100644 --- a/crates/bevy_render/src/view/window/mod.rs +++ b/crates/bevy_render/src/view/window/mod.rs @@ -245,7 +245,7 @@ pub fn prepare_windows( pipeline_cache: Res, mut pipelines: ResMut>, mut msaa: ResMut, - #[cfg(any(target_os = "linux"))] render_instance: Res, + #[cfg(target_os = "linux")] render_instance: Res, ) { for window in windows.windows.values_mut() { let window_surfaces = window_surfaces.deref_mut(); From 0e6b0bc43a5e02aeca4ff040595119441474cafe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sat, 3 Feb 2024 09:49:10 +0100 Subject: [PATCH 4/5] remove unneeded lint allow --- crates/bevy_render/src/view/window/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/bevy_render/src/view/window/mod.rs b/crates/bevy_render/src/view/window/mod.rs index b0ae008f3799b..2559b95a4fa29 100644 --- a/crates/bevy_render/src/view/window/mod.rs +++ b/crates/bevy_render/src/view/window/mod.rs @@ -420,7 +420,6 @@ pub fn prepare_windows( } /// Creates window surfaces. -#[allow(clippy::too_many_arguments)] pub fn create_surfaces( // By accessing a NonSend resource, we tell the scheduler to put this system on the main thread, // which is necessary for some OS's From c5b3540d2c84ac034146e9d14557f57714fde96b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sat, 3 Feb 2024 09:59:37 +0100 Subject: [PATCH 5/5] remove unneeded deref_mut --- crates/bevy_render/src/view/window/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/bevy_render/src/view/window/mod.rs b/crates/bevy_render/src/view/window/mod.rs index 2559b95a4fa29..d10e354a17316 100644 --- a/crates/bevy_render/src/view/window/mod.rs +++ b/crates/bevy_render/src/view/window/mod.rs @@ -430,7 +430,6 @@ pub fn create_surfaces( render_adapter: Res, ) { for window in windows.windows.values() { - let window_surfaces = window_surfaces.deref_mut(); window_surfaces .surfaces .entry(window.entity)