Skip to content
Open
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
68 changes: 51 additions & 17 deletions crates/bevy_render/src/view/window/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use core::{
num::NonZero,
ops::{Deref, DerefMut},
};
use tracing::{debug, warn};
use tracing::{debug, info, warn};
use wgpu::{
SurfaceConfiguration, SurfaceTargetUnsafe, TextureFormat, TextureUsages, TextureViewDescriptor,
};
Expand Down Expand Up @@ -348,6 +348,7 @@ pub fn create_surfaces(
.expect("Failed to create wgpu surface")
};
let caps = surface.get_capabilities(&render_adapter);
let present_mode = present_mode(window, &caps);
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.
Expand All @@ -368,14 +369,7 @@ pub fn create_surfaces(
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,
},
present_mode,
desired_maximum_frame_latency: window
.desired_maximum_frame_latency
.map(NonZero::<u32>::get)
Expand Down Expand Up @@ -413,17 +407,57 @@ pub fn create_surfaces(

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,
};
let caps = data.surface.get_capabilities(&render_adapter);
data.configuration.present_mode = present_mode(window, &caps);
render_device.configure_surface(&data.surface, &data.configuration);
}

window_surfaces.configured_windows.insert(window.entity);
}
}

fn present_mode(
window: &mut ExtractedWindow,
caps: &wgpu::SurfaceCapabilities,
) -> wgpu::PresentMode {
let 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,
};
let fallbacks = match present_mode {
wgpu::PresentMode::AutoVsync => {
&[wgpu::PresentMode::FifoRelaxed, wgpu::PresentMode::Fifo][..]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does the &[][..] syntax do?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It turns it into a slice. Rust thinks these are array references if we dont do that, and the match complains about heterogeneous return value.

}
wgpu::PresentMode::AutoNoVsync => &[
wgpu::PresentMode::Immediate,
wgpu::PresentMode::Mailbox,
wgpu::PresentMode::Fifo,
][..],
wgpu::PresentMode::Mailbox => &[
wgpu::PresentMode::Mailbox,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it intentional that in some cases the fallbacks start with the mode they're for, and in other cases not?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, AutoVsync and AutoNoVsync are not actual presentation modes, they never show up in surface caps. Wgpu offers them as a "reasonable defaults" fallback order so that not everyone has to do this cap check type logic in their apps from what i gather. The logic here is the same as in the wgpu source: these two modes convert to this set of fallbacks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, okay that explains it, thanks.

wgpu::PresentMode::Immediate,
wgpu::PresentMode::Fifo,
][..],
// Always end in FIFO to make sure it's always supported
x => &[x, wgpu::PresentMode::Fifo][..],
};
let new_present_mode = fallbacks
.iter()
.copied()
.find(|fallback| caps.present_modes.contains(fallback))
.unwrap_or_else(|| {
unreachable!(
"Fallback system failed to choose present mode. \
This is a bug. Mode: {:?}, Options: {:?}",
window.present_mode, &caps.present_modes
);
});
if new_present_mode != present_mode && fallbacks.contains(&present_mode) {
info!("PresentMode {present_mode:?} requested but not available. Falling back to {new_present_mode:?}");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may be a little chatty for something like AutoNoVsync where it's not really like you "requested" Immediate, you're more like "just gimme whatever works"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AutoNoVsync and AutoVsync will not log because of the fallbacks.contains(&present_mode) check

}
new_present_mode
}