@@ -96,6 +96,7 @@ struct TileCacheImpl {
9696 total_memory : usize ,
9797 cache_key : CacheKey ,
9898 current_scale : f64 ,
99+ texture_cache : ( UVec2 , Vec < Arc < wgpu:: Texture > > ) ,
99100}
100101
101102impl Default for TileCacheImpl {
@@ -106,6 +107,7 @@ impl Default for TileCacheImpl {
106107 total_memory : 0 ,
107108 cache_key : CacheKey :: default ( ) ,
108109 current_scale : 0.0 ,
110+ texture_cache : Default :: default ( ) ,
109111 }
110112 }
111113}
@@ -224,6 +226,36 @@ impl TileCacheImpl {
224226 self . regions . clear ( ) ;
225227 self . total_memory = 0 ;
226228 }
229+
230+ pub fn request_texture ( & mut self , size : UVec2 , device : & wgpu:: Device ) -> Arc < wgpu:: Texture > {
231+ if self . texture_cache . 0 != size {
232+ self . texture_cache . 0 = size;
233+ self . texture_cache . 1 . clear ( ) ;
234+ }
235+ self . texture_cache . 1 . truncate ( 5 ) ;
236+ for texture in & self . texture_cache . 1 {
237+ if Arc :: strong_count ( & texture) == 1 {
238+ return Arc :: clone ( texture) ;
239+ }
240+ }
241+ let texture = Arc :: new ( device. create_texture ( & wgpu:: TextureDescriptor {
242+ label : Some ( "viewport_output" ) ,
243+ size : wgpu:: Extent3d {
244+ width : size. x ,
245+ height : size. y ,
246+ depth_or_array_layers : 1 ,
247+ } ,
248+ mip_level_count : 1 ,
249+ sample_count : 1 ,
250+ dimension : wgpu:: TextureDimension :: D2 ,
251+ format : wgpu:: TextureFormat :: Rgba8Unorm ,
252+ usage : wgpu:: TextureUsages :: RENDER_ATTACHMENT | wgpu:: TextureUsages :: COPY_DST | wgpu:: TextureUsages :: COPY_SRC | wgpu:: TextureUsages :: TEXTURE_BINDING ,
253+ view_formats : & [ ] ,
254+ } ) ) ;
255+ self . texture_cache . 1 . push ( texture. clone ( ) ) ;
256+
257+ texture
258+ }
227259}
228260
229261impl TileCache {
@@ -234,6 +266,10 @@ impl TileCache {
234266 pub fn store_regions ( & self , regions : Vec < CachedRegion > ) {
235267 self . 0 . lock ( ) . unwrap ( ) . store_regions ( regions) ;
236268 }
269+
270+ pub fn request_texture ( & self , size : UVec2 , device : & wgpu:: Device ) -> Arc < wgpu:: Texture > {
271+ self . 0 . lock ( ) . unwrap ( ) . request_texture ( size, device)
272+ }
237273}
238274
239275fn group_into_regions ( tiles : & [ TileCoord ] , scale : f64 , max_region_area : u32 ) -> Vec < RenderRegion > {
@@ -421,7 +457,12 @@ pub async fn render_output_cache<'a: 'n>(
421457 }
422458
423459 let exec = editor_api. application_io . as_ref ( ) . unwrap ( ) . gpu_executor ( ) . unwrap ( ) ;
424- let ( output_texture, combined_metadata) = composite_cached_regions ( & all_regions, & viewport_bounds, physical_resolution, logical_scale, physical_scale, exec) ;
460+
461+ // TODO: Use texture pool to reuse existing unused textures instead of allocating fresh ones every time
462+ let device = & exec. context . device ;
463+ let output_texture = tile_cache. request_texture ( physical_resolution, device) ;
464+
465+ let combined_metadata = composite_cached_regions ( & all_regions, & viewport_bounds, output_texture. as_ref ( ) , logical_scale, physical_scale, exec) ;
425466
426467 RenderOutput {
427468 data : RenderOutputType :: Texture ( ImageTexture { texture : output_texture } ) ,
@@ -475,7 +516,7 @@ where
475516 let memory_size = ( region_pixel_size. x * region_pixel_size. y ) as usize * BYTES_PER_PIXEL ;
476517
477518 CachedRegion {
478- texture : rendered_texture. texture ,
519+ texture : rendered_texture. texture . as_ref ( ) . clone ( ) ,
479520 texture_size : region_pixel_size,
480521 scene_bounds : region. scene_bounds . clone ( ) ,
481522 tiles : region. tiles . clone ( ) ,
@@ -488,29 +529,14 @@ where
488529fn composite_cached_regions (
489530 regions : & [ CachedRegion ] ,
490531 viewport_bounds : & AxisAlignedBbox ,
491- output_resolution : UVec2 ,
532+ output_texture : & wgpu :: Texture ,
492533 logical_scale : f64 ,
493534 physical_scale : f64 ,
494535 exec : & wgpu_executor:: WgpuExecutor ,
495- ) -> ( wgpu :: Texture , rendering:: RenderMetadata ) {
536+ ) -> rendering:: RenderMetadata {
496537 let device = & exec. context . device ;
497538 let queue = & exec. context . queue ;
498-
499- // TODO: Use texture pool to reuse existing unused textures instead of allocating fresh ones every time
500- let output_texture = device. create_texture ( & wgpu:: TextureDescriptor {
501- label : Some ( "viewport_output" ) ,
502- size : wgpu:: Extent3d {
503- width : output_resolution. x ,
504- height : output_resolution. y ,
505- depth_or_array_layers : 1 ,
506- } ,
507- mip_level_count : 1 ,
508- sample_count : 1 ,
509- dimension : wgpu:: TextureDimension :: D2 ,
510- format : wgpu:: TextureFormat :: Rgba8Unorm ,
511- usage : wgpu:: TextureUsages :: RENDER_ATTACHMENT | wgpu:: TextureUsages :: COPY_DST | wgpu:: TextureUsages :: COPY_SRC | wgpu:: TextureUsages :: TEXTURE_BINDING ,
512- view_formats : & [ ] ,
513- } ) ;
539+ let output_resolution = UVec2 :: new ( output_texture. width ( ) , output_texture. height ( ) ) ;
514540
515541 let mut encoder = device. create_command_encoder ( & wgpu:: CommandEncoderDescriptor { label : Some ( "composite" ) } ) ;
516542 let mut combined_metadata = rendering:: RenderMetadata :: default ( ) ;
@@ -570,5 +596,5 @@ fn composite_cached_regions(
570596 }
571597
572598 queue. submit ( [ encoder. finish ( ) ] ) ;
573- ( output_texture , combined_metadata)
599+ combined_metadata
574600}
0 commit comments