@@ -42,6 +42,7 @@ pub struct Surface {
42
42
}
43
43
44
44
pub struct TargetTexture {
45
+ texture : wgpu:: Texture ,
45
46
view : wgpu:: TextureView ,
46
47
size : UVec2 ,
47
48
}
@@ -60,29 +61,6 @@ const VELLO_SURFACE_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Rgba8Unor
60
61
impl WgpuExecutor {
61
62
pub async fn render_vello_scene ( & self , scene : & Scene , surface : & WgpuSurface , size : UVec2 , context : & RenderContext , background : Color ) -> Result < ( ) > {
62
63
let mut guard = surface. surface . target_texture . lock ( ) . await ;
63
- let target_texture = if let Some ( target_texture) = & * guard
64
- && target_texture. size == size
65
- {
66
- target_texture
67
- } else {
68
- let texture = self . context . device . create_texture ( & wgpu:: TextureDescriptor {
69
- label : None ,
70
- size : wgpu:: Extent3d {
71
- width : size. x ,
72
- height : size. y ,
73
- depth_or_array_layers : 1 ,
74
- } ,
75
- mip_level_count : 1 ,
76
- sample_count : 1 ,
77
- dimension : wgpu:: TextureDimension :: D2 ,
78
- usage : wgpu:: TextureUsages :: STORAGE_BINDING | wgpu:: TextureUsages :: TEXTURE_BINDING ,
79
- format : VELLO_SURFACE_FORMAT ,
80
- view_formats : & [ ] ,
81
- } ) ;
82
- let view = texture. create_view ( & wgpu:: TextureViewDescriptor :: default ( ) ) ;
83
- * guard = Some ( TargetTexture { size, view } ) ;
84
- guard. as_ref ( ) . unwrap ( )
85
- } ;
86
64
87
65
let surface_inner = & surface. surface . inner ;
88
66
let surface_caps = surface_inner. get_capabilities ( & self . context . adapter ) ;
@@ -100,39 +78,14 @@ impl WgpuExecutor {
100
78
} ,
101
79
) ;
102
80
103
- let [ r, g, b, _] = background. to_rgba8_srgb ( ) ;
104
- let render_params = RenderParams {
105
- // We are using an explicit opaque color here to eliminate the alpha premultiplication step
106
- // which would be required to support a transparent webgpu canvas
107
- base_color : vello:: peniko:: Color :: from_rgba8 ( r, g, b, 0xff ) ,
108
- width : size. x ,
109
- height : size. y ,
110
- antialiasing_method : AaConfig :: Msaa16 ,
111
- } ;
112
-
113
- {
114
- let mut renderer = self . vello_renderer . lock ( ) . await ;
115
- for ( image, texture) in context. resource_overrides . iter ( ) {
116
- let texture_view = wgpu:: TexelCopyTextureInfoBase {
117
- texture : texture. clone ( ) ,
118
- mip_level : 0 ,
119
- origin : Origin3d :: ZERO ,
120
- aspect : TextureAspect :: All ,
121
- } ;
122
- renderer. override_image ( image, Some ( texture_view) ) ;
123
- }
124
- renderer. render_to_texture ( & self . context . device , & self . context . queue , scene, & target_texture. view , & render_params) ?;
125
- for ( image, _) in context. resource_overrides . iter ( ) {
126
- renderer. override_image ( image, None ) ;
127
- }
128
- }
81
+ self . render_vello_scene_to_target_texture ( scene, size, context, background, & mut guard) . await ?;
129
82
130
83
let surface_texture = surface_inner. get_current_texture ( ) ?;
131
84
let mut encoder = self . context . device . create_command_encoder ( & wgpu:: CommandEncoderDescriptor { label : Some ( "Surface Blit" ) } ) ;
132
85
surface. surface . blitter . copy (
133
86
& self . context . device ,
134
87
& mut encoder,
135
- & target_texture . view ,
88
+ & guard . as_ref ( ) . unwrap ( ) . view ,
136
89
& surface_texture. texture . create_view ( & wgpu:: TextureViewDescriptor :: default ( ) ) ,
137
90
) ;
138
91
self . context . queue . submit ( [ encoder. finish ( ) ] ) ;
@@ -142,21 +95,35 @@ impl WgpuExecutor {
142
95
}
143
96
144
97
pub async fn render_vello_scene_to_texture ( & self , scene : & Scene , size : UVec2 , context : & RenderContext , background : Color ) -> Result < wgpu:: Texture > {
145
- let texture = self . context . device . create_texture ( & wgpu:: TextureDescriptor {
146
- label : None ,
147
- size : wgpu:: Extent3d {
148
- width : size. x . max ( 1 ) ,
149
- height : size. y . max ( 1 ) ,
150
- depth_or_array_layers : 1 ,
151
- } ,
152
- mip_level_count : 1 ,
153
- sample_count : 1 ,
154
- dimension : wgpu:: TextureDimension :: D2 ,
155
- usage : wgpu:: TextureUsages :: STORAGE_BINDING | wgpu:: TextureUsages :: TEXTURE_BINDING ,
156
- format : VELLO_SURFACE_FORMAT ,
157
- view_formats : & [ ] ,
158
- } ) ;
159
- let view = texture. create_view ( & wgpu:: TextureViewDescriptor :: default ( ) ) ;
98
+ let mut output = None ;
99
+ self . render_vello_scene_to_target_texture ( scene, size, context, background, & mut output) . await ?;
100
+ Ok ( output. unwrap ( ) . texture )
101
+ }
102
+
103
+ async fn render_vello_scene_to_target_texture ( & self , scene : & Scene , size : UVec2 , context : & RenderContext , background : Color , output : & mut Option < TargetTexture > ) -> Result < ( ) > {
104
+ let target_texture = if let Some ( target_texture) = output
105
+ && target_texture. size == size
106
+ {
107
+ target_texture
108
+ } else {
109
+ let texture = self . context . device . create_texture ( & wgpu:: TextureDescriptor {
110
+ label : None ,
111
+ size : wgpu:: Extent3d {
112
+ width : size. x ,
113
+ height : size. y ,
114
+ depth_or_array_layers : 1 ,
115
+ } ,
116
+ mip_level_count : 1 ,
117
+ sample_count : 1 ,
118
+ dimension : wgpu:: TextureDimension :: D2 ,
119
+ usage : wgpu:: TextureUsages :: STORAGE_BINDING | wgpu:: TextureUsages :: TEXTURE_BINDING ,
120
+ format : VELLO_SURFACE_FORMAT ,
121
+ view_formats : & [ ] ,
122
+ } ) ;
123
+ let view = texture. create_view ( & wgpu:: TextureViewDescriptor :: default ( ) ) ;
124
+ * output = Some ( TargetTexture { texture, view, size } ) ;
125
+ output. as_mut ( ) . unwrap ( )
126
+ } ;
160
127
161
128
let [ r, g, b, a] = background. to_rgba8_srgb ( ) ;
162
129
let render_params = RenderParams {
@@ -177,13 +144,12 @@ impl WgpuExecutor {
177
144
} ;
178
145
renderer. override_image ( image, Some ( texture_view) ) ;
179
146
}
180
- renderer. render_to_texture ( & self . context . device , & self . context . queue , scene, & view, & render_params) ?;
147
+ renderer. render_to_texture ( & self . context . device , & self . context . queue , scene, & target_texture . view , & render_params) ?;
181
148
for ( image, _) in context. resource_overrides . iter ( ) {
182
149
renderer. override_image ( image, None ) ;
183
150
}
184
151
}
185
-
186
- Ok ( texture)
152
+ Ok ( ( ) )
187
153
}
188
154
189
155
#[ cfg( target_family = "wasm" ) ]
@@ -212,26 +178,9 @@ impl WgpuExecutor {
212
178
213
179
impl WgpuExecutor {
214
180
pub async fn new ( ) -> Option < Self > {
215
- let context = Context :: new ( ) . await ?;
216
-
217
- let vello_renderer = Renderer :: new (
218
- & context. device ,
219
- RendererOptions {
220
- // surface_format: Some(wgpu::TextureFormat::Rgba8Unorm),
221
- pipeline_cache : None ,
222
- use_cpu : false ,
223
- antialiasing_support : AaSupport :: all ( ) ,
224
- num_init_threads : std:: num:: NonZeroUsize :: new ( 1 ) ,
225
- } ,
226
- )
227
- . map_err ( |e| anyhow:: anyhow!( "Failed to create Vello renderer: {:?}" , e) )
228
- . ok ( ) ?;
229
-
230
- Some ( Self {
231
- context,
232
- vello_renderer : vello_renderer. into ( ) ,
233
- } )
181
+ Self :: with_context ( Context :: new ( ) . await ?)
234
182
}
183
+
235
184
pub fn with_context ( context : Context ) -> Option < Self > {
236
185
let vello_renderer = Renderer :: new (
237
186
& context. device ,
0 commit comments