@@ -48,12 +48,58 @@ pub struct Surface {
4848 pub blitter : TextureBlitter ,
4949}
5050
51+ #[ derive( Clone , Debug ) ]
5152pub struct TargetTexture {
5253 texture : wgpu:: Texture ,
5354 view : wgpu:: TextureView ,
5455 size : UVec2 ,
5556}
5657
58+ impl TargetTexture {
59+ /// Creates a new TargetTexture with the specified size.
60+ pub fn new ( device : & wgpu:: Device , size : UVec2 ) -> Self {
61+ let size = size. max ( UVec2 :: ONE ) ;
62+ let texture = device. create_texture ( & wgpu:: TextureDescriptor {
63+ label : None ,
64+ size : wgpu:: Extent3d {
65+ width : size. x ,
66+ height : size. y ,
67+ depth_or_array_layers : 1 ,
68+ } ,
69+ mip_level_count : 1 ,
70+ sample_count : 1 ,
71+ dimension : wgpu:: TextureDimension :: D2 ,
72+ usage : wgpu:: TextureUsages :: STORAGE_BINDING | wgpu:: TextureUsages :: TEXTURE_BINDING | wgpu:: TextureUsages :: COPY_SRC ,
73+ format : VELLO_SURFACE_FORMAT ,
74+ view_formats : & [ ] ,
75+ } ) ;
76+ let view = texture. create_view ( & wgpu:: TextureViewDescriptor :: default ( ) ) ;
77+
78+ Self { texture, view, size }
79+ }
80+
81+ /// Ensures the texture has the specified size, creating a new one if needed.
82+ /// This allows reusing the same texture across frames when the size hasn't changed.
83+ pub fn ensure_size ( & mut self , device : & wgpu:: Device , size : UVec2 ) {
84+ let size = size. max ( UVec2 :: ONE ) ;
85+ if self . size == size {
86+ return ;
87+ }
88+
89+ * self = Self :: new ( device, size) ;
90+ }
91+
92+ /// Returns a reference to the texture view for rendering.
93+ pub fn view ( & self ) -> & wgpu:: TextureView {
94+ & self . view
95+ }
96+
97+ /// Returns a reference to the underlying texture.
98+ pub fn texture ( & self ) -> & wgpu:: Texture {
99+ & self . texture
100+ }
101+ }
102+
57103#[ cfg( target_family = "wasm" ) ]
58104pub type Window = web_sys:: HtmlCanvasElement ;
59105#[ cfg( not( target_family = "wasm" ) ) ]
@@ -71,55 +117,38 @@ impl WgpuExecutor {
71117 self . render_vello_scene_to_target_texture ( scene, size, context, background, & mut output) . await ?;
72118 Ok ( output. unwrap ( ) . texture )
73119 }
120+ pub async fn render_vello_scene_to_target_texture ( & self , scene : & Scene , size : UVec2 , context : & RenderContext , background : Color , output : & mut Option < TargetTexture > ) -> Result < ( ) > {
121+ // Initialize (lazily) if this is the first call
122+ if output. is_none ( ) {
123+ * output = Some ( TargetTexture :: new ( & self . context . device , size) ) ;
124+ }
74125
75- async fn render_vello_scene_to_target_texture ( & self , scene : & Scene , size : UVec2 , context : & RenderContext , background : Color , output : & mut Option < TargetTexture > ) -> Result < ( ) > {
76- let size = size. max ( UVec2 :: ONE ) ;
77- let target_texture = if let Some ( target_texture) = output
78- && target_texture. size == size
79- {
80- target_texture
81- } else {
82- let texture = self . context . device . create_texture ( & wgpu:: TextureDescriptor {
83- label : None ,
84- size : wgpu:: Extent3d {
85- width : size. x ,
86- height : size. y ,
87- depth_or_array_layers : 1 ,
88- } ,
89- mip_level_count : 1 ,
90- sample_count : 1 ,
91- dimension : wgpu:: TextureDimension :: D2 ,
92- usage : wgpu:: TextureUsages :: STORAGE_BINDING | wgpu:: TextureUsages :: TEXTURE_BINDING | wgpu:: TextureUsages :: COPY_SRC ,
93- format : VELLO_SURFACE_FORMAT ,
94- view_formats : & [ ] ,
95- } ) ;
96- let view = texture. create_view ( & wgpu:: TextureViewDescriptor :: default ( ) ) ;
97- * output = Some ( TargetTexture { texture, view, size } ) ;
98- output. as_mut ( ) . unwrap ( )
99- } ;
100-
101- let [ r, g, b, a] = background. to_rgba8_srgb ( ) ;
102- let render_params = RenderParams {
103- base_color : vello:: peniko:: Color :: from_rgba8 ( r, g, b, a) ,
104- width : size. x ,
105- height : size. y ,
106- antialiasing_method : AaConfig :: Msaa16 ,
107- } ;
108-
109- {
110- let mut renderer = self . vello_renderer . lock ( ) . await ;
111- for ( image_brush, texture) in context. resource_overrides . iter ( ) {
112- let texture_view = wgpu:: TexelCopyTextureInfoBase {
113- texture : texture. clone ( ) ,
114- mip_level : 0 ,
115- origin : Origin3d :: ZERO ,
116- aspect : TextureAspect :: All ,
117- } ;
118- renderer. override_image ( & image_brush. image , Some ( texture_view) ) ;
119- }
120- renderer. render_to_texture ( & self . context . device , & self . context . queue , scene, & target_texture. view , & render_params) ?;
121- for ( image_brush, _) in context. resource_overrides . iter ( ) {
122- renderer. override_image ( & image_brush. image , None ) ;
126+ if let Some ( target_texture) = output. as_mut ( ) {
127+ target_texture. ensure_size ( & self . context . device , size) ;
128+
129+ let [ r, g, b, a] = background. to_rgba8_srgb ( ) ;
130+ let render_params = RenderParams {
131+ base_color : vello:: peniko:: Color :: from_rgba8 ( r, g, b, a) ,
132+ width : size. x ,
133+ height : size. y ,
134+ antialiasing_method : AaConfig :: Msaa16 ,
135+ } ;
136+
137+ {
138+ let mut renderer = self . vello_renderer . lock ( ) . await ;
139+ for ( image_brush, texture) in context. resource_overrides . iter ( ) {
140+ let texture_view = wgpu:: TexelCopyTextureInfoBase {
141+ texture : texture. clone ( ) ,
142+ mip_level : 0 ,
143+ origin : Origin3d :: ZERO ,
144+ aspect : TextureAspect :: All ,
145+ } ;
146+ renderer. override_image ( & image_brush. image , Some ( texture_view) ) ;
147+ }
148+ renderer. render_to_texture ( & self . context . device , & self . context . queue , scene, target_texture. view ( ) , & render_params) ?;
149+ for ( image_brush, _) in context. resource_overrides . iter ( ) {
150+ renderer. override_image ( & image_brush. image , None ) ;
151+ }
123152 }
124153 }
125154 Ok ( ( ) )
0 commit comments