@@ -21,10 +21,6 @@ use screenshot::{
21
21
22
22
use super :: Msaa ;
23
23
24
- /// Token to ensure a system runs on the main thread.
25
- #[ derive( Resource , Default ) ]
26
- pub struct NonSendMarker ;
27
-
28
24
pub struct WindowRenderPlugin ;
29
25
30
26
impl Plugin for WindowRenderPlugin {
@@ -188,30 +184,28 @@ pub struct WindowSurfaces {
188
184
189
185
/// Creates and (re)configures window surfaces, and obtains a swapchain texture for rendering.
190
186
///
191
- /// NOTE: `get_current_texture` in `prepare_windows` can take a long time if the GPU workload is
192
- /// the performance bottleneck . This can be seen in profiles as multiple prepare-set systems all
193
- /// taking an unusually long time to complete, and all finishing at about the same time as the
194
- /// `prepare_windows` system. Improvements in bevy are planned to avoid this happening when it
195
- /// should not but it will still happen as it is easy for a user to create a large GPU workload
196
- /// relative to the GPU performance and/or CPU workload.
197
- /// This can be caused by many reasons, but several of them are :
198
- /// - GPU workload is more than your current GPU can manage
199
- /// - Error / performance bug in your custom shaders
200
- /// - wgpu was unable to detect a proper GPU hardware-accelerated device given the chosen
187
+ /// ** NOTE:** `get_current_texture` (acquiring the next framebuffer) in `prepare_windows` can take
188
+ /// a long time if the GPU workload is heavy . This can be seen in profiling views with many prepare
189
+ /// systems taking an unusually long time to complete, but all finishing at around the same time
190
+ /// `prepare_windows` does. Performance improvements are planned to reduce how often this happens,
191
+ /// but it will still be possible, since it's easy to create a heavy GPU workload.
192
+ ///
193
+ /// These are some contributing factors :
194
+ /// - The GPU workload is more than your GPU can handle.
195
+ /// - There are custom shaders with an error / performance bug.
196
+ /// - wgpu could not detect a proper GPU hardware-accelerated device given the chosen
201
197
/// [`Backends`](crate::settings::Backends), [`WgpuLimits`](crate::settings::WgpuLimits),
202
- /// and/or [`WgpuFeatures`](crate::settings::WgpuFeatures). For example, on Windows currently
203
- /// ` DirectX 11` is not supported by wgpu 0.12 and so if your GPU/drivers do not support Vulkan,
204
- /// it may be that a software renderer called "Microsoft Basic Render Driver" using ` DirectX 12`
205
- /// will be chosen and performance will be very poor. This is visible in a log message that is
206
- /// output during renderer initialization . Future versions of wgpu will support ` DirectX 11` , but
207
- /// another alternative is to try to use [`ANGLE`](https://github.com/gfx-rs/wgpu#angle) and
208
- /// [`Backends::GL`](crate::settings::Backends::GL) if your GPU/drivers support ` OpenGL 4.3` / `OpenGL ES 3.0` or
209
- /// later.
198
+ /// and/or [`WgpuFeatures`](crate::settings::WgpuFeatures).
199
+ /// - On Windows, DirectX 11 is not supported by wgpu 0.12, and if your GPU/drivers do not
200
+ /// support Vulkan, a software renderer called "Microsoft Basic Render Driver" using DirectX 12
201
+ /// may be used and performance will be very poor. This will be logged as a message when the
202
+ /// renderer is initialized . Future versions of wgpu will support DirectX 11, but an
203
+ /// alternative is to try to use [`ANGLE`](https://github.com/gfx-rs/wgpu#angle) and
204
+ /// [`Backends::GL`](crate::settings::Backends::GL) if your GPU/drivers support OpenGL 4.3,
205
+ /// OpenGL ES 3.0, or later.
210
206
#[ allow( clippy:: too_many_arguments) ]
211
207
pub fn prepare_windows (
212
- // By accessing a NonSend resource, we tell the scheduler to put this system on the main thread,
213
- // which is necessary for some OS s
214
- _marker : Option < NonSend < NonSendMarker > > ,
208
+ mut main_thread : ThreadLocal ,
215
209
mut windows : ResMut < ExtractedWindows > ,
216
210
mut window_surfaces : ResMut < WindowSurfaces > ,
217
211
render_device : Res < RenderDevice > ,
@@ -227,20 +221,28 @@ pub fn prepare_windows(
227
221
let surface_data = window_surfaces
228
222
. surfaces
229
223
. entry ( window. entity )
230
- . or_insert_with ( || unsafe {
231
- // NOTE: On some OSes this MUST be called from the main thread.
232
- // As of wgpu 0.15, only failable if the given window is a HTML canvas and obtaining a WebGPU or WebGL2 context fails.
233
- let surface = render_instance
234
- . create_surface ( & window. handle . get_handle ( ) )
235
- . expect ( "Failed to create wgpu surface" ) ;
224
+ . or_insert_with ( || {
225
+ let surface = main_thread. run ( |_| {
226
+ // SAFETY: raw window handle is valid
227
+ unsafe {
228
+ render_instance
229
+ // Some operating systems only allow dereferencing window handles in
230
+ // the *main* thread (and may panic if done in another thread).
231
+ . create_surface ( & window. handle . get_handle ( ) )
232
+ // As of wgpu 0.15, this can only fail if the window is a HTML canvas
233
+ // and obtaining a WebGPU/WebGL2 context fails.
234
+ . expect ( "failed to create wgpu surface" )
235
+ }
236
+ } ) ;
236
237
let caps = surface. get_capabilities ( & render_adapter) ;
237
238
let formats = caps. formats ;
238
- // For future HDR output support, we'll need to request a format that supports HDR,
239
- // but as of wgpu 0.15 that is not yet supported.
240
- // Prefer sRGB formats for surfaces , but fall back to first available format if no sRGB formats are available .
241
- let mut format = * formats. get ( 0 ) . expect ( "No supported formats for surface" ) ;
239
+ // Prefer sRGB formats, but fall back to first available format if none available.
240
+ // NOTE: To support HDR output in the future, we'll need to request a format that
241
+ // supports HDR , but as of wgpu 0.15 that is still unsupported .
242
+ let mut format = * formats. get ( 0 ) . expect ( "no supported formats for surface" ) ;
242
243
for available_format in formats {
243
- // Rgba8UnormSrgb and Bgra8UnormSrgb and the only sRGB formats wgpu exposes that we can use for surfaces.
244
+ // Rgba8UnormSrgb and Bgra8UnormSrgb and the only sRGB formats wgpu exposes
245
+ // that we can use for surfaces.
244
246
if available_format == TextureFormat :: Rgba8UnormSrgb
245
247
|| available_format == TextureFormat :: Bgra8UnormSrgb
246
248
{
0 commit comments