mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Allow prepare_windows to run off main thread on all platforms (#11672)
# Objective - Allow prepare windows to run off of the main thread on all platforms. - Fixes https://github.com/bevyengine/bevy/issues/9964 on all platforms. ## Solution - Running `prepare_windows` on the main thread on apple platforms is only mandatory to create surface, which is only needed during window creation. Split that part into its own system that happens before `prepare_windows` - Tested on macOS and iOS --- ## Changelog - Allow prepare windows to run off main thread on all platforms.
This commit is contained in:
parent
9bad607df9
commit
55493a823e
1 changed files with 55 additions and 40 deletions
|
@ -43,7 +43,8 @@ impl Plugin for WindowRenderPlugin {
|
||||||
.init_resource::<ExtractedWindows>()
|
.init_resource::<ExtractedWindows>()
|
||||||
.init_resource::<WindowSurfaces>()
|
.init_resource::<WindowSurfaces>()
|
||||||
.add_systems(ExtractSchedule, extract_windows)
|
.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
|
/// 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
|
/// the performance bottleneck. This can be seen in profiles as multiple prepare-set systems all
|
||||||
|
@ -236,55 +237,21 @@ impl WindowSurfaces {
|
||||||
/// later.
|
/// later.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn prepare_windows(
|
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<NonSend<NonSendMarker>>,
|
|
||||||
mut windows: ResMut<ExtractedWindows>,
|
mut windows: ResMut<ExtractedWindows>,
|
||||||
mut window_surfaces: ResMut<WindowSurfaces>,
|
mut window_surfaces: ResMut<WindowSurfaces>,
|
||||||
render_device: Res<RenderDevice>,
|
render_device: Res<RenderDevice>,
|
||||||
render_instance: Res<RenderInstance>,
|
|
||||||
render_adapter: Res<RenderAdapter>,
|
render_adapter: Res<RenderAdapter>,
|
||||||
screenshot_pipeline: Res<ScreenshotToScreenPipeline>,
|
screenshot_pipeline: Res<ScreenshotToScreenPipeline>,
|
||||||
pipeline_cache: Res<PipelineCache>,
|
pipeline_cache: Res<PipelineCache>,
|
||||||
mut pipelines: ResMut<SpecializedRenderPipelines<ScreenshotToScreenPipeline>>,
|
mut pipelines: ResMut<SpecializedRenderPipelines<ScreenshotToScreenPipeline>>,
|
||||||
mut msaa: ResMut<Msaa>,
|
mut msaa: ResMut<Msaa>,
|
||||||
|
#[cfg(target_os = "linux")] render_instance: Res<RenderInstance>,
|
||||||
) {
|
) {
|
||||||
for window in windows.windows.values_mut() {
|
for window in windows.windows.values_mut() {
|
||||||
let window_surfaces = window_surfaces.deref_mut();
|
let window_surfaces = window_surfaces.deref_mut();
|
||||||
let surface_data = window_surfaces
|
let Some(surface_data) = window_surfaces.surfaces.get(&window.entity) else {
|
||||||
.surfaces
|
continue;
|
||||||
.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 surface_configuration = wgpu::SurfaceConfiguration {
|
let surface_configuration = wgpu::SurfaceConfiguration {
|
||||||
format: surface_data.format,
|
format: surface_data.format,
|
||||||
|
@ -451,3 +418,51 @@ pub fn prepare_windows(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates window surfaces.
|
||||||
|
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<NonSend<NonSendMarker>>,
|
||||||
|
windows: Res<ExtractedWindows>,
|
||||||
|
mut window_surfaces: ResMut<WindowSurfaces>,
|
||||||
|
render_instance: Res<RenderInstance>,
|
||||||
|
render_adapter: Res<RenderAdapter>,
|
||||||
|
) {
|
||||||
|
for window in windows.windows.values() {
|
||||||
|
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 }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue