mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 15:14:50 +00:00
Replace VSync with PresentMode (#3812)
# Objective Enable the user to specify any presentation modes (including `Mailbox`). Fixes #3807 ## Solution I've added a new `PresentMode` enum in `bevy_window` that mirrors the `wgpu` enum 1:1. Alternatively, I could add a new dependency on `wgpu-types` if that would be preferred.
This commit is contained in:
parent
fe0e5580db
commit
1477765f62
8 changed files with 64 additions and 26 deletions
|
@ -7,7 +7,7 @@ use crate::{
|
|||
use bevy_app::{App, Plugin};
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_utils::{tracing::debug, HashMap, HashSet};
|
||||
use bevy_window::{RawWindowHandleWrapper, WindowId, Windows};
|
||||
use bevy_window::{PresentMode, RawWindowHandleWrapper, WindowId, Windows};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use wgpu::TextureFormat;
|
||||
|
||||
|
@ -43,7 +43,7 @@ pub struct ExtractedWindow {
|
|||
pub handle: RawWindowHandleWrapper,
|
||||
pub physical_width: u32,
|
||||
pub physical_height: u32,
|
||||
pub vsync: bool,
|
||||
pub present_mode: PresentMode,
|
||||
pub swap_chain_texture: Option<TextureView>,
|
||||
pub size_changed: bool,
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ fn extract_windows(mut render_world: ResMut<RenderWorld>, windows: Res<Windows>)
|
|||
handle: window.raw_window_handle(),
|
||||
physical_width: new_width,
|
||||
physical_height: new_height,
|
||||
vsync: window.vsync(),
|
||||
present_mode: window.present_mode(),
|
||||
swap_chain_texture: None,
|
||||
size_changed: false,
|
||||
});
|
||||
|
@ -138,10 +138,10 @@ pub fn prepare_windows(
|
|||
width: window.physical_width,
|
||||
height: window.physical_height,
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||
present_mode: if window.vsync {
|
||||
wgpu::PresentMode::Fifo
|
||||
} else {
|
||||
wgpu::PresentMode::Immediate
|
||||
present_mode: match window.present_mode {
|
||||
PresentMode::Fifo => wgpu::PresentMode::Fifo,
|
||||
PresentMode::Mailbox => wgpu::PresentMode::Mailbox,
|
||||
PresentMode::Immediate => wgpu::PresentMode::Immediate,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -5,6 +5,39 @@ use raw_window_handle::RawWindowHandle;
|
|||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct WindowId(Uuid);
|
||||
|
||||
/// Presentation mode for a window.
|
||||
///
|
||||
/// The presentation mode specifies when a frame is presented to the window. The `Fifo`
|
||||
/// option corresponds to a traditional `VSync`, where the framerate is capped by the
|
||||
/// display refresh rate. Both `Immediate` and `Mailbox` are low-latency and are not
|
||||
/// capped by the refresh rate, but may not be available on all platforms. Tearing
|
||||
/// may be observed with `Immediate` mode, but will not be observed with `Mailbox` or
|
||||
/// `Fifo`.
|
||||
///
|
||||
/// `Immediate` or `Mailbox` will gracefully fallback to `Fifo` when unavailable.
|
||||
///
|
||||
/// The presentation mode may be declared in the [`WindowDescriptor`](WindowDescriptor::present_mode)
|
||||
/// or updated on a [`Window`](Window::set_present_mode).
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[doc(alias = "vsync")]
|
||||
pub enum PresentMode {
|
||||
/// The presentation engine does **not** wait for a vertical blanking period and
|
||||
/// the request is presented immediately. This is a low-latency presentation mode,
|
||||
/// but visible tearing may be observed. Will fallback to `Fifo` if unavailable on the
|
||||
/// selected platform and backend. Not optimal for mobile.
|
||||
Immediate = 0,
|
||||
/// The presentation engine waits for the next vertical blanking period to update
|
||||
/// the current image, but frames may be submitted without delay. This is a low-latency
|
||||
/// presentation mode and visible tearing will **not** be observed. Will fallback to `Fifo`
|
||||
/// if unavailable on the selected platform and backend. Not optimal for mobile.
|
||||
Mailbox = 1,
|
||||
/// The presentation engine waits for the next vertical blanking period to update
|
||||
/// the current image. The framerate will be capped at the display refresh rate,
|
||||
/// corresponding to the `VSync`. Tearing cannot be observed. Optimal for mobile.
|
||||
Fifo = 2, // NOTE: The explicit ordinal values mirror wgpu and the vulkan spec.
|
||||
}
|
||||
|
||||
impl WindowId {
|
||||
pub fn new() -> Self {
|
||||
WindowId(Uuid::new_v4())
|
||||
|
@ -121,7 +154,7 @@ pub struct Window {
|
|||
scale_factor_override: Option<f64>,
|
||||
backend_scale_factor: f64,
|
||||
title: String,
|
||||
vsync: bool,
|
||||
present_mode: PresentMode,
|
||||
resizable: bool,
|
||||
decorations: bool,
|
||||
cursor_icon: CursorIcon,
|
||||
|
@ -152,8 +185,8 @@ pub enum WindowCommand {
|
|||
logical_resolution: (f32, f32),
|
||||
scale_factor: f64,
|
||||
},
|
||||
SetVsync {
|
||||
vsync: bool,
|
||||
SetPresentMode {
|
||||
present_mode: PresentMode,
|
||||
},
|
||||
SetResizable {
|
||||
resizable: bool,
|
||||
|
@ -222,7 +255,7 @@ impl Window {
|
|||
scale_factor_override: window_descriptor.scale_factor_override,
|
||||
backend_scale_factor: scale_factor,
|
||||
title: window_descriptor.title.clone(),
|
||||
vsync: window_descriptor.vsync,
|
||||
present_mode: window_descriptor.present_mode,
|
||||
resizable: window_descriptor.resizable,
|
||||
decorations: window_descriptor.decorations,
|
||||
cursor_visible: window_descriptor.cursor_visible,
|
||||
|
@ -425,14 +458,17 @@ impl Window {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn vsync(&self) -> bool {
|
||||
self.vsync
|
||||
#[doc(alias = "vsync")]
|
||||
pub fn present_mode(&self) -> PresentMode {
|
||||
self.present_mode
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_vsync(&mut self, vsync: bool) {
|
||||
self.vsync = vsync;
|
||||
self.command_queue.push(WindowCommand::SetVsync { vsync });
|
||||
#[doc(alias = "set_vsync")]
|
||||
pub fn set_present_mode(&mut self, present_mode: PresentMode) {
|
||||
self.present_mode = present_mode;
|
||||
self.command_queue
|
||||
.push(WindowCommand::SetPresentMode { present_mode });
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -557,7 +593,8 @@ pub struct WindowDescriptor {
|
|||
pub resize_constraints: WindowResizeConstraints,
|
||||
pub scale_factor_override: Option<f64>,
|
||||
pub title: String,
|
||||
pub vsync: bool,
|
||||
#[doc(alias = "vsync")]
|
||||
pub present_mode: PresentMode,
|
||||
pub resizable: bool,
|
||||
pub decorations: bool,
|
||||
pub cursor_visible: bool,
|
||||
|
@ -584,7 +621,7 @@ impl Default for WindowDescriptor {
|
|||
position: None,
|
||||
resize_constraints: WindowResizeConstraints::default(),
|
||||
scale_factor_override: None,
|
||||
vsync: true,
|
||||
present_mode: PresentMode::Fifo,
|
||||
resizable: true,
|
||||
decorations: true,
|
||||
cursor_locked: false,
|
||||
|
|
|
@ -94,7 +94,7 @@ fn change_window(world: &mut World) {
|
|||
.to_physical::<f64>(scale_factor),
|
||||
);
|
||||
}
|
||||
bevy_window::WindowCommand::SetVsync { .. } => (),
|
||||
bevy_window::WindowCommand::SetPresentMode { .. } => (),
|
||||
bevy_window::WindowCommand::SetResizable { resizable } => {
|
||||
let window = winit_windows.get_window(id).unwrap();
|
||||
window.set_resizable(resizable);
|
||||
|
|
|
@ -5,7 +5,6 @@ use bevy::{input::touch::TouchPhase, prelude::*, window::WindowMode};
|
|||
fn main() {
|
||||
App::new()
|
||||
.insert_resource(WindowDescriptor {
|
||||
vsync: true,
|
||||
resizable: false,
|
||||
mode: WindowMode::BorderlessFullscreen,
|
||||
..Default::default()
|
||||
|
|
|
@ -2,6 +2,7 @@ use bevy::{
|
|||
core::FixedTimestep,
|
||||
diagnostic::{Diagnostics, FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
|
||||
prelude::*,
|
||||
window::PresentMode,
|
||||
};
|
||||
use rand::random;
|
||||
|
||||
|
@ -28,7 +29,7 @@ fn main() {
|
|||
title: "BevyMark".to_string(),
|
||||
width: 800.,
|
||||
height: 600.,
|
||||
vsync: false,
|
||||
present_mode: PresentMode::Mailbox,
|
||||
resizable: true,
|
||||
..Default::default()
|
||||
})
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
use bevy::{
|
||||
diagnostic::{Diagnostics, FrameTimeDiagnosticsPlugin},
|
||||
prelude::*,
|
||||
window::PresentMode,
|
||||
};
|
||||
|
||||
/// This example is for debugging text layout
|
||||
fn main() {
|
||||
App::new()
|
||||
.insert_resource(WindowDescriptor {
|
||||
vsync: false,
|
||||
present_mode: PresentMode::Immediate,
|
||||
..Default::default()
|
||||
})
|
||||
.add_plugins(DefaultPlugins)
|
||||
|
|
|
@ -8,7 +8,7 @@ use bevy::{
|
|||
renderer::RenderContext,
|
||||
RenderApp, RenderStage,
|
||||
},
|
||||
window::{CreateWindow, WindowId},
|
||||
window::{CreateWindow, PresentMode, WindowId},
|
||||
};
|
||||
|
||||
/// This example creates a second window and draws a mesh from two different cameras, one in each window
|
||||
|
@ -57,7 +57,7 @@ fn create_new_window(
|
|||
descriptor: WindowDescriptor {
|
||||
width: 800.,
|
||||
height: 600.,
|
||||
vsync: false,
|
||||
present_mode: PresentMode::Immediate,
|
||||
title: "Second window".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use bevy::prelude::*;
|
||||
use bevy::{prelude::*, window::PresentMode};
|
||||
|
||||
/// This example illustrates how to customize the default window settings
|
||||
fn main() {
|
||||
|
@ -7,7 +7,7 @@ fn main() {
|
|||
title: "I am a window!".to_string(),
|
||||
width: 500.,
|
||||
height: 300.,
|
||||
vsync: true,
|
||||
present_mode: PresentMode::Fifo,
|
||||
..Default::default()
|
||||
})
|
||||
.add_plugins(DefaultPlugins)
|
||||
|
|
Loading…
Reference in a new issue