Skip to content

Commit

Permalink
Introduce AbstractWindowHandle enum
Browse files Browse the repository at this point in the history
  • Loading branch information
MDeiml committed Oct 17, 2022
1 parent 7a25a33 commit 460c467
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 79 deletions.
20 changes: 9 additions & 11 deletions crates/bevy_render/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub mod view;

use bevy_core::FrameCount;
use bevy_hierarchy::ValidParentCheckPlugin;
use bevy_window::AbstractWindowHandle;
pub use extract_param::Extract;

pub mod prelude {
Expand Down Expand Up @@ -144,21 +145,18 @@ impl Plugin for RenderPlugin {
.register_type::<Color>();

if let Some(backends) = options.backends {
let windows = app.world.resource_mut::<bevy_window::Windows>();
let instance = wgpu::Instance::new(backends);
let surface = {
if let Some(window) = windows.get_primary() {
if let Some(raw_window_handle) = window.raw_window_handle() {
unsafe {
let handle = raw_window_handle.get_handle();
Some(instance.create_surface(&handle))
let windows = app.world.resource_mut::<bevy_window::Windows>();
let raw_handle = windows.get_primary().and_then(|window| unsafe {
match window.window_handle() {
AbstractWindowHandle::RawWindowHandle(handle) => {
Some(instance.create_surface(&handle.get_handle()))
}
} else {
None
AbstractWindowHandle::Virtual => None,
}
} else {
None
}
});
raw_handle
};
let request_adapter_options = wgpu::RequestAdapterOptions {
power_preference: options.power_preference,
Expand Down
97 changes: 49 additions & 48 deletions crates/bevy_render/src/view/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
use bevy_app::{App, Plugin};
use bevy_ecs::prelude::*;
use bevy_utils::{tracing::debug, HashMap, HashSet};
use bevy_window::{PresentMode, RawWindowHandleWrapper, WindowClosed, WindowId, Windows};
use bevy_window::{AbstractWindowHandle, PresentMode, WindowClosed, WindowId, Windows};
use std::ops::{Deref, DerefMut};

/// Token to ensure a system runs on the main thread.
Expand Down Expand Up @@ -38,7 +38,7 @@ impl Plugin for WindowRenderPlugin {

pub struct ExtractedWindow {
pub id: WindowId,
pub raw_window_handle: Option<RawWindowHandleWrapper>,
pub handle: AbstractWindowHandle,
pub physical_width: u32,
pub physical_height: u32,
pub present_mode: PresentMode,
Expand Down Expand Up @@ -83,7 +83,7 @@ fn extract_windows(
.entry(window.id())
.or_insert(ExtractedWindow {
id: window.id(),
raw_window_handle: window.raw_window_handle(),
handle: window.window_handle(),
physical_width: new_width,
physical_height: new_height,
present_mode: window.present_mode(),
Expand Down Expand Up @@ -132,7 +132,7 @@ pub struct WindowSurfaces {

/// Creates and (re)configures window surfaces, and obtains a swapchain texture for rendering.
///
/// This will not handle [virtual windows](bevy_window::Window::new_virtual).
/// This will not handle [virtual windows](bevy_window::AbstractWindowHandle::Virtual).
///
/// 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-stage systems all
Expand Down Expand Up @@ -165,58 +165,59 @@ pub fn prepare_windows(
) {
let window_surfaces = window_surfaces.deref_mut();
for window in windows.windows.values_mut() {
if let Some(handle) = &window.handle {
let surface = window_surfaces
let surface = match &window.handle {
AbstractWindowHandle::RawWindowHandle(handle) => window_surfaces
.surfaces
.entry(window.id)
.or_insert_with(|| unsafe {
// NOTE: On some OSes this MUST be called from the main thread.
render_instance.create_surface(&handle.get_handle())
});
}),
AbstractWindowHandle::Virtual => continue,
};

let swap_chain_descriptor = wgpu::SurfaceConfiguration {
format: *surface
.get_supported_formats(&render_adapter)
.get(0)
.unwrap_or_else(|| {
panic!(
"No supported formats found for surface {:?} on adapter {:?}",
surface, render_adapter
)
}),
width: window.physical_width,
height: window.physical_height,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
present_mode: match window.present_mode {
PresentMode::Fifo => wgpu::PresentMode::Fifo,
PresentMode::Mailbox => wgpu::PresentMode::Mailbox,
PresentMode::Immediate => wgpu::PresentMode::Immediate,
PresentMode::AutoVsync => wgpu::PresentMode::AutoVsync,
PresentMode::AutoNoVsync => wgpu::PresentMode::AutoNoVsync,
},
};

// Do the initial surface configuration if it hasn't been configured yet. Or if size or
// present mode changed.
if window_surfaces.configured_windows.insert(window.id)
|| window.size_changed
|| window.present_mode_changed
{
render_device.configure_surface(surface, &swap_chain_descriptor);
}

let swap_chain_descriptor = wgpu::SurfaceConfiguration {
format: *surface
.get_supported_formats(&render_adapter)
.get(0)
.unwrap_or_else(|| {
panic!(
"No supported formats found for surface {:?} on adapter {:?}",
surface, render_adapter
)
}),
width: window.physical_width,
height: window.physical_height,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
present_mode: match window.present_mode {
PresentMode::Fifo => wgpu::PresentMode::Fifo,
PresentMode::Mailbox => wgpu::PresentMode::Mailbox,
PresentMode::Immediate => wgpu::PresentMode::Immediate,
PresentMode::AutoVsync => wgpu::PresentMode::AutoVsync,
PresentMode::AutoNoVsync => wgpu::PresentMode::AutoNoVsync,
},
};

// Do the initial surface configuration if it hasn't been configured yet. Or if size or
// present mode changed.
if window_surfaces.configured_windows.insert(window.id)
|| window.size_changed
|| window.present_mode_changed
{
let frame = match surface.get_current_texture() {
Ok(swap_chain_frame) => swap_chain_frame,
Err(wgpu::SurfaceError::Outdated) => {
render_device.configure_surface(surface, &swap_chain_descriptor);
surface
.get_current_texture()
.expect("Error reconfiguring surface")
}
err => err.expect("Failed to acquire next swap chain texture!"),
};

let frame = match surface.get_current_texture() {
Ok(swap_chain_frame) => swap_chain_frame,
Err(wgpu::SurfaceError::Outdated) => {
render_device.configure_surface(surface, &swap_chain_descriptor);
surface
.get_current_texture()
.expect("Error reconfiguring surface")
}
err => err.expect("Failed to acquire next swap chain texture!"),
};

window.swap_chain_texture = Some(TextureView::from(frame));
}
window.swap_chain_texture = Some(TextureView::from(frame));
}
}
44 changes: 25 additions & 19 deletions crates/bevy_window/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,21 @@ impl WindowResizeConstraints {
}
}

/// Handle used for creating surfaces in the render plugin
///
/// Either a raw handle to an OS window or `Virtual` to signify that there is no corresponding OS window.
#[derive(Clone, Debug)]
pub enum AbstractWindowHandle {
/// The window corresponds to an operator system window.
RawWindowHandle(RawWindowHandleWrapper),
/// The window does not to correspond to an operator system window.
///
/// It differs from a non-virtual window, in that the caller is responsible
/// for creating and presenting surface textures and inserting them into
/// [`ExtractedWindow`](https://docs.rs/bevy/*/bevy/render/view/struct.ExtractedWindow.html).
Virtual,
}

/// An operating system or virtual window that can present content and receive user input.
///
/// To create a window, use a [`EventWriter<CreateWindow>`](`crate::CreateWindow`).
Expand Down Expand Up @@ -259,7 +274,7 @@ pub struct Window {
cursor_visible: bool,
cursor_locked: bool,
physical_cursor_position: Option<DVec2>,
raw_window_handle: Option<RawWindowHandleWrapper>,
window_handle: AbstractWindowHandle,
focused: bool,
mode: WindowMode,
canvas: Option<String>,
Expand Down Expand Up @@ -368,7 +383,7 @@ impl Window {
physical_height: u32,
scale_factor: f64,
position: Option<IVec2>,
raw_window_handle: Option<RawWindowHandle>,
raw_window_handle: RawWindowHandle,
) -> Self {
Window {
id,
Expand All @@ -388,7 +403,9 @@ impl Window {
cursor_locked: window_descriptor.cursor_locked,
cursor_icon: CursorIcon::Default,
physical_cursor_position: None,
raw_window_handle: Some(RawWindowHandleWrapper::new(raw_window_handle)),
window_handle: AbstractWindowHandle::RawWindowHandle(RawWindowHandleWrapper::new(
raw_window_handle,
)),
focused: true,
mode: window_descriptor.mode,
canvas: window_descriptor.canvas.clone(),
Expand All @@ -399,11 +416,7 @@ impl Window {

/// Creates a new virtual [`Window`].
///
/// This window does not have to correspond to an operator system window.
///
/// It differs from a non-virtual window, in that the caller is responsible
/// for creating and presenting surface textures and inserting them into
/// [`ExtractedWindow`](https://docs.rs/bevy/*/bevy/render/view/struct.ExtractedWindow.html).
/// See [`AbstractWindowHandle::Virtual`].
pub fn new_virtual(
id: WindowId,
window_descriptor: &WindowDescriptor,
Expand All @@ -430,7 +443,7 @@ impl Window {
cursor_locked: window_descriptor.cursor_locked,
cursor_icon: CursorIcon::Default,
physical_cursor_position: None,
raw_window_handle: None,
window_handle: AbstractWindowHandle::Virtual,
focused: true,
mode: window_descriptor.mode,
canvas: window_descriptor.canvas.clone(),
Expand Down Expand Up @@ -816,16 +829,9 @@ impl Window {
self.focused
}

/// Get the [`RawWindowHandleWrapper`] corresponding to this window.
///
/// A return value of `None` signifies that this is a virtual window and does not
/// correspond to an OS window. The creator of the window is responsible
/// for creating and presenting surface textures and inserting them into
/// [`ExtractedWindow`](https://docs.rs/bevy/*/bevy/render/view/struct.ExtractedWindow.html).
///
/// See [`Self::new_virtual`].
pub fn raw_window_handle(&self) -> Option<RawWindowHandleWrapper> {
self.raw_window_handle.clone()
/// Get the [`AbstractWindowHandle`] corresponding to this window.
pub fn window_handle(&self) -> AbstractWindowHandle {
self.window_handle.clone()
}

/// The "html canvas" element selector.
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_winit/src/winit_windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ impl WinitWindows {
inner_size.height,
scale_factor,
position,
Some(raw_window_handle),
raw_window_handle,
)
}

Expand Down

0 comments on commit 460c467

Please sign in to comment.