diff --git a/crates/gpui/src/platform/linux/blade_atlas.rs b/crates/gpui/src/platform/linux/blade_atlas.rs index 7f27bf68a4..6f5b3da255 100644 --- a/crates/gpui/src/platform/linux/blade_atlas.rs +++ b/crates/gpui/src/platform/linux/blade_atlas.rs @@ -14,14 +14,20 @@ pub(crate) const PATH_TEXTURE_FORMAT: gpu::TextureFormat = gpu::TextureFormat::R pub(crate) struct BladeAtlas(Mutex); +struct PendingUpload { + id: AtlasTextureId, + bounds: Bounds, + data: gpu::BufferPiece, +} + struct BladeAtlasState { gpu: Arc, - gpu_encoder: gpu::CommandEncoder, upload_belt: BladeBelt, monochrome_textures: Vec, polychrome_textures: Vec, path_textures: Vec, tiles_by_key: FxHashMap, + uploads: Vec, } impl BladeAtlasState { @@ -36,7 +42,6 @@ impl BladeAtlasState { self.gpu.destroy_texture(texture.raw); self.gpu.destroy_texture_view(texture.raw_view.unwrap()); } - self.gpu.destroy_command_encoder(&mut self.gpu_encoder); self.upload_belt.destroy(&self.gpu); } } @@ -50,10 +55,6 @@ impl BladeAtlas { pub(crate) fn new(gpu: &Arc) -> Self { BladeAtlas(Mutex::new(BladeAtlasState { gpu: Arc::clone(gpu), - gpu_encoder: gpu.create_command_encoder(gpu::CommandEncoderDesc { - name: "atlas", - buffer_count: 3, - }), upload_belt: BladeBelt::new(BladeBeltDescriptor { memory: gpu::Memory::Upload, min_chunk_size: 0x10000, @@ -62,6 +63,7 @@ impl BladeAtlas { polychrome_textures: Default::default(), path_textures: Default::default(), tiles_by_key: Default::default(), + uploads: Vec::new(), })) } @@ -81,22 +83,19 @@ impl BladeAtlas { } } - pub fn start_frame(&self) { - let mut lock = self.0.lock(); - lock.gpu_encoder.start(); - } - pub fn allocate(&self, size: Size, texture_kind: AtlasTextureKind) -> AtlasTile { let mut lock = self.0.lock(); lock.allocate(size, texture_kind) } - pub fn finish_frame(&self) -> gpu::SyncPoint { + pub fn before_frame(&self, gpu_encoder: &mut gpu::CommandEncoder) { let mut lock = self.0.lock(); - let gpu = lock.gpu.clone(); - let sync_point = gpu.submit(&mut lock.gpu_encoder); - lock.upload_belt.flush(&sync_point); - sync_point + lock.flush(gpu_encoder.transfer()); + } + + pub fn after_frame(&self, sync_point: &gpu::SyncPoint) { + let mut lock = self.0.lock(); + lock.upload_belt.flush(sync_point); } pub fn get_texture_info(&self, id: AtlasTextureId) -> BladeTextureInfo { @@ -186,7 +185,7 @@ impl BladeAtlasState { } let raw = self.gpu.create_texture(gpu::TextureDesc { - name: "", + name: "atlas", format, size: gpu::Extent { width: size.width.into(), @@ -230,31 +229,39 @@ impl BladeAtlasState { } fn upload_texture(&mut self, id: AtlasTextureId, bounds: Bounds, bytes: &[u8]) { - let textures = match id.kind { - crate::AtlasTextureKind::Monochrome => &self.monochrome_textures, - crate::AtlasTextureKind::Polychrome => &self.polychrome_textures, - crate::AtlasTextureKind::Path => &self.path_textures, - }; - let texture = &textures[id.index as usize]; + let data = self.upload_belt.alloc_data(bytes, &self.gpu); + self.uploads.push(PendingUpload { id, bounds, data }); + } - let src_data = self.upload_belt.alloc_data(bytes, &self.gpu); + fn flush(&mut self, mut transfers: gpu::TransferCommandEncoder) { + for upload in self.uploads.drain(..) { + let textures = match upload.id.kind { + crate::AtlasTextureKind::Monochrome => &self.monochrome_textures, + crate::AtlasTextureKind::Polychrome => &self.polychrome_textures, + crate::AtlasTextureKind::Path => &self.path_textures, + }; + let texture = &textures[upload.id.index as usize]; - let mut transfers = self.gpu_encoder.transfer(); - transfers.copy_buffer_to_texture( - src_data, - bounds.size.width.to_bytes(texture.bytes_per_pixel()), - gpu::TexturePiece { - texture: texture.raw, - mip_level: 0, - array_layer: 0, - origin: [bounds.origin.x.into(), bounds.origin.y.into(), 0], - }, - gpu::Extent { - width: bounds.size.width.into(), - height: bounds.size.height.into(), - depth: 1, - }, - ); + transfers.copy_buffer_to_texture( + upload.data, + upload.bounds.size.width.to_bytes(texture.bytes_per_pixel()), + gpu::TexturePiece { + texture: texture.raw, + mip_level: 0, + array_layer: 0, + origin: [ + upload.bounds.origin.x.into(), + upload.bounds.origin.y.into(), + 0, + ], + }, + gpu::Extent { + width: upload.bounds.size.width.into(), + height: upload.bounds.size.height.into(), + depth: 1, + }, + ); + } } } diff --git a/crates/gpui/src/platform/linux/blade_renderer.rs b/crates/gpui/src/platform/linux/blade_renderer.rs index 4d64b184f0..184b607ca6 100644 --- a/crates/gpui/src/platform/linux/blade_renderer.rs +++ b/crates/gpui/src/platform/linux/blade_renderer.rs @@ -285,6 +285,7 @@ impl BladeRenderer { self.command_encoder.start(); self.command_encoder.init_texture(frame.texture()); + self.atlas.before_frame(&mut self.command_encoder); self.rasterize_paths(scene.paths()); let globals = GlobalParams { @@ -365,7 +366,11 @@ impl BladeRenderer { self.command_encoder.present(frame); let sync_point = self.gpu.submit(&mut self.command_encoder); + self.instance_belt.flush(&sync_point); + self.atlas.after_frame(&sync_point); + self.atlas.clear_textures(AtlasTextureKind::Path); + self.wait_for_gpu(); self.last_sync_point = Some(sync_point); } diff --git a/crates/gpui/src/platform/linux/window.rs b/crates/gpui/src/platform/linux/window.rs index 3efade0c89..4e136da3d6 100644 --- a/crates/gpui/src/platform/linux/window.rs +++ b/crates/gpui/src/platform/linux/window.rs @@ -244,7 +244,7 @@ impl LinuxWindowState { pub fn configure(&self, bounds: Bounds) { let mut resize_args = None; - let mut do_move = false; + let do_move; { let mut inner = self.inner.lock(); let old_bounds = mem::replace(&mut inner.bounds, bounds); @@ -393,7 +393,7 @@ impl PlatformWindow for LinuxWindow { } fn sprite_atlas(&self) -> sync::Arc { - let mut inner = self.0.inner.lock(); + let inner = self.0.inner.lock(); inner.renderer.atlas().clone() } }