diff --git a/crates/gpui_wgpu/src/wgpu_atlas.rs b/crates/gpui_wgpu/src/wgpu_atlas.rs index 4c2c6ab601442fbebabd6759c5111d5e852b509f..71a93d524a013b304cf1d5e0266b6038b29413ac 100644 --- a/crates/gpui_wgpu/src/wgpu_atlas.rs +++ b/crates/gpui_wgpu/src/wgpu_atlas.rs @@ -112,7 +112,7 @@ impl PlatformAtlas for WgpuAtlas { let tile = lock .allocate(size, key.texture_kind()) .context("failed to allocate")?; - lock.upload_texture(tile.texture_id, tile.bounds, &bytes); + lock.upload_texture(tile.texture_id, tile.bounds, bytes); lock.tiles_by_key.insert(key.clone(), tile.clone()); Ok(Some(tile)) } @@ -236,15 +236,17 @@ impl WgpuAtlasState { } } - fn upload_texture(&mut self, id: AtlasTextureId, bounds: Bounds, bytes: &[u8]) { - let data = self - .storage - .get(id) - .map(|texture| swizzle_upload_data(bytes, texture.format)) - .unwrap_or_else(|| bytes.to_vec()); - - self.pending_uploads - .push(PendingUpload { id, bounds, data }); + fn upload_texture( + &mut self, + id: AtlasTextureId, + bounds: Bounds, + bytes: Cow<'_, [u8]>, + ) { + if let Some(texture) = self.storage.get(id) { + let data = swizzle_upload_data(bytes, texture.format); + self.pending_uploads + .push(PendingUpload { id, bounds, data }); + } } fn flush_uploads(&mut self) { @@ -374,16 +376,21 @@ impl WgpuAtlasTexture { } } -fn swizzle_upload_data(bytes: &[u8], format: wgpu::TextureFormat) -> Vec { +fn swizzle_upload_data(bytes: Cow<'_, [u8]>, format: wgpu::TextureFormat) -> Vec { match format { wgpu::TextureFormat::Rgba8Unorm => { - let mut data = bytes.to_vec(); + debug_assert_eq!( + bytes.len() % 4, + 0, + "upload data must be a multiple of 4 bytes" + ); + let mut data = bytes.into_owned(); for pixel in data.chunks_exact_mut(4) { pixel.swap(0, 2); } data } - _ => bytes.to_vec(), + _ => bytes.into_owned(), } } @@ -456,7 +463,7 @@ mod tests { fn swizzle_upload_data_preserves_bgra_uploads() { let input = vec![0x10, 0x20, 0x30, 0x40]; assert_eq!( - swizzle_upload_data(&input, wgpu::TextureFormat::Bgra8Unorm), + swizzle_upload_data(Cow::Borrowed(&input), wgpu::TextureFormat::Bgra8Unorm), input ); } @@ -465,7 +472,7 @@ mod tests { fn swizzle_upload_data_converts_bgra_to_rgba() { let input = vec![0x10, 0x20, 0x30, 0x40, 0xAA, 0xBB, 0xCC, 0xDD]; assert_eq!( - swizzle_upload_data(&input, wgpu::TextureFormat::Rgba8Unorm), + swizzle_upload_data(Cow::Borrowed(&input), wgpu::TextureFormat::Rgba8Unorm), vec![0x30, 0x20, 0x10, 0x40, 0xCC, 0xBB, 0xAA, 0xDD] ); }