diff --git a/Cargo.toml b/Cargo.toml index e33ac34bcf09c..dc9ef3e6ae000 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,8 @@ +[patch.crates-io] +wgpu = { git = "https://github.com/MarijnS95/wgpu/", rev = "23201c402" } +wgpu-types = { git = "https://github.com/MarijnS95/wgpu/", rev = "23201c402" } +naga = { git = "https://github.com/MarijnS95/wgpu/", rev = "23201c402" } + [package] name = "bevy" version = "0.17.0-dev" diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index 79a769effe737..ccd0510a6aaf8 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -58,6 +58,13 @@ mod extract_impls; /// /// This includes the most common types in this crate, re-exported for your convenience. pub mod prelude { + // TODO: Remove this in a follow-up + #[doc(hidden)] + pub use bevy_camera::{ + Camera, ClearColor, ClearColorConfig, OrthographicProjection, PerspectiveProjection, + Projection, + }; + #[doc(hidden)] pub use crate::{ alpha::AlphaMode, @@ -71,12 +78,6 @@ pub mod prelude { view::{InheritedVisibility, Msaa, ViewVisibility, Visibility}, ExtractSchedule, }; - // TODO: Remove this in a follow-up - #[doc(hidden)] - pub use bevy_camera::{ - Camera, ClearColor, ClearColorConfig, OrthographicProjection, PerspectiveProjection, - Projection, - }; } #[doc(hidden)] @@ -84,21 +85,10 @@ pub mod _macro { pub use bevy_asset; } -pub use extract_param::Extract; - -use crate::{ - camera::CameraPlugin, - gpu_readback::GpuReadbackPlugin, - mesh::{MeshPlugin, MorphPlugin, RenderMesh}, - render_asset::prepare_assets, - render_resource::{init_empty_bind_group_layout, PipelineCache, Shader, ShaderLoader}, - renderer::{render_system, RenderInstance}, - settings::RenderCreation, - storage::StoragePlugin, - view::{ViewPlugin, WindowRenderPlugin}, -}; use alloc::sync::Arc; -use batching::gpu_preprocessing::BatchingPlugin; +use core::ops::{Deref, DerefMut}; +use std::sync::Mutex; + use bevy_app::{App, AppLabel, Plugin, SubApp}; use bevy_asset::{AssetApp, AssetServer}; use bevy_ecs::{ @@ -107,21 +97,33 @@ use bevy_ecs::{ }; use bevy_image::{CompressedImageFormatSupport, CompressedImageFormats}; use bevy_utils::prelude::default; -use bevy_window::{PrimaryWindow, RawHandleWrapperHolder}; -use bitflags::bitflags; -use core::ops::{Deref, DerefMut}; -use experimental::occlusion_culling::OcclusionCullingPlugin; -use globals::GlobalsPlugin; -use render_asset::{ - extract_render_asset_bytes_per_frame, reset_render_asset_bytes_per_frame, - RenderAssetBytesPerFrame, RenderAssetBytesPerFrameLimiter, +use bevy_window::{ + PrimaryWindow, RawDisplayHandleWrapper, RawWindowHandleWrapperHolder, + ThreadLockedRawWindowHandleWrapper, }; -use renderer::{RenderAdapter, RenderDevice, RenderQueue}; -use settings::RenderResources; -use std::sync::Mutex; -use sync_world::{despawn_temporary_render_entities, entity_sync_system, SyncWorldPlugin}; +use bitflags::bitflags; use tracing::debug; -pub use wgpu_wrapper::WgpuWrapper; +use wgpu::rwh::{DisplayHandle, HandleError, HasDisplayHandle, HasWindowHandle, WindowHandle}; + +use crate::{ + batching::gpu_preprocessing::BatchingPlugin, + camera::CameraPlugin, + experimental::occlusion_culling::OcclusionCullingPlugin, + globals::GlobalsPlugin, + gpu_readback::GpuReadbackPlugin, + mesh::{MeshPlugin, MorphPlugin, RenderMesh}, + render_asset::{ + extract_render_asset_bytes_per_frame, prepare_assets, reset_render_asset_bytes_per_frame, + RenderAssetBytesPerFrame, RenderAssetBytesPerFrameLimiter, + }, + render_resource::{init_empty_bind_group_layout, PipelineCache, Shader, ShaderLoader}, + renderer::{render_system, RenderAdapter, RenderDevice, RenderInstance, RenderQueue}, + settings::{RenderCreation, RenderResources}, + storage::StoragePlugin, + sync_world::{despawn_temporary_render_entities, entity_sync_system, SyncWorldPlugin}, + view::{ViewPlugin, WindowRenderPlugin}, +}; +pub use crate::{extract_param::Extract, wgpu_wrapper::WgpuWrapper}; /// Inline shader as an `embedded_asset` and load it permanently. /// @@ -347,9 +349,10 @@ impl Plugin for RenderPlugin { future_render_resources_wrapper.clone(), )); + let display = app.world().resource::().clone(); let primary_window = app .world_mut() - .query_filtered::<&RawHandleWrapperHolder, With>() + .query_filtered::<&RawWindowHandleWrapperHolder, With>() .single(app.world()) .ok() .cloned(); @@ -369,18 +372,45 @@ impl Plugin for RenderPlugin { }, noop: wgpu::NoopBackendOptions { enable: false }, }, + display: Some(display.display_handle().unwrap().as_raw()), }); let surface = primary_window.and_then(|wrapper| { let maybe_handle = wrapper.0.lock().expect( - "Couldn't get the window handle in time for renderer initialization", + "too long string breaks rustfmt", // "Couldn't get the window handle in time for renderer initialization", ); if let Some(wrapper) = maybe_handle.as_ref() { // SAFETY: Plugins should be set up on the main thread. let handle = unsafe { wrapper.get_handle() }; + + /// WGPU shouldn't force a single type to implement both traits. + struct BadWgpuApiWrapper { + display: RawDisplayHandleWrapper, + window: ThreadLockedRawWindowHandleWrapper, + } + impl HasDisplayHandle for BadWgpuApiWrapper { + fn display_handle( + &self, + ) -> Result, HandleError> + { + self.display.display_handle() + } + } + impl HasWindowHandle for BadWgpuApiWrapper { + fn window_handle( + &self, + ) -> Result, HandleError> + { + self.window.window_handle() + } + } + Some( instance - .create_surface(handle) + .create_surface(BadWgpuApiWrapper { + display, + window: handle, + }) .expect("Failed to create wgpu surface"), ) } else { diff --git a/crates/bevy_render/src/view/window/mod.rs b/crates/bevy_render/src/view/window/mod.rs index e682829bf4a07..fba9d4e158c36 100644 --- a/crates/bevy_render/src/view/window/mod.rs +++ b/crates/bevy_render/src/view/window/mod.rs @@ -9,7 +9,8 @@ use bevy_ecs::{entity::EntityHashMap, prelude::*}; use bevy_platform::collections::HashSet; use bevy_utils::default; use bevy_window::{ - CompositeAlphaMode, PresentMode, PrimaryWindow, RawHandleWrapper, Window, WindowClosing, + CompositeAlphaMode, PresentMode, PrimaryWindow, RawDisplayHandleWrapper, + RawWindowHandleWrapper, Window, WindowClosing, }; use core::{ num::NonZero, @@ -30,10 +31,14 @@ impl Plugin for WindowRenderPlugin { fn build(&self, app: &mut App) { app.add_plugins(ScreenshotPlugin); + let display = app.world().resource::().clone(); + if let Some(render_app) = app.get_sub_app_mut(RenderApp) { render_app .init_resource::() .init_resource::() + // Forward it to the sub-app? + .insert_resource(display) .add_systems(ExtractSchedule, extract_windows) .add_systems( Render, @@ -49,7 +54,7 @@ impl Plugin for WindowRenderPlugin { pub struct ExtractedWindow { /// An entity that contains the components in [`Window`]. pub entity: Entity, - pub handle: RawHandleWrapper, + pub handle: RawWindowHandleWrapper, pub physical_width: u32, pub physical_height: u32, pub present_mode: PresentMode, @@ -101,8 +106,15 @@ impl DerefMut for ExtractedWindows { fn extract_windows( mut extracted_windows: ResMut, mut closing: Extract>, - windows: Extract)>>, - mut removed: Extract>, + windows: Extract< + Query<( + Entity, + &Window, + &RawWindowHandleWrapper, + Option<&PrimaryWindow>, + )>, + >, + mut removed: Extract>, mut window_surfaces: ResMut, ) { for (entity, window, handle, primary) in windows.iter() { @@ -300,6 +312,7 @@ pub fn create_surfaces( // By accessing a NonSend resource, we tell the scheduler to put this system on the main thread, // which is necessary for some OS's #[cfg(any(target_os = "macos", target_os = "ios"))] _marker: bevy_ecs::system::NonSendMarker, + display: Res, windows: Res, mut window_surfaces: ResMut, render_instance: Res, @@ -312,7 +325,7 @@ pub fn create_surfaces( .entry(window.entity) .or_insert_with(|| { let surface_target = SurfaceTargetUnsafe::RawHandle { - raw_display_handle: window.handle.get_display_handle(), + raw_display_handle: display.get_display_handle(), raw_window_handle: window.handle.get_window_handle(), }; // SAFETY: The window handles in ExtractedWindows will always be valid objects to create surfaces on diff --git a/crates/bevy_window/src/lib.rs b/crates/bevy_window/src/lib.rs index 59bebf29b70d5..854990d180796 100644 --- a/crates/bevy_window/src/lib.rs +++ b/crates/bevy_window/src/lib.rs @@ -128,7 +128,7 @@ impl Plugin for WindowPlugin { let mut entity_commands = app.world_mut().spawn(primary_window.clone()); entity_commands.insert(( PrimaryWindow, - RawHandleWrapperHolder(Arc::new(Mutex::new(None))), + RawWindowHandleWrapperHolder(Arc::new(Mutex::new(None))), )); if let Some(primary_cursor_options) = &self.primary_cursor_options { entity_commands.insert(primary_cursor_options.clone()); diff --git a/crates/bevy_window/src/raw_handle.rs b/crates/bevy_window/src/raw_handle.rs index 0943315055fb6..b45b251ac310f 100644 --- a/crates/bevy_window/src/raw_handle.rs +++ b/crates/bevy_window/src/raw_handle.rs @@ -4,7 +4,7 @@ )] use alloc::sync::Arc; -use bevy_ecs::prelude::Component; +use bevy_ecs::{prelude::Component, resource::Resource}; use bevy_platform::sync::Mutex; use core::{any::Any, marker::PhantomData, ops::Deref}; use raw_window_handle::{ @@ -17,7 +17,7 @@ use raw_window_handle::{ /// This allows us to extend the lifetime of the window, so it doesn't get eagerly dropped while a /// pipelined renderer still has frames in flight that need to draw to it. /// -/// This is achieved by storing a shared reference to the window in the [`RawHandleWrapper`], +/// This is achieved by storing a shared reference to the window in the [`RawWindowHandleWrapper`], /// which gets picked up by the renderer during extraction. #[derive(Debug)] pub struct WindowWrapper { @@ -49,7 +49,7 @@ impl Deref for WindowWrapper { /// and so we cannot simply make it (or any type that has a safe operation to get a [`RawWindowHandle`] or [`RawDisplayHandle`]) /// thread-safe. #[derive(Debug, Clone, Component)] -pub struct RawHandleWrapper { +pub struct RawWindowHandleWrapper { /// A shared reference to the window. /// This allows us to extend the lifetime of the window, /// so it doesn’t get eagerly dropped while a pipelined @@ -57,19 +57,17 @@ pub struct RawHandleWrapper { _window: Arc, /// Raw handle to a window. window_handle: RawWindowHandle, - /// Raw handle to the display server. - display_handle: RawDisplayHandle, } -impl RawHandleWrapper { - /// Creates a `RawHandleWrapper` from a `WindowWrapper`. - pub fn new( +impl RawWindowHandleWrapper { + /// Creates a [`RawWindowHandleWrapper`] from a [`WindowWrapper`]. + pub fn new( window: &WindowWrapper, - ) -> Result { - Ok(RawHandleWrapper { + ) -> Result { + Ok(Self { _window: window.reference.clone(), window_handle: window.window_handle()?.as_raw(), - display_handle: window.display_handle()?.as_raw(), + // display_handle: window.display_handle()?.as_raw(), }) } @@ -78,7 +76,7 @@ impl RawHandleWrapper { /// # Safety /// /// Some platforms have constraints on where/how this handle can be used. For example, some platforms don't support doing window - /// operations off of the main thread. The caller must ensure the [`RawHandleWrapper`] is only used in valid contexts. + /// operations off of the main thread. The caller must ensure the [`RawWindowHandleWrapper`] is only used in valid contexts. pub unsafe fn get_handle(&self) -> ThreadLockedRawWindowHandleWrapper { ThreadLockedRawWindowHandleWrapper(self.clone()) } @@ -101,66 +99,110 @@ impl RawHandleWrapper { self } - - /// Gets the stored display handle - pub fn get_display_handle(&self) -> RawDisplayHandle { - self.display_handle - } - - /// Sets the display handle. - /// - /// # Safety - /// - /// The passed in [`RawDisplayHandle`] must be a valid display handle. - pub fn set_display_handle(&mut self, display_handle: RawDisplayHandle) -> &mut Self { - self.display_handle = display_handle; - - self - } } -// SAFETY: [`RawHandleWrapper`] is just a normal "raw pointer", which doesn't impl Send/Sync. However the pointer is only +// SAFETY: `RawWindowHandleWrapper` is just a normal "raw pointer", which doesn't impl Send/Sync. However the pointer is only // exposed via an unsafe method that forces the user to make a call for a given platform. (ex: some platforms don't // support doing window operations off of the main thread). // A recommendation for this pattern (and more context) is available here: // https://github.com/rust-windowing/raw-window-handle/issues/59 -unsafe impl Send for RawHandleWrapper {} +unsafe impl Send for RawWindowHandleWrapper {} // SAFETY: This is safe for the same reasons as the Send impl above. -unsafe impl Sync for RawHandleWrapper {} +unsafe impl Sync for RawWindowHandleWrapper {} -/// A [`RawHandleWrapper`] that cannot be sent across threads. +/// A [`RawWindowHandleWrapper`] that cannot be sent across threads. /// -/// This safely exposes [`RawWindowHandle`] and [`RawDisplayHandle`], but care must be taken to ensure that the construction itself is correct. +/// This safely exposes [`RawWindowHandle`], but care must be taken to ensure that the construction itself is correct. /// -/// This can only be constructed via the [`RawHandleWrapper::get_handle()`] method; +/// This can only be constructed via the [`RawWindowHandleWrapper::get_handle()`] method; /// be sure to read the safety docs there about platform-specific limitations. /// In many cases, this should only be constructed on the main thread. -pub struct ThreadLockedRawWindowHandleWrapper(RawHandleWrapper); +pub struct ThreadLockedRawWindowHandleWrapper(RawWindowHandleWrapper); impl HasWindowHandle for ThreadLockedRawWindowHandleWrapper { fn window_handle(&self) -> Result { - // SAFETY: the caller has validated that this is a valid context to get [`RawHandleWrapper`] + // SAFETY: the caller has validated that this is a valid context to get `RawWindowHandleWrapper` // as otherwise an instance of this type could not have been constructed - // NOTE: we cannot simply impl HasRawWindowHandle for RawHandleWrapper, + // NOTE: we cannot simply impl HasRawWindowHandle for RawWindowHandleWrapper, // as the `raw_window_handle` method is safe. We cannot guarantee that all calls // of this method are correct (as it may be off the main thread on an incompatible platform), // and so exposing a safe method to get a [`RawWindowHandle`] directly would be UB. + // XXX: ^ that note is flawed. "getting" the handle is safe - it's about how it's used. Any + // API **consuming** a RawWindowHandle should be adequately marked unsafe instead. Ok(unsafe { WindowHandle::borrow_raw(self.0.window_handle) }) } } -impl HasDisplayHandle for ThreadLockedRawWindowHandleWrapper { +// XXX: Could still be implemented because `_window` provides it +// impl HasDisplayHandle for ThreadLockedRawDisplayHandleWrapper { +// fn display_handle(&self) -> Result { +// } +// } + +/// Holder of the [`RawHWindowandleWrapper`] with wrappers, to allow use in asynchronous context +#[derive(Debug, Clone, Component)] +pub struct RawWindowHandleWrapperHolder(pub Arc>>); + +/// A wrapper over [`RawDisplayHandle`] that allows us to safely pass it across threads. +/// +/// Depending on the platform, the underlying pointer-containing handle cannot be used on all threads, +/// and so we cannot simply make it (or any type that has a safe operation to get a [`RawWindowHandle`] or [`RawDisplayHandle`]) +/// thread-safe. +#[derive(Debug, Clone, Resource)] +pub struct RawDisplayHandleWrapper { + // XXX: Do we need to hold on to the EventLoop who owns/runs the app? + /// Raw handle to the display server. + display_handle: RawDisplayHandle, +} + +impl RawDisplayHandleWrapper { + /// Creates a `RawDisplayHandleWrapper` from an event loop or similar. + // XXX: Do we need to store `display` for lifetime purposes? It should outlive App. + pub fn new(display: &W) -> Result { + Ok(Self { + display_handle: display.display_handle()?.as_raw(), + }) + } + + /// Gets the stored display handle + pub fn get_display_handle(&self) -> RawDisplayHandle { + self.display_handle + } + + /// Sets the display handle. + /// + /// # Safety + /// + /// The passed in [`RawDisplayHandle`] must be a valid display handle. + pub fn set_display_handle(&mut self, display_handle: RawDisplayHandle) -> &mut Self { + self.display_handle = display_handle; + + self + } +} + +// SAFETY: `RawDisplayHandleWrapper` is just a normal "raw pointer", which doesn't impl Send/Sync. However the pointer is only +// exposed via an unsafe method that forces the user to make a call for a given platform. (ex: some platforms don't +// support doing window operations off of the main thread). +// A recommendation for this pattern (and more context) is available here: +// https://github.com/rust-windowing/raw-window-handle/issues/59 +unsafe impl Send for RawDisplayHandleWrapper {} +// SAFETY: This is safe for the same reasons as the Send impl above. +unsafe impl Sync for RawDisplayHandleWrapper {} + +// /// A [`RawDisplayHandleWrapper`] that cannot be sent across threads. +// /// +// /// This safely exposes [`RawDisplayHandle`], but care must be taken to ensure that the construction itself is correct. +// /// +// /// This can only be constructed via the [`RawDisplayHandleWrapper::get_handle()`] method; +// /// be sure to read the safety docs there about platform-specific limitations. +// /// In many cases, this should only be constructed on the main thread. +// pub struct ThreadLockedRawDisplayHandleWrapper(RawDisplayHandleWrapper); + +impl HasDisplayHandle for RawDisplayHandleWrapper { fn display_handle(&self) -> Result { - // SAFETY: the caller has validated that this is a valid context to get [`RawDisplayHandle`] + // SAFETY: the caller has validated that this is a valid context to get `RawDisplayHandle` // as otherwise an instance of this type could not have been constructed - // NOTE: we cannot simply impl HasRawDisplayHandle for RawHandleWrapper, - // as the `raw_display_handle` method is safe. We cannot guarantee that all calls - // of this method are correct (as it may be off the main thread on an incompatible platform), - // and so exposing a safe method to get a [`RawDisplayHandle`] directly would be UB. - Ok(unsafe { DisplayHandle::borrow_raw(self.0.display_handle) }) + Ok(unsafe { DisplayHandle::borrow_raw(self.display_handle) }) } } - -/// Holder of the [`RawHandleWrapper`] with wrappers, to allow use in asynchronous context -#[derive(Debug, Clone, Component)] -pub struct RawHandleWrapperHolder(pub Arc>>); diff --git a/crates/bevy_winit/src/lib.rs b/crates/bevy_winit/src/lib.rs index dc3eaf36b88c5..4c4a947bf1ff0 100644 --- a/crates/bevy_winit/src/lib.rs +++ b/crates/bevy_winit/src/lib.rs @@ -17,7 +17,7 @@ extern crate alloc; use bevy_derive::Deref; use bevy_reflect::prelude::ReflectDefault; use bevy_reflect::Reflect; -use bevy_window::{RawHandleWrapperHolder, WindowEvent}; +use bevy_window::{RawDisplayHandleWrapper, RawWindowHandleWrapperHolder, WindowEvent}; use core::cell::RefCell; use core::marker::PhantomData; use winit::{event_loop::EventLoop, window::WindowId}; @@ -130,9 +130,11 @@ impl Plugin for WinitPlugin { .build() .expect("Failed to build event loop"); + tracing::info!("Init app"); + app.init_resource::() .init_resource::() - .insert_resource(DisplayHandleWrapper(event_loop.owned_display_handle())) + .insert_resource(RawDisplayHandleWrapper::new(&event_loop).unwrap()) .add_event::() .set_runner(|app| winit_runner(app, event_loop)) .add_systems( @@ -183,15 +185,6 @@ pub struct RawWinitWindowEvent { #[derive(Resource, Deref)] pub struct EventLoopProxyWrapper(EventLoopProxy); -/// A wrapper around [`winit::event_loop::OwnedDisplayHandle`] -/// -/// The `DisplayHandleWrapper` can be used to build integrations that rely on direct -/// access to the display handle -/// -/// Use `Res` to receive this resource. -#[derive(Resource, Deref)] -pub struct DisplayHandleWrapper(pub winit::event_loop::OwnedDisplayHandle); - trait AppSendEvent { fn send(&mut self, event: impl Into); } @@ -212,7 +205,7 @@ pub type CreateWindowParams<'w, 's, F = ()> = ( Entity, &'static mut Window, &'static CursorOptions, - Option<&'static RawHandleWrapperHolder>, + Option<&'static RawWindowHandleWrapperHolder>, ), F, >, diff --git a/crates/bevy_winit/src/state.rs b/crates/bevy_winit/src/state.rs index 4f90905463351..f3699023c6837 100644 --- a/crates/bevy_winit/src/state.rs +++ b/crates/bevy_winit/src/state.rs @@ -36,7 +36,7 @@ use bevy_window::{ WindowScaleFactorChanged, WindowThemeChanged, }; #[cfg(target_os = "android")] -use bevy_window::{CursorOptions, PrimaryWindow, RawHandleWrapper}; +use bevy_window::{CursorOptions, PrimaryWindow, RawWindowHandleWrapper}; use crate::{ accessibility::ACCESS_KIT_ADAPTERS, @@ -529,9 +529,10 @@ impl WinitAppRunnerState { should_update = true; self.ran_update_since_last_redraw = false; + // XXX: Handle generically #[cfg(target_os = "android")] { - // Remove the `RawHandleWrapper` from the primary window. + // Remove the `RawWindowHandleWrapper` from the primary window. // This will trigger the surface destruction. let mut query = self .world_mut() @@ -539,7 +540,7 @@ impl WinitAppRunnerState { let entity = query.single(&self.world()).unwrap(); self.world_mut() .entity_mut(entity) - .remove::(); + .remove::(); } } @@ -550,13 +551,14 @@ impl WinitAppRunnerState { // Trigger the next redraw to refresh the screen immediately self.redraw_requested = true; + // XXX: Handle generically #[cfg(target_os = "android")] { // Get windows that are cached but without raw handles. Those window were already created, but got their // handle wrapper removed when the app was suspended. let mut query = self.world_mut() - .query_filtered::<(Entity, &Window, &CursorOptions), (With, Without)>(); + .query_filtered::<(Entity, &Window, &CursorOptions), (With, Without)>(); if let Ok((entity, window, cursor_options)) = query.single(&self.world()) { let window = window.clone(); let cursor_options = cursor_options.clone(); @@ -580,7 +582,7 @@ impl WinitAppRunnerState { &monitors, ); - let wrapper = RawHandleWrapper::new(winit_window).unwrap(); + let wrapper = RawWindowHandleWrapper::new(winit_window).unwrap(); self.world_mut().entity_mut(entity).insert(wrapper); }); diff --git a/crates/bevy_winit/src/system.rs b/crates/bevy_winit/src/system.rs index 6d3a76c9b3728..1662e3f34b1a5 100644 --- a/crates/bevy_winit/src/system.rs +++ b/crates/bevy_winit/src/system.rs @@ -12,7 +12,7 @@ use bevy_ecs::{ }; use bevy_input::keyboard::{Key, KeyCode, KeyboardFocusLost, KeyboardInput}; use bevy_window::{ - ClosingWindow, CursorOptions, Monitor, PrimaryMonitor, RawHandleWrapper, VideoMode, Window, + ClosingWindow, CursorOptions, Monitor, PrimaryMonitor, RawWindowHandleWrapper, VideoMode, Window, WindowClosed, WindowClosing, WindowCreated, WindowEvent, WindowFocused, WindowMode, WindowResized, WindowWrapper, }; @@ -93,7 +93,7 @@ pub fn create_windows( WinitWindowPressedKeys::default(), )); - if let Ok(handle_wrapper) = RawHandleWrapper::new(winit_window) { + if let Ok(handle_wrapper) = RawWindowHandleWrapper::new(winit_window) { commands.entity(entity).insert(handle_wrapper.clone()); if let Some(handle_holder) = handle_holder { *handle_holder.0.lock().unwrap() = Some(handle_wrapper);