@@ -17,7 +17,8 @@ use std::{
17
17
sync:: PoisonError ,
18
18
} ;
19
19
use wgpu:: {
20
- BufferUsages , SurfaceTargetUnsafe , TextureFormat , TextureUsages , TextureViewDescriptor ,
20
+ BufferUsages , SurfaceConfiguration , SurfaceTargetUnsafe , TextureFormat , TextureUsages ,
21
+ TextureViewDescriptor ,
21
22
} ;
22
23
23
24
pub mod screenshot;
@@ -42,7 +43,7 @@ impl Plugin for WindowRenderPlugin {
42
43
. add_systems (
43
44
Render ,
44
45
create_surfaces
45
- . run_if ( need_new_surfaces )
46
+ . run_if ( need_surface_configuration )
46
47
. before ( prepare_windows) ,
47
48
)
48
49
. add_systems ( Render , prepare_windows. in_set ( RenderSet :: ManageViews ) ) ;
@@ -198,7 +199,7 @@ fn extract_windows(
198
199
struct SurfaceData {
199
200
// TODO: what lifetime should this be?
200
201
surface : wgpu:: Surface < ' static > ,
201
- format : TextureFormat ,
202
+ configuration : SurfaceConfiguration ,
202
203
}
203
204
204
205
#[ derive( Resource , Default ) ]
@@ -254,45 +255,12 @@ pub fn prepare_windows(
254
255
continue ;
255
256
} ;
256
257
257
- let surface_configuration = wgpu:: SurfaceConfiguration {
258
- format : surface_data. format ,
259
- width : window. physical_width ,
260
- height : window. physical_height ,
261
- usage : TextureUsages :: RENDER_ATTACHMENT ,
262
- present_mode : match window. present_mode {
263
- PresentMode :: Fifo => wgpu:: PresentMode :: Fifo ,
264
- PresentMode :: FifoRelaxed => wgpu:: PresentMode :: FifoRelaxed ,
265
- PresentMode :: Mailbox => wgpu:: PresentMode :: Mailbox ,
266
- PresentMode :: Immediate => wgpu:: PresentMode :: Immediate ,
267
- PresentMode :: AutoVsync => wgpu:: PresentMode :: AutoVsync ,
268
- PresentMode :: AutoNoVsync => wgpu:: PresentMode :: AutoNoVsync ,
269
- } ,
270
- // TODO: Expose this as a setting somewhere
271
- // 2 is wgpu's default/what we've been using so far.
272
- // 1 is the minimum, but may cause lower framerates due to the cpu waiting for the gpu to finish
273
- // all work for the previous frame before starting work on the next frame, which then means the gpu
274
- // has to wait for the cpu to finish to start on the next frame.
275
- desired_maximum_frame_latency : 2 ,
276
- alpha_mode : match window. alpha_mode {
277
- CompositeAlphaMode :: Auto => wgpu:: CompositeAlphaMode :: Auto ,
278
- CompositeAlphaMode :: Opaque => wgpu:: CompositeAlphaMode :: Opaque ,
279
- CompositeAlphaMode :: PreMultiplied => wgpu:: CompositeAlphaMode :: PreMultiplied ,
280
- CompositeAlphaMode :: PostMultiplied => wgpu:: CompositeAlphaMode :: PostMultiplied ,
281
- CompositeAlphaMode :: Inherit => wgpu:: CompositeAlphaMode :: Inherit ,
282
- } ,
283
- view_formats : if !surface_data. format . is_srgb ( ) {
284
- vec ! [ surface_data. format. add_srgb_suffix( ) ]
285
- } else {
286
- vec ! [ ]
287
- } ,
288
- } ;
289
-
290
258
// This is an ugly hack to work around drivers that don't support MSAA.
291
259
// This should be removed once https://github.com/bevyengine/bevy/issues/7194 lands and we're doing proper
292
260
// feature detection for MSAA.
293
261
// When removed, we can also remove the `.after(prepare_windows)` of `prepare_core_3d_depth_textures` and `prepare_prepass_textures`
294
262
let sample_flags = render_adapter
295
- . get_texture_format_features ( surface_configuration . format )
263
+ . get_texture_format_features ( surface_data . configuration . format )
296
264
. flags ;
297
265
298
266
if !sample_flags. sample_count_supported ( msaa. samples ( ) ) {
@@ -340,7 +308,6 @@ pub fn prepare_windows(
340
308
341
309
let surface = & surface_data. surface ;
342
310
if not_already_configured || window. size_changed || window. present_mode_changed {
343
- render_device. configure_surface ( surface, & surface_configuration) ;
344
311
let frame = surface
345
312
. get_current_texture ( )
346
313
. expect ( "Error configuring surface" ) ;
@@ -351,7 +318,7 @@ pub fn prepare_windows(
351
318
window. set_swapchain_texture ( frame) ;
352
319
}
353
320
Err ( wgpu:: SurfaceError :: Outdated ) => {
354
- render_device. configure_surface ( surface, & surface_configuration ) ;
321
+ render_device. configure_surface ( surface, & surface_data . configuration ) ;
355
322
let frame = surface
356
323
. get_current_texture ( )
357
324
. expect ( "Error reconfiguring surface" ) ;
@@ -369,20 +336,20 @@ pub fn prepare_windows(
369
336
}
370
337
}
371
338
} ;
372
- window. swap_chain_texture_format = Some ( surface_data. format ) ;
339
+ window. swap_chain_texture_format = Some ( surface_data. configuration . format ) ;
373
340
374
341
if window. screenshot_func . is_some ( ) {
375
342
let texture = render_device. create_texture ( & wgpu:: TextureDescriptor {
376
343
label : Some ( "screenshot-capture-rendertarget" ) ,
377
344
size : wgpu:: Extent3d {
378
- width : surface_configuration . width ,
379
- height : surface_configuration . height ,
345
+ width : surface_data . configuration . width ,
346
+ height : surface_data . configuration . height ,
380
347
depth_or_array_layers : 1 ,
381
348
} ,
382
349
mip_level_count : 1 ,
383
350
sample_count : 1 ,
384
351
dimension : wgpu:: TextureDimension :: D2 ,
385
- format : surface_configuration . format . add_srgb_suffix ( ) ,
352
+ format : surface_data . configuration . format . add_srgb_suffix ( ) ,
386
353
usage : TextureUsages :: RENDER_ATTACHMENT
387
354
| TextureUsages :: COPY_SRC
388
355
| TextureUsages :: TEXTURE_BINDING ,
@@ -394,7 +361,7 @@ pub fn prepare_windows(
394
361
size : screenshot:: get_aligned_size (
395
362
window. physical_width ,
396
363
window. physical_height ,
397
- surface_data. format . pixel_size ( ) as u32 ,
364
+ surface_data. configuration . format . pixel_size ( ) as u32 ,
398
365
) as u64 ,
399
366
usage : BufferUsages :: MAP_READ | BufferUsages :: COPY_DST ,
400
367
mapped_at_creation : false ,
@@ -407,7 +374,7 @@ pub fn prepare_windows(
407
374
let pipeline_id = pipelines. specialize (
408
375
& pipeline_cache,
409
376
& screenshot_pipeline,
410
- surface_configuration . format ,
377
+ surface_data . configuration . format ,
411
378
) ;
412
379
window. swap_chain_texture_view = Some ( texture_view) ;
413
380
window. screenshot_memory = Some ( ScreenshotPreparedState {
@@ -420,12 +387,15 @@ pub fn prepare_windows(
420
387
}
421
388
}
422
389
423
- pub fn need_new_surfaces (
390
+ pub fn need_surface_configuration (
424
391
windows : Res < ExtractedWindows > ,
425
392
window_surfaces : Res < WindowSurfaces > ,
426
393
) -> bool {
427
394
for window in windows. windows . values ( ) {
428
- if !window_surfaces. configured_windows . contains ( & window. entity ) {
395
+ if !window_surfaces. configured_windows . contains ( & window. entity )
396
+ || window. size_changed
397
+ || window. present_mode_changed
398
+ {
429
399
return true ;
430
400
}
431
401
}
@@ -443,9 +413,10 @@ pub fn create_surfaces(
443
413
mut window_surfaces : ResMut < WindowSurfaces > ,
444
414
render_instance : Res < RenderInstance > ,
445
415
render_adapter : Res < RenderAdapter > ,
416
+ render_device : Res < RenderDevice > ,
446
417
) {
447
418
for window in windows. windows . values ( ) {
448
- window_surfaces
419
+ let data = window_surfaces
449
420
. surfaces
450
421
. entry ( window. entity )
451
422
. or_insert_with ( || {
@@ -477,7 +448,63 @@ pub fn create_surfaces(
477
448
}
478
449
}
479
450
480
- SurfaceData { surface, format }
451
+ let configuration = wgpu:: SurfaceConfiguration {
452
+ format,
453
+ width : window. physical_width ,
454
+ height : window. physical_height ,
455
+ usage : TextureUsages :: RENDER_ATTACHMENT ,
456
+ present_mode : match window. present_mode {
457
+ PresentMode :: Fifo => wgpu:: PresentMode :: Fifo ,
458
+ PresentMode :: FifoRelaxed => wgpu:: PresentMode :: FifoRelaxed ,
459
+ PresentMode :: Mailbox => wgpu:: PresentMode :: Mailbox ,
460
+ PresentMode :: Immediate => wgpu:: PresentMode :: Immediate ,
461
+ PresentMode :: AutoVsync => wgpu:: PresentMode :: AutoVsync ,
462
+ PresentMode :: AutoNoVsync => wgpu:: PresentMode :: AutoNoVsync ,
463
+ } ,
464
+ // TODO: Expose this as a setting somewhere
465
+ // 2 is wgpu's default/what we've been using so far.
466
+ // 1 is the minimum, but may cause lower framerates due to the cpu waiting for the gpu to finish
467
+ // all work for the previous frame before starting work on the next frame, which then means the gpu
468
+ // has to wait for the cpu to finish to start on the next frame.
469
+ desired_maximum_frame_latency : 2 ,
470
+ alpha_mode : match window. alpha_mode {
471
+ CompositeAlphaMode :: Auto => wgpu:: CompositeAlphaMode :: Auto ,
472
+ CompositeAlphaMode :: Opaque => wgpu:: CompositeAlphaMode :: Opaque ,
473
+ CompositeAlphaMode :: PreMultiplied => {
474
+ wgpu:: CompositeAlphaMode :: PreMultiplied
475
+ }
476
+ CompositeAlphaMode :: PostMultiplied => {
477
+ wgpu:: CompositeAlphaMode :: PostMultiplied
478
+ }
479
+ CompositeAlphaMode :: Inherit => wgpu:: CompositeAlphaMode :: Inherit ,
480
+ } ,
481
+ view_formats : if !format. is_srgb ( ) {
482
+ vec ! [ format. add_srgb_suffix( ) ]
483
+ } else {
484
+ vec ! [ ]
485
+ } ,
486
+ } ;
487
+
488
+ render_device. configure_surface ( & surface, & configuration) ;
489
+
490
+ SurfaceData {
491
+ surface,
492
+ configuration,
493
+ }
481
494
} ) ;
495
+
496
+ if window. size_changed || window. present_mode_changed {
497
+ data. configuration . width = window. physical_width ;
498
+ data. configuration . height = window. physical_height ;
499
+ data. configuration . present_mode = match window. present_mode {
500
+ PresentMode :: Fifo => wgpu:: PresentMode :: Fifo ,
501
+ PresentMode :: FifoRelaxed => wgpu:: PresentMode :: FifoRelaxed ,
502
+ PresentMode :: Mailbox => wgpu:: PresentMode :: Mailbox ,
503
+ PresentMode :: Immediate => wgpu:: PresentMode :: Immediate ,
504
+ PresentMode :: AutoVsync => wgpu:: PresentMode :: AutoVsync ,
505
+ PresentMode :: AutoNoVsync => wgpu:: PresentMode :: AutoNoVsync ,
506
+ } ;
507
+ render_device. configure_surface ( & data. surface , & data. configuration ) ;
508
+ }
482
509
}
483
510
}
0 commit comments