@@ -4,13 +4,12 @@ use anyhow::Result;
44pub use context:: Context ;
55use dyn_any:: StaticType ;
66use glam:: UVec2 ;
7- use graphene_application_io:: { ApplicationIo , EditorApi , SurfaceHandle } ;
7+ use graphene_application_io:: { ApplicationIo , EditorApi , SurfaceHandle , SurfaceId } ;
88use graphene_core:: { Color , Ctx } ;
99pub use graphene_svg_renderer:: RenderContext ;
10- use std:: sync:: Arc ;
10+ use std:: sync:: { Arc , Mutex } ;
1111use vello:: Error ;
1212use vello:: { AaConfig , AaSupport , RenderParams , Renderer , RendererOptions , Scene } ;
13- use wgpu:: TextureFormat ;
1413use wgpu:: util:: TextureBlitter ;
1514use wgpu:: { Origin3d , SurfaceConfiguration , TextureAspect } ;
1615
@@ -35,19 +34,17 @@ impl<'a, T: ApplicationIo<Executor = WgpuExecutor>> From<&'a EditorApi<T>> for &
3534pub type WgpuSurface = Arc < SurfaceHandle < Surface > > ;
3635pub type WgpuWindow = Arc < SurfaceHandle < WindowHandle > > ;
3736
38- impl graphene_application_io:: Size for Surface {
39- fn size ( & self ) -> UVec2 {
40- self . resolution
41- }
42- }
43-
4437pub struct Surface {
4538 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 ,
5046}
47+
5148#[ cfg( target_arch = "wasm32" ) ]
5249pub type Window = web_sys:: HtmlCanvasElement ;
5350#[ cfg( not( target_arch = "wasm32" ) ) ]
@@ -58,29 +55,55 @@ unsafe impl StaticType for Surface {
5855}
5956
6057impl 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+
6284 let surface_inner = & surface. surface . inner ;
6385 let surface_caps = surface_inner. get_capabilities ( & self . context . adapter ) ;
6486 surface_inner. configure (
6587 & self . context . device ,
6688 & SurfaceConfiguration {
6789 usage : wgpu:: TextureUsages :: RENDER_ATTACHMENT | wgpu:: TextureUsages :: STORAGE_BINDING ,
6890 format : wgpu:: TextureFormat :: Rgba8Unorm ,
69- width,
70- height,
91+ width : size . x ,
92+ height : size . y ,
7193 present_mode : surface_caps. present_modes [ 0 ] ,
7294 alpha_mode : wgpu:: CompositeAlphaMode :: Opaque ,
7395 view_formats : vec ! [ ] ,
7496 desired_maximum_frame_latency : 2 ,
7597 } ,
7698 ) ;
99+
77100 let [ r, g, b, _] = background. to_rgba8_srgb ( ) ;
78101 let render_params = RenderParams {
79102 // We are using an explicit opaque color here to eliminate the alpha premultiplication step
80103 // which would be required to support a transparent webgpu canvas
81104 base_color : vello:: peniko:: Color :: from_rgba8 ( r, g, b, 0xff ) ,
82- width,
83- height,
105+ width : size . x ,
106+ height : size . y ,
84107 antialiasing_method : AaConfig :: Msaa16 ,
85108 } ;
86109
@@ -99,17 +122,15 @@ impl WgpuExecutor {
99122 Some ( texture_view) ,
100123 ) ;
101124 }
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) ?;
105126 }
106127
107128 let surface_texture = surface_inner. get_current_texture ( ) ?;
108129 let mut encoder = self . context . device . create_command_encoder ( & wgpu:: CommandEncoderDescriptor { label : Some ( "Surface Blit" ) } ) ;
109130 surface. surface . blitter . copy (
110131 & self . context . device ,
111132 & mut encoder,
112- & surface . surface . target_view ,
133+ & target_texture . view ,
113134 & surface_texture. texture . create_view ( & wgpu:: TextureViewDescriptor :: default ( ) ) ,
114135 ) ;
115136 self . context . queue . submit ( [ encoder. finish ( ) ] ) ;
@@ -121,78 +142,27 @@ impl WgpuExecutor {
121142 #[ cfg( target_arch = "wasm32" ) ]
122143 pub fn create_surface ( & self , canvas : graphene_application_io:: WasmSurfaceHandle ) -> Result < SurfaceHandle < Surface > > {
123144 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 )
159146 }
160147 #[ cfg( not( target_arch = "wasm32" ) ) ]
161148 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 ) ;
164149 let surface = self . context . instance . create_surface ( wgpu:: SurfaceTarget :: Window ( Box :: new ( window. surface ) ) ) ?;
150+ self . create_surface_inner ( surface, window. window_id )
151+ }
165152
153+ pub fn create_surface_inner ( & self , surface : wgpu:: Surface < ' static > , window_id : SurfaceId ) -> Result < SurfaceHandle < Surface > > {
166154 let capabilities = surface. get_capabilities ( & self . context . adapter ) ;
167155 let format = capabilities
168156 . formats
169157 . into_iter ( )
170- . find ( |it| matches ! ( it, TextureFormat :: Rgba8Unorm | TextureFormat :: Bgra8Unorm ) )
158+ . find ( |it| matches ! ( it, wgpu :: TextureFormat :: Rgba8Unorm | wgpu :: TextureFormat :: Bgra8Unorm ) )
171159 . 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 ( ) ) ;
187160 let blitter = TextureBlitter :: new ( & self . context . device , format) ;
188-
189161 Ok ( SurfaceHandle {
190- window_id : window . window_id ,
162+ window_id,
191163 surface : Surface {
192164 inner : surface,
193- resolution,
194- target_view,
195- target_texture,
165+ target_texture : Mutex :: new ( None ) ,
196166 blitter,
197167 } ,
198168 } )
0 commit comments