From ea5f122f78fd5001e0e3612eaeb66c72322bd7ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Wed, 8 Feb 2023 21:21:54 +0100 Subject: [PATCH] Remove potentially huge `texture_pending` from `InnerAtlas` Instead, issue a `write_texture` for every glyph that isn't present in the atlas. I think this should be fine, since cache eviction should be rare and, therefore, uploads will be too. The result here is lower memory usage for bigger caches. --- src/text_atlas.rs | 11 +---- src/text_render.rs | 110 +++++++++++---------------------------------- 2 files changed, 26 insertions(+), 95 deletions(-) diff --git a/src/text_atlas.rs b/src/text_atlas.rs index 075cff0..526ff17 100644 --- a/src/text_atlas.rs +++ b/src/text_atlas.rs @@ -13,8 +13,8 @@ use wgpu::{ TextureViewDescriptor, TextureViewDimension, VertexFormat, VertexState, }; +#[allow(dead_code)] pub(crate) struct InnerAtlas { - pub texture_pending: Vec, pub texture: Texture, pub texture_view: TextureView, pub packer: BucketedAtlasAllocator, @@ -33,7 +33,6 @@ impl InnerAtlas { let packer = BucketedAtlasAllocator::new(size2(width as i32, height as i32)); // Create a texture to use for our atlas - let texture_pending = vec![0; (width * height) as usize * num_atlas_channels]; let texture = device.create_texture(&TextureDescriptor { label: Some("glyphon atlas"), size: Extent3d { @@ -57,7 +56,6 @@ impl InnerAtlas { let glyph_cache = LruCache::unbounded(); Self { - texture_pending, texture, texture_view, packer, @@ -273,13 +271,6 @@ impl TextAtlas { .or_else(|| self.color_atlas.glyph_cache.peek(glyph)) } - pub(crate) fn inner_for_content(&self, content_type: ContentType) -> &InnerAtlas { - match content_type { - ContentType::Color => &self.color_atlas, - ContentType::Mask => &self.mask_atlas, - } - } - pub(crate) fn inner_for_content_mut(&mut self, content_type: ContentType) -> &mut InnerAtlas { match content_type { ContentType::Color => &mut self.color_atlas, diff --git a/src/text_render.rs b/src/text_render.rs index aa9b583..b87abb5 100644 --- a/src/text_render.rs +++ b/src/text_render.rs @@ -87,23 +87,6 @@ impl TextRenderer { }); } - struct UploadBounds { - x_min: usize, - x_max: usize, - y_min: usize, - y_max: usize, - } - - struct BoundsPerAtlas { - color: Option, - mask: Option, - } - - let mut upload_bounds_per_atlas = BoundsPerAtlas { - color: None, - mask: None, - }; - self.glyphs_in_use.clear(); for text_area in text_areas.iter() { @@ -146,41 +129,32 @@ impl TextRenderer { None => return Err(PrepareError::AtlasFull), }; let atlas_min = allocation.rectangle.min; - let atlas_max = allocation.rectangle.max; - for row in 0..height { - let y_offset = atlas_min.y as usize; - let x_offset = - (y_offset + row) * inner.width as usize + atlas_min.x as usize; - let num_atlas_channels = inner.num_atlas_channels; - let bitmap_row = &image.data[row * width * num_atlas_channels - ..(row + 1) * width * num_atlas_channels]; - inner.texture_pending[x_offset * num_atlas_channels - ..(x_offset + width) * num_atlas_channels] - .copy_from_slice(bitmap_row); - } - - let upload_bounds = match content_type { - ContentType::Color => &mut upload_bounds_per_atlas.color, - ContentType::Mask => &mut upload_bounds_per_atlas.mask, - }; - - match upload_bounds.as_mut() { - Some(ub) => { - ub.x_min = ub.x_min.min(atlas_min.x as usize); - ub.x_max = ub.x_max.max(atlas_max.x as usize); - ub.y_min = ub.y_min.min(atlas_min.y as usize); - ub.y_max = ub.y_max.max(atlas_max.y as usize); - } - None => { - *upload_bounds = Some(UploadBounds { - x_min: atlas_min.x as usize, - x_max: atlas_max.x as usize, - y_min: atlas_min.y as usize, - y_max: atlas_max.y as usize, - }); - } - } + queue.write_texture( + ImageCopyTexture { + texture: &inner.texture, + mip_level: 0, + origin: Origin3d { + x: atlas_min.x as u32, + y: atlas_min.y as u32, + z: 0, + }, + aspect: TextureAspect::All, + }, + &image.data, + ImageDataLayout { + offset: 0, + bytes_per_row: NonZeroU32::new( + width as u32 * inner.num_atlas_channels as u32, + ), + rows_per_image: None, + }, + Extent3d { + width: width as u32, + height: height as u32, + depth_or_array_layers: 1, + }, + ); ( GpuCacheStatus::InAtlas { @@ -213,40 +187,6 @@ impl TextRenderer { } } - for (content_type, bounds) in [ - (ContentType::Color, upload_bounds_per_atlas.color), - (ContentType::Mask, upload_bounds_per_atlas.mask), - ] { - if let Some(ub) = bounds { - let inner = atlas.inner_for_content(content_type); - let num_atlas_channels = inner.num_atlas_channels; - queue.write_texture( - ImageCopyTexture { - texture: &inner.texture, - mip_level: 0, - origin: Origin3d { - x: ub.x_min as u32, - y: ub.y_min as u32, - z: 0, - }, - aspect: TextureAspect::All, - }, - &inner.texture_pending - [ub.y_min * inner.width as usize + ub.x_min * num_atlas_channels..], - ImageDataLayout { - offset: 0, - bytes_per_row: NonZeroU32::new(inner.width * num_atlas_channels as u32), - rows_per_image: NonZeroU32::new(inner.height), - }, - Extent3d { - width: (ub.x_max - ub.x_min) as u32, - height: (ub.y_max - ub.y_min) as u32, - depth_or_array_layers: 1, - }, - ); - } - } - let mut glyph_vertices: Vec = Vec::new(); let mut glyph_indices: Vec = Vec::new(); let mut glyphs_added = 0;