-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Add PresentMode fallbacks #22108
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
base: main
Are you sure you want to change the base?
Add PresentMode fallbacks #22108
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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, | ||
| }; | ||
|
|
@@ -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. | ||
|
|
@@ -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) | ||
|
|
@@ -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][..] | ||
| } | ||
| wgpu::PresentMode::AutoNoVsync => &[ | ||
| wgpu::PresentMode::Immediate, | ||
| wgpu::PresentMode::Mailbox, | ||
| wgpu::PresentMode::Fifo, | ||
| ][..], | ||
| wgpu::PresentMode::Mailbox => &[ | ||
| wgpu::PresentMode::Mailbox, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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:?}"); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This may be a little chatty for something like
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AutoNoVsync and AutoVsync will not log because of the |
||
| } | ||
| new_present_mode | ||
| } | ||
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.