Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

configure_surface needs to be on the main thread on iOS #12055

Merged
merged 2 commits into from
Feb 29, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 76 additions & 49 deletions crates/bevy_render/src/view/window/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ use std::{
sync::PoisonError,
};
use wgpu::{
BufferUsages, SurfaceTargetUnsafe, TextureFormat, TextureUsages, TextureViewDescriptor,
BufferUsages, SurfaceConfiguration, SurfaceTargetUnsafe, TextureFormat, TextureUsages,
TextureViewDescriptor,
};

pub mod screenshot;
Expand All @@ -42,7 +43,7 @@ impl Plugin for WindowRenderPlugin {
.add_systems(
Render,
create_surfaces
.run_if(need_new_surfaces)
.run_if(need_surface_configuration)
.before(prepare_windows),
)
.add_systems(Render, prepare_windows.in_set(RenderSet::ManageViews));
Expand Down Expand Up @@ -198,7 +199,7 @@ fn extract_windows(
struct SurfaceData {
// TODO: what lifetime should this be?
surface: wgpu::Surface<'static>,
format: TextureFormat,
configuration: SurfaceConfiguration,
}

#[derive(Resource, Default)]
Expand Down Expand Up @@ -254,45 +255,12 @@ pub fn prepare_windows(
continue;
};

let surface_configuration = wgpu::SurfaceConfiguration {
format: surface_data.format,
width: window.physical_width,
height: window.physical_height,
usage: TextureUsages::RENDER_ATTACHMENT,
present_mode: match window.present_mode {
PresentMode::Fifo => wgpu::PresentMode::Fifo,
PresentMode::FifoRelaxed => wgpu::PresentMode::FifoRelaxed,
PresentMode::Mailbox => wgpu::PresentMode::Mailbox,
PresentMode::Immediate => wgpu::PresentMode::Immediate,
PresentMode::AutoVsync => wgpu::PresentMode::AutoVsync,
PresentMode::AutoNoVsync => wgpu::PresentMode::AutoNoVsync,
},
// TODO: Expose this as a setting somewhere
// 2 is wgpu's default/what we've been using so far.
// 1 is the minimum, but may cause lower framerates due to the cpu waiting for the gpu to finish
// all work for the previous frame before starting work on the next frame, which then means the gpu
// has to wait for the cpu to finish to start on the next frame.
desired_maximum_frame_latency: 2,
alpha_mode: match window.alpha_mode {
CompositeAlphaMode::Auto => wgpu::CompositeAlphaMode::Auto,
CompositeAlphaMode::Opaque => wgpu::CompositeAlphaMode::Opaque,
CompositeAlphaMode::PreMultiplied => wgpu::CompositeAlphaMode::PreMultiplied,
CompositeAlphaMode::PostMultiplied => wgpu::CompositeAlphaMode::PostMultiplied,
CompositeAlphaMode::Inherit => wgpu::CompositeAlphaMode::Inherit,
},
view_formats: if !surface_data.format.is_srgb() {
vec![surface_data.format.add_srgb_suffix()]
} else {
vec![]
},
};

// This is an ugly hack to work around drivers that don't support MSAA.
// This should be removed once https://github.com/bevyengine/bevy/issues/7194 lands and we're doing proper
// feature detection for MSAA.
// When removed, we can also remove the `.after(prepare_windows)` of `prepare_core_3d_depth_textures` and `prepare_prepass_textures`
let sample_flags = render_adapter
.get_texture_format_features(surface_configuration.format)
.get_texture_format_features(surface_data.configuration.format)
.flags;

if !sample_flags.sample_count_supported(msaa.samples()) {
Expand Down Expand Up @@ -340,7 +308,6 @@ pub fn prepare_windows(

let surface = &surface_data.surface;
if not_already_configured || window.size_changed || window.present_mode_changed {
render_device.configure_surface(surface, &surface_configuration);
let frame = surface
.get_current_texture()
.expect("Error configuring surface");
Expand All @@ -351,7 +318,7 @@ pub fn prepare_windows(
window.set_swapchain_texture(frame);
}
Err(wgpu::SurfaceError::Outdated) => {
render_device.configure_surface(surface, &surface_configuration);
render_device.configure_surface(surface, &surface_data.configuration);
let frame = surface
.get_current_texture()
.expect("Error reconfiguring surface");
Expand All @@ -369,20 +336,20 @@ pub fn prepare_windows(
}
}
};
window.swap_chain_texture_format = Some(surface_data.format);
window.swap_chain_texture_format = Some(surface_data.configuration.format);

if window.screenshot_func.is_some() {
let texture = render_device.create_texture(&wgpu::TextureDescriptor {
label: Some("screenshot-capture-rendertarget"),
size: wgpu::Extent3d {
width: surface_configuration.width,
height: surface_configuration.height,
width: surface_data.configuration.width,
height: surface_data.configuration.height,
depth_or_array_layers: 1,
},
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: surface_configuration.format.add_srgb_suffix(),
format: surface_data.configuration.format.add_srgb_suffix(),
usage: TextureUsages::RENDER_ATTACHMENT
| TextureUsages::COPY_SRC
| TextureUsages::TEXTURE_BINDING,
Expand All @@ -394,7 +361,7 @@ pub fn prepare_windows(
size: screenshot::get_aligned_size(
window.physical_width,
window.physical_height,
surface_data.format.pixel_size() as u32,
surface_data.configuration.format.pixel_size() as u32,
) as u64,
usage: BufferUsages::MAP_READ | BufferUsages::COPY_DST,
mapped_at_creation: false,
Expand All @@ -407,7 +374,7 @@ pub fn prepare_windows(
let pipeline_id = pipelines.specialize(
&pipeline_cache,
&screenshot_pipeline,
surface_configuration.format,
surface_data.configuration.format,
);
window.swap_chain_texture_view = Some(texture_view);
window.screenshot_memory = Some(ScreenshotPreparedState {
Expand All @@ -420,12 +387,15 @@ pub fn prepare_windows(
}
}

pub fn need_new_surfaces(
pub fn need_surface_configuration(
mockersf marked this conversation as resolved.
Show resolved Hide resolved
windows: Res<ExtractedWindows>,
window_surfaces: Res<WindowSurfaces>,
) -> bool {
for window in windows.windows.values() {
if !window_surfaces.configured_windows.contains(&window.entity) {
if !window_surfaces.configured_windows.contains(&window.entity)
|| window.size_changed
|| window.present_mode_changed
{
return true;
}
}
Expand All @@ -443,9 +413,10 @@ pub fn create_surfaces(
mut window_surfaces: ResMut<WindowSurfaces>,
render_instance: Res<RenderInstance>,
render_adapter: Res<RenderAdapter>,
render_device: Res<RenderDevice>,
) {
for window in windows.windows.values() {
window_surfaces
let data = window_surfaces
.surfaces
.entry(window.entity)
.or_insert_with(|| {
Expand Down Expand Up @@ -477,7 +448,63 @@ pub fn create_surfaces(
}
}

SurfaceData { surface, format }
let configuration = wgpu::SurfaceConfiguration {
format,
width: window.physical_width,
height: window.physical_height,
usage: TextureUsages::RENDER_ATTACHMENT,
present_mode: match window.present_mode {
PresentMode::Fifo => wgpu::PresentMode::Fifo,
PresentMode::FifoRelaxed => wgpu::PresentMode::FifoRelaxed,
PresentMode::Mailbox => wgpu::PresentMode::Mailbox,
PresentMode::Immediate => wgpu::PresentMode::Immediate,
PresentMode::AutoVsync => wgpu::PresentMode::AutoVsync,
PresentMode::AutoNoVsync => wgpu::PresentMode::AutoNoVsync,
},
// TODO: Expose this as a setting somewhere
// 2 is wgpu's default/what we've been using so far.
// 1 is the minimum, but may cause lower framerates due to the cpu waiting for the gpu to finish
// all work for the previous frame before starting work on the next frame, which then means the gpu
// has to wait for the cpu to finish to start on the next frame.
desired_maximum_frame_latency: 2,
alpha_mode: match window.alpha_mode {
CompositeAlphaMode::Auto => wgpu::CompositeAlphaMode::Auto,
CompositeAlphaMode::Opaque => wgpu::CompositeAlphaMode::Opaque,
CompositeAlphaMode::PreMultiplied => {
wgpu::CompositeAlphaMode::PreMultiplied
}
CompositeAlphaMode::PostMultiplied => {
wgpu::CompositeAlphaMode::PostMultiplied
}
CompositeAlphaMode::Inherit => wgpu::CompositeAlphaMode::Inherit,
},
view_formats: if !format.is_srgb() {
vec![format.add_srgb_suffix()]
} else {
vec![]
},
};

render_device.configure_surface(&surface, &configuration);

SurfaceData {
surface,
configuration,
}
});

if window.size_changed || window.present_mode_changed {
data.configuration.width = window.physical_width;
data.configuration.height = window.physical_height;
data.configuration.present_mode = match window.present_mode {
PresentMode::Fifo => wgpu::PresentMode::Fifo,
PresentMode::FifoRelaxed => wgpu::PresentMode::FifoRelaxed,
PresentMode::Mailbox => wgpu::PresentMode::Mailbox,
PresentMode::Immediate => wgpu::PresentMode::Immediate,
PresentMode::AutoVsync => wgpu::PresentMode::AutoVsync,
PresentMode::AutoNoVsync => wgpu::PresentMode::AutoNoVsync,
};
render_device.configure_surface(&data.surface, &data.configuration);
cart marked this conversation as resolved.
Show resolved Hide resolved
}
}
}