From 9051b314266e5067fd7d855c9c58b3317a522686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sun, 19 May 2024 01:11:22 +0200 Subject: [PATCH] support webgl2 --- crates/bevy_render/src/lib.rs | 24 ++++++++++++++++-------- crates/bevy_window/src/lib.rs | 7 ++++++- crates/bevy_window/src/raw_handle.rs | 11 ++++++++++- crates/bevy_winit/src/lib.rs | 12 +++++++++++- crates/bevy_winit/src/system.rs | 8 ++++++-- 5 files changed, 49 insertions(+), 13 deletions(-) diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index dea5f7bb7d38f..120425fc948d3 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -58,7 +58,7 @@ use bevy_utils::prelude::default; pub use extract_param::Extract; use bevy_hierarchy::ValidParentCheckPlugin; -use bevy_window::{PrimaryWindow, RawHandleWrapper}; +use bevy_window::{PrimaryWindow, RawHandleWrapperHolder}; use extract_resource::ExtractResourcePlugin; use globals::GlobalsPlugin; use render_asset::RenderAssetBytesPerFrame; @@ -268,10 +268,9 @@ impl Plugin for RenderPlugin { )); let mut system_state: SystemState< - Query<&RawHandleWrapper, With>, + Query<&RawHandleWrapperHolder, With>, > = SystemState::new(app.world_mut()); let primary_window = system_state.get(app.world()).get_single().ok().cloned(); - let settings = render_creation.clone(); let async_renderer = async move { let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { @@ -282,11 +281,20 @@ impl Plugin for RenderPlugin { }); // SAFETY: Plugins should be set up on the main thread. - let surface = primary_window.map(|wrapper| unsafe { - let handle = wrapper.get_handle(); - instance - .create_surface(handle) - .expect("Failed to create wgpu surface") + let surface = primary_window.and_then(|wrapper| unsafe { + let maybe_handle = wrapper.0.lock().expect( + "Couldn't get the window handle in time for renderer initialization", + ); + if let Some(wrapper) = maybe_handle.as_ref() { + let handle = wrapper.get_handle(); + Some( + instance + .create_surface(handle) + .expect("Failed to create wgpu surface"), + ) + } else { + None + } }); let request_adapter_options = wgpu::RequestAdapterOptions { diff --git a/crates/bevy_window/src/lib.rs b/crates/bevy_window/src/lib.rs index fcb895a619e73..9dd91bd86219d 100644 --- a/crates/bevy_window/src/lib.rs +++ b/crates/bevy_window/src/lib.rs @@ -11,6 +11,8 @@ //! The [`WindowPlugin`] sets up some global window-related parameters and //! is part of the [`DefaultPlugins`](https://docs.rs/bevy/latest/bevy/struct.DefaultPlugins.html). +use std::sync::{Arc, Mutex}; + use bevy_a11y::Focus; mod cursor; @@ -112,7 +114,10 @@ impl Plugin for WindowPlugin { let initial_focus = app .world_mut() .spawn(primary_window.clone()) - .insert(PrimaryWindow) + .insert(( + PrimaryWindow, + RawHandleWrapperHolder(Arc::new(Mutex::new(None))), + )) .id(); if let Some(mut focus) = app.world_mut().get_resource_mut::() { **focus = Some(initial_focus); diff --git a/crates/bevy_window/src/raw_handle.rs b/crates/bevy_window/src/raw_handle.rs index 0b799a1142936..81b9a37096a83 100644 --- a/crates/bevy_window/src/raw_handle.rs +++ b/crates/bevy_window/src/raw_handle.rs @@ -5,7 +5,12 @@ use raw_window_handle::{ DisplayHandle, HandleError, HasDisplayHandle, HasWindowHandle, RawDisplayHandle, RawWindowHandle, WindowHandle, }; -use std::{any::Any, marker::PhantomData, ops::Deref, sync::Arc}; +use std::{ + any::Any, + marker::PhantomData, + ops::Deref, + sync::{Arc, Mutex}, +}; /// A wrapper over a window. /// @@ -116,3 +121,7 @@ impl HasDisplayHandle for ThreadLockedRawWindowHandleWrapper { Ok(unsafe { DisplayHandle::borrow_raw(self.0.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 d4e53eda117ba..6d54214b02ab2 100644 --- a/crates/bevy_winit/src/lib.rs +++ b/crates/bevy_winit/src/lib.rs @@ -12,6 +12,7 @@ //! The app's [runner](bevy_app::App::runner) is set by `WinitPlugin` and handles the `winit` [`EventLoop`]. //! See `winit_runner` for details. +use bevy_window::RawHandleWrapperHolder; use std::marker::PhantomData; use winit::event_loop::EventLoop; #[cfg(target_os = "android")] @@ -158,7 +159,16 @@ impl AppSendEvent for Vec { /// The parameters of the [`create_windows`] system. pub type CreateWindowParams<'w, 's, F = ()> = ( Commands<'w, 's>, - Query<'w, 's, (Entity, &'static mut Window), F>, + Query< + 'w, + 's, + ( + Entity, + &'static mut Window, + Option<&'static RawHandleWrapperHolder>, + ), + F, + >, EventWriter<'w, WindowCreated>, NonSendMut<'w, WinitWindows>, NonSendMut<'w, AccessKitAdapters>, diff --git a/crates/bevy_winit/src/system.rs b/crates/bevy_winit/src/system.rs index ece5a3dbbfea5..40861a2d28996 100644 --- a/crates/bevy_winit/src/system.rs +++ b/crates/bevy_winit/src/system.rs @@ -45,7 +45,7 @@ pub fn create_windows( accessibility_requested, ): SystemParamItem>, ) { - for (entity, mut window) in &mut created_windows { + for (entity, mut window, handle_holder) in &mut created_windows { if winit_windows.get_window(entity).is_some() { continue; } @@ -78,7 +78,11 @@ pub fn create_windows( }); if let Ok(handle_wrapper) = RawHandleWrapper::new(winit_window) { - commands.entity(entity).insert(handle_wrapper); + let mut entity = commands.entity(entity); + entity.insert(handle_wrapper.clone()); + if let Some(handle_holder) = handle_holder { + *handle_holder.0.lock().unwrap() = Some(handle_wrapper); + } } #[cfg(target_arch = "wasm32")]