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

Implemented support for creating a render surface from a canvas or offscreencanvas #6147

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
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
7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1547,6 +1547,13 @@ path = "tests/window/minimising.rs"
[package.metadata.example.minimising]
hidden = true

[[example]]
name = "virtual"
path = "examples/window/virtual.rs"

[package.metadata.example.virtual]
hidden = true

[[example]]
name = "window_resizing"
path = "examples/window/window_resizing.rs"
Expand Down
29 changes: 20 additions & 9 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,17 +145,27 @@ 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 = windows
.get_primary()
.and_then(|window| window.raw_window_handle())
.map(|wrapper| unsafe {
let handle = wrapper.get_handle();
instance.create_surface(&handle)
let surface = {
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()))
}
AbstractWindowHandle::Virtual => None,
#[cfg(target_arch = "wasm32")]
AbstractWindowHandle::HtmlCanvas(canvas) => {
Some(instance.create_surface_from_canvas(&canvas))
}
#[cfg(target_arch = "wasm32")]
AbstractWindowHandle::OffscreenCanvas(canvas) => {
Some(instance.create_surface_from_offscreen_canvas(&canvas))
}
}
});

raw_handle
};
let request_adapter_options = wgpu::RequestAdapterOptions {
power_preference: options.power_preference,
compatible_surface: surface.as_ref(),
Expand Down
45 changes: 27 additions & 18 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,6 +132,8 @@ pub struct WindowSurfaces {

/// Creates and (re)configures window surfaces, and obtains a swapchain texture for rendering.
///
/// 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
/// taking an unusually long time to complete, and all finishing at about the same time as the
Expand Down Expand Up @@ -161,21 +163,28 @@ pub fn prepare_windows(
render_instance: Res<RenderInstance>,
render_adapter: Res<RenderAdapter>,
) {
for window in windows
.windows
.values_mut()
// value of raw_winndow_handle only None if synthetic test
.filter(|x| x.raw_window_handle.is_some())
{
let window_surfaces = window_surfaces.deref_mut();
let surface = 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(&window.raw_window_handle.as_ref().unwrap().get_handle())
});
let window_surfaces = window_surfaces.deref_mut();
for window in windows.windows.values_mut() {
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())
}),
#[cfg(target_arch = "wasm32")]
AbstractWindowHandle::HtmlCanvas(canvas) => window_surfaces
.surfaces
.entry(window.id)
.or_insert_with(|| render_instance.create_surface_from_canvas(canvas)),
#[cfg(target_arch = "wasm32")]
AbstractWindowHandle::OffscreenCanvas(canvas) => window_surfaces
.surfaces
.entry(window.id)
.or_insert_with(|| render_instance.create_surface_from_offscreen_canvas(canvas)),
AbstractWindowHandle::Virtual => continue,
};

let swap_chain_descriptor = wgpu::SurfaceConfiguration {
format: *surface
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_window/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ serde = { version = "1.0", features = ["derive"], optional = true }

[target.'cfg(target_arch = "wasm32")'.dependencies]
web-sys = "0.3"
wasm-bindgen = "0.2"
Loading