1
1
use std:: sync:: Arc ;
2
2
3
- use tracing:: error;
4
- use wgpu:: { Adapter , Instance , Surface } ;
5
-
6
3
use epaint:: mutex:: RwLock ;
7
4
5
+ use tracing:: error;
6
+
8
7
use crate :: { renderer, RenderState , Renderer , SurfaceErrorAction , WgpuConfiguration } ;
9
8
10
9
struct SurfaceState {
11
- surface : Surface ,
10
+ surface : wgpu:: Surface ,
11
+ alpha_mode : wgpu:: CompositeAlphaMode ,
12
12
width : u32 ,
13
13
height : u32 ,
14
14
}
@@ -19,11 +19,12 @@ struct SurfaceState {
19
19
pub struct Painter {
20
20
configuration : WgpuConfiguration ,
21
21
msaa_samples : u32 ,
22
+ support_transparent_backbuffer : bool ,
22
23
depth_format : Option < wgpu:: TextureFormat > ,
23
24
depth_texture_view : Option < wgpu:: TextureView > ,
24
25
25
- instance : Instance ,
26
- adapter : Option < Adapter > ,
26
+ instance : wgpu :: Instance ,
27
+ adapter : Option < wgpu :: Adapter > ,
27
28
render_state : Option < RenderState > ,
28
29
surface_state : Option < SurfaceState > ,
29
30
}
@@ -41,7 +42,12 @@ impl Painter {
41
42
/// [`set_window()`](Self::set_window) once you have
42
43
/// a [`winit::window::Window`] with a valid `.raw_window_handle()`
43
44
/// associated.
44
- pub fn new ( configuration : WgpuConfiguration , msaa_samples : u32 , depth_bits : u8 ) -> Self {
45
+ pub fn new (
46
+ configuration : WgpuConfiguration ,
47
+ msaa_samples : u32 ,
48
+ depth_bits : u8 ,
49
+ support_transparent_backbuffer : bool ,
50
+ ) -> Self {
45
51
let instance = wgpu:: Instance :: new ( wgpu:: InstanceDescriptor {
46
52
backends : configuration. backends ,
47
53
dx12_shader_compiler : Default :: default ( ) , //
@@ -50,6 +56,7 @@ impl Painter {
50
56
Self {
51
57
configuration,
52
58
msaa_samples,
59
+ support_transparent_backbuffer,
53
60
depth_format : ( depth_bits > 0 ) . then_some ( wgpu:: TextureFormat :: Depth32Float ) ,
54
61
depth_texture_view : None ,
55
62
@@ -69,7 +76,7 @@ impl Painter {
69
76
70
77
async fn init_render_state (
71
78
& self ,
72
- adapter : & Adapter ,
79
+ adapter : & wgpu :: Adapter ,
73
80
target_format : wgpu:: TextureFormat ,
74
81
) -> Result < RenderState , wgpu:: RequestDeviceError > {
75
82
adapter
@@ -94,7 +101,7 @@ impl Painter {
94
101
// will have the same format and so this render state will remain valid.
95
102
async fn ensure_render_state_for_surface (
96
103
& mut self ,
97
- surface : & Surface ,
104
+ surface : & wgpu :: Surface ,
98
105
) -> Result < ( ) , wgpu:: RequestDeviceError > {
99
106
if self . adapter . is_none ( ) {
100
107
self . adapter = self
@@ -121,34 +128,23 @@ impl Painter {
121
128
Ok ( ( ) )
122
129
}
123
130
124
- fn configure_surface ( & mut self , width_in_pixels : u32 , height_in_pixels : u32 ) {
125
- crate :: profile_function!( ) ;
126
-
127
- let render_state = self
128
- . render_state
129
- . as_ref ( )
130
- . expect ( "Render state should exist before surface configuration" ) ;
131
- let format = render_state. target_format ;
132
-
133
- let config = wgpu:: SurfaceConfiguration {
134
- usage : wgpu:: TextureUsages :: RENDER_ATTACHMENT ,
135
- format,
136
- width : width_in_pixels,
137
- height : height_in_pixels,
138
- present_mode : self . configuration . present_mode ,
139
- alpha_mode : wgpu:: CompositeAlphaMode :: Auto ,
140
- view_formats : vec ! [ format] ,
141
- } ;
142
-
143
- let surface_state = self
144
- . surface_state
145
- . as_mut ( )
146
- . expect ( "Surface state should exist before surface configuration" ) ;
147
- surface_state
148
- . surface
149
- . configure ( & render_state. device , & config) ;
150
- surface_state. width = width_in_pixels;
151
- surface_state. height = height_in_pixels;
131
+ fn configure_surface (
132
+ surface_state : & SurfaceState ,
133
+ render_state : & RenderState ,
134
+ present_mode : wgpu:: PresentMode ,
135
+ ) {
136
+ surface_state. surface . configure (
137
+ & render_state. device ,
138
+ & wgpu:: SurfaceConfiguration {
139
+ usage : wgpu:: TextureUsages :: RENDER_ATTACHMENT ,
140
+ format : render_state. target_format ,
141
+ width : surface_state. width ,
142
+ height : surface_state. height ,
143
+ present_mode,
144
+ alpha_mode : surface_state. alpha_mode ,
145
+ view_formats : vec ! [ render_state. target_format] ,
146
+ } ,
147
+ ) ;
152
148
}
153
149
154
150
/// Updates (or clears) the [`winit::window::Window`] associated with the [`Painter`]
@@ -188,15 +184,34 @@ impl Painter {
188
184
189
185
self . ensure_render_state_for_surface ( & surface) . await ?;
190
186
187
+ let alpha_mode = if self . support_transparent_backbuffer {
188
+ let supported_alpha_modes = surface
189
+ . get_capabilities ( self . adapter . as_ref ( ) . unwrap ( ) )
190
+ . alpha_modes ;
191
+
192
+ // Prefer pre multiplied over post multiplied!
193
+ if supported_alpha_modes. contains ( & wgpu:: CompositeAlphaMode :: PreMultiplied ) {
194
+ wgpu:: CompositeAlphaMode :: PreMultiplied
195
+ } else if supported_alpha_modes
196
+ . contains ( & wgpu:: CompositeAlphaMode :: PostMultiplied )
197
+ {
198
+ wgpu:: CompositeAlphaMode :: PostMultiplied
199
+ } else {
200
+ warn ! ( "Transparent window was requested, but the active wgpu surface does not support a `CompositeAlphaMode` with transparency." ) ;
201
+ wgpu:: CompositeAlphaMode :: Auto
202
+ }
203
+ } else {
204
+ wgpu:: CompositeAlphaMode :: Auto
205
+ } ;
206
+
191
207
let size = window. inner_size ( ) ;
192
- let width = size. width ;
193
- let height = size. height ;
194
208
self . surface_state = Some ( SurfaceState {
195
209
surface,
196
- width,
197
- height,
210
+ width : size. width ,
211
+ height : size. height ,
212
+ alpha_mode,
198
213
} ) ;
199
- self . resize_and_generate_depth_texture_view ( width, height) ;
214
+ self . resize_and_generate_depth_texture_view ( size . width , size . height ) ;
200
215
}
201
216
None => {
202
217
self . surface_state = None ;
@@ -221,10 +236,17 @@ impl Painter {
221
236
width_in_pixels : u32 ,
222
237
height_in_pixels : u32 ,
223
238
) {
224
- self . configure_surface ( width_in_pixels, height_in_pixels) ;
225
- let device = & self . render_state . as_ref ( ) . unwrap ( ) . device ;
239
+ let render_state = self . render_state . as_ref ( ) . unwrap ( ) ;
240
+ let surface_state = self . surface_state . as_mut ( ) . unwrap ( ) ;
241
+
242
+ surface_state. width = width_in_pixels;
243
+ surface_state. height = height_in_pixels;
244
+
245
+ Self :: configure_surface ( surface_state, render_state, self . configuration . present_mode ) ;
246
+
226
247
self . depth_texture_view = self . depth_format . map ( |depth_format| {
227
- device
248
+ render_state
249
+ . device
228
250
. create_texture ( & wgpu:: TextureDescriptor {
229
251
label : Some ( "egui_depth_texture" ) ,
230
252
size : wgpu:: Extent3d {
@@ -269,7 +291,6 @@ impl Painter {
269
291
Some ( rs) => rs,
270
292
None => return ,
271
293
} ;
272
- let ( width, height) = ( surface_state. width , surface_state. height ) ;
273
294
274
295
let output_frame = {
275
296
crate :: profile_scope!( "get_current_texture" ) ;
@@ -282,7 +303,11 @@ impl Painter {
282
303
#[ allow( clippy:: single_match_else) ]
283
304
Err ( e) => match ( * self . configuration . on_surface_error ) ( e) {
284
305
SurfaceErrorAction :: RecreateSurface => {
285
- self . configure_surface ( width, height) ;
306
+ Self :: configure_surface (
307
+ surface_state,
308
+ render_state,
309
+ self . configuration . present_mode ,
310
+ ) ;
286
311
return ;
287
312
}
288
313
SurfaceErrorAction :: SkipFrame => {
@@ -300,7 +325,7 @@ impl Painter {
300
325
301
326
// Upload all resources for the GPU.
302
327
let screen_descriptor = renderer:: ScreenDescriptor {
303
- size_in_pixels : [ width, height] ,
328
+ size_in_pixels : [ surface_state . width , surface_state . height ] ,
304
329
pixels_per_point,
305
330
} ;
306
331
0 commit comments