@@ -4,13 +4,12 @@ use anyhow::Result;
4
4
pub use context:: Context ;
5
5
use dyn_any:: StaticType ;
6
6
use glam:: UVec2 ;
7
- use graphene_application_io:: { ApplicationIo , EditorApi , SurfaceHandle } ;
7
+ use graphene_application_io:: { ApplicationIo , EditorApi , SurfaceHandle , SurfaceId } ;
8
8
use graphene_core:: { Color , Ctx } ;
9
9
pub use graphene_svg_renderer:: RenderContext ;
10
- use std:: sync:: Arc ;
10
+ use std:: sync:: { Arc , Mutex } ;
11
11
use vello:: Error ;
12
12
use vello:: { AaConfig , AaSupport , RenderParams , Renderer , RendererOptions , Scene } ;
13
- use wgpu:: TextureFormat ;
14
13
use wgpu:: util:: TextureBlitter ;
15
14
use wgpu:: { Origin3d , SurfaceConfiguration , TextureAspect } ;
16
15
@@ -35,19 +34,17 @@ impl<'a, T: ApplicationIo<Executor = WgpuExecutor>> From<&'a EditorApi<T>> for &
35
34
pub type WgpuSurface = Arc < SurfaceHandle < Surface > > ;
36
35
pub type WgpuWindow = Arc < SurfaceHandle < WindowHandle > > ;
37
36
38
- impl graphene_application_io:: Size for Surface {
39
- fn size ( & self ) -> UVec2 {
40
- self . resolution
41
- }
42
- }
43
-
44
37
pub struct Surface {
45
38
pub inner : wgpu:: Surface < ' static > ,
46
- pub target_texture : wgpu:: Texture ,
47
- pub target_view : wgpu:: TextureView ,
48
- pub blitter : wgpu:: util:: TextureBlitter ,
49
- resolution : UVec2 ,
39
+ pub target_texture : Mutex < Option < TargetTexture > > ,
40
+ pub blitter : TextureBlitter ,
41
+ }
42
+
43
+ pub struct TargetTexture {
44
+ view : wgpu:: TextureView ,
45
+ size : UVec2 ,
50
46
}
47
+
51
48
#[ cfg( target_arch = "wasm32" ) ]
52
49
pub type Window = web_sys:: HtmlCanvasElement ;
53
50
#[ cfg( not( target_arch = "wasm32" ) ) ]
@@ -58,29 +55,55 @@ unsafe impl StaticType for Surface {
58
55
}
59
56
60
57
impl WgpuExecutor {
61
- pub async fn render_vello_scene ( & self , scene : & Scene , surface : & WgpuSurface , width : u32 , height : u32 , context : & RenderContext , background : Color ) -> Result < ( ) > {
58
+ pub async fn render_vello_scene ( & self , scene : & Scene , surface : & WgpuSurface , size : UVec2 , context : & RenderContext , background : Color ) -> Result < ( ) > {
59
+ let mut guard = surface. surface . target_texture . lock ( ) . unwrap ( ) ;
60
+ let target_texture = if let Some ( target_texture) = & * guard
61
+ && target_texture. size == size
62
+ {
63
+ target_texture
64
+ } else {
65
+ let texture = self . context . device . create_texture ( & wgpu:: TextureDescriptor {
66
+ label : None ,
67
+ size : wgpu:: Extent3d {
68
+ width : size. x ,
69
+ height : size. y ,
70
+ depth_or_array_layers : 1 ,
71
+ } ,
72
+ mip_level_count : 1 ,
73
+ sample_count : 1 ,
74
+ dimension : wgpu:: TextureDimension :: D2 ,
75
+ usage : wgpu:: TextureUsages :: STORAGE_BINDING | wgpu:: TextureUsages :: TEXTURE_BINDING ,
76
+ format : wgpu:: TextureFormat :: Rgba8Unorm ,
77
+ view_formats : & [ ] ,
78
+ } ) ;
79
+ let view = texture. create_view ( & wgpu:: TextureViewDescriptor :: default ( ) ) ;
80
+ * guard = Some ( TargetTexture { size, view } ) ;
81
+ guard. as_ref ( ) . unwrap ( )
82
+ } ;
83
+
62
84
let surface_inner = & surface. surface . inner ;
63
85
let surface_caps = surface_inner. get_capabilities ( & self . context . adapter ) ;
64
86
surface_inner. configure (
65
87
& self . context . device ,
66
88
& SurfaceConfiguration {
67
89
usage : wgpu:: TextureUsages :: RENDER_ATTACHMENT | wgpu:: TextureUsages :: STORAGE_BINDING ,
68
90
format : wgpu:: TextureFormat :: Rgba8Unorm ,
69
- width,
70
- height,
91
+ width : size . x ,
92
+ height : size . y ,
71
93
present_mode : surface_caps. present_modes [ 0 ] ,
72
94
alpha_mode : wgpu:: CompositeAlphaMode :: Opaque ,
73
95
view_formats : vec ! [ ] ,
74
96
desired_maximum_frame_latency : 2 ,
75
97
} ,
76
98
) ;
99
+
77
100
let [ r, g, b, _] = background. to_rgba8_srgb ( ) ;
78
101
let render_params = RenderParams {
79
102
// We are using an explicit opaque color here to eliminate the alpha premultiplication step
80
103
// which would be required to support a transparent webgpu canvas
81
104
base_color : vello:: peniko:: Color :: from_rgba8 ( r, g, b, 0xff ) ,
82
- width,
83
- height,
105
+ width : size . x ,
106
+ height : size . y ,
84
107
antialiasing_method : AaConfig :: Msaa16 ,
85
108
} ;
86
109
@@ -99,17 +122,15 @@ impl WgpuExecutor {
99
122
Some ( texture_view) ,
100
123
) ;
101
124
}
102
- renderer
103
- . render_to_texture ( & self . context . device , & self . context . queue , scene, & surface. surface . target_view , & render_params)
104
- . unwrap ( ) ;
125
+ renderer. render_to_texture ( & self . context . device , & self . context . queue , scene, & target_texture. view , & render_params) ?;
105
126
}
106
127
107
128
let surface_texture = surface_inner. get_current_texture ( ) ?;
108
129
let mut encoder = self . context . device . create_command_encoder ( & wgpu:: CommandEncoderDescriptor { label : Some ( "Surface Blit" ) } ) ;
109
130
surface. surface . blitter . copy (
110
131
& self . context . device ,
111
132
& mut encoder,
112
- & surface . surface . target_view ,
133
+ & target_texture . view ,
113
134
& surface_texture. texture . create_view ( & wgpu:: TextureViewDescriptor :: default ( ) ) ,
114
135
) ;
115
136
self . context . queue . submit ( [ encoder. finish ( ) ] ) ;
@@ -121,78 +142,27 @@ impl WgpuExecutor {
121
142
#[ cfg( target_arch = "wasm32" ) ]
122
143
pub fn create_surface ( & self , canvas : graphene_application_io:: WasmSurfaceHandle ) -> Result < SurfaceHandle < Surface > > {
123
144
let surface = self . context . instance . create_surface ( wgpu:: SurfaceTarget :: Canvas ( canvas. surface ) ) ?;
124
- let size = UVec2 :: ZERO ;
125
-
126
- let capabilities = surface. get_capabilities ( & self . context . adapter ) ;
127
- let format = capabilities
128
- . formats
129
- . into_iter ( )
130
- . find ( |it| matches ! ( it, TextureFormat :: Rgba8Unorm | TextureFormat :: Bgra8Unorm ) )
131
- . ok_or ( Error :: UnsupportedSurfaceFormat ) ?;
132
- let target_texture = self . context . device . create_texture ( & wgpu:: TextureDescriptor {
133
- label : None ,
134
- size : wgpu:: Extent3d {
135
- width : size. x ,
136
- height : size. y ,
137
- depth_or_array_layers : 1 ,
138
- } ,
139
- mip_level_count : 1 ,
140
- sample_count : 1 ,
141
- dimension : wgpu:: TextureDimension :: D2 ,
142
- usage : wgpu:: TextureUsages :: STORAGE_BINDING | wgpu:: TextureUsages :: TEXTURE_BINDING ,
143
- format : TextureFormat :: Rgba8Unorm ,
144
- view_formats : & [ ] ,
145
- } ) ;
146
- let target_view = target_texture. create_view ( & wgpu:: TextureViewDescriptor :: default ( ) ) ;
147
- let blitter = TextureBlitter :: new ( & self . context . device , format) ;
148
-
149
- Ok ( SurfaceHandle {
150
- window_id : canvas. window_id ,
151
- surface : Surface {
152
- inner : surface,
153
- resolution : size,
154
- blitter,
155
- target_texture,
156
- target_view,
157
- } ,
158
- } )
145
+ self . create_surface_inner ( surface, canvas. window_id )
159
146
}
160
147
#[ cfg( not( target_arch = "wasm32" ) ) ]
161
148
pub fn create_surface ( & self , window : SurfaceHandle < Window > ) -> Result < SurfaceHandle < Surface > > {
162
- let size = window. surface . inner_size ( ) ;
163
- let resolution = UVec2 :: new ( size. width , size. height ) ;
164
149
let surface = self . context . instance . create_surface ( wgpu:: SurfaceTarget :: Window ( Box :: new ( window. surface ) ) ) ?;
150
+ self . create_surface_inner ( surface, window. window_id )
151
+ }
165
152
153
+ pub fn create_surface_inner ( & self , surface : wgpu:: Surface < ' static > , window_id : SurfaceId ) -> Result < SurfaceHandle < Surface > > {
166
154
let capabilities = surface. get_capabilities ( & self . context . adapter ) ;
167
155
let format = capabilities
168
156
. formats
169
157
. into_iter ( )
170
- . find ( |it| matches ! ( it, TextureFormat :: Rgba8Unorm | TextureFormat :: Bgra8Unorm ) )
158
+ . find ( |it| matches ! ( it, wgpu :: TextureFormat :: Rgba8Unorm | wgpu :: TextureFormat :: Bgra8Unorm ) )
171
159
. ok_or ( Error :: UnsupportedSurfaceFormat ) ?;
172
- let target_texture = self . context . device . create_texture ( & wgpu:: TextureDescriptor {
173
- label : None ,
174
- size : wgpu:: Extent3d {
175
- width : size. width ,
176
- height : size. height ,
177
- depth_or_array_layers : 1 ,
178
- } ,
179
- mip_level_count : 1 ,
180
- sample_count : 1 ,
181
- dimension : wgpu:: TextureDimension :: D2 ,
182
- usage : wgpu:: TextureUsages :: STORAGE_BINDING | wgpu:: TextureUsages :: TEXTURE_BINDING ,
183
- format : TextureFormat :: Rgba8Unorm ,
184
- view_formats : & [ ] ,
185
- } ) ;
186
- let target_view = target_texture. create_view ( & wgpu:: TextureViewDescriptor :: default ( ) ) ;
187
160
let blitter = TextureBlitter :: new ( & self . context . device , format) ;
188
-
189
161
Ok ( SurfaceHandle {
190
- window_id : window . window_id ,
162
+ window_id,
191
163
surface : Surface {
192
164
inner : surface,
193
- resolution,
194
- target_view,
195
- target_texture,
165
+ target_texture : Mutex :: new ( None ) ,
196
166
blitter,
197
167
} ,
198
168
} )
0 commit comments