diff --git a/crates/gpui/src/platform/windows/directx_atlas.rs b/crates/gpui/src/platform/windows/directx_atlas.rs index 3a5da33ae6..abd6e4ad40 100644 --- a/crates/gpui/src/platform/windows/directx_atlas.rs +++ b/crates/gpui/src/platform/windows/directx_atlas.rs @@ -3,25 +3,25 @@ use etagere::BucketedAtlasAllocator; use parking_lot::Mutex; use windows::Win32::Graphics::{ Direct3D11::{ - D3D11_BIND_RENDER_TARGET, D3D11_BIND_SHADER_RESOURCE, D3D11_BOX, D3D11_CPU_ACCESS_WRITE, - D3D11_TEXTURE2D_DESC, D3D11_USAGE_DEFAULT, ID3D11Device, ID3D11DeviceContext, - ID3D11RenderTargetView, ID3D11ShaderResourceView, ID3D11Texture2D, - }, - Dxgi::Common::{ - DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_R16_FLOAT, DXGI_SAMPLE_DESC, + D3D11_BIND_SHADER_RESOURCE, D3D11_BOX, D3D11_CPU_ACCESS_WRITE, D3D11_TEXTURE2D_DESC, + D3D11_USAGE_DEFAULT, ID3D11Device, ID3D11DeviceContext, ID3D11ShaderResourceView, + ID3D11Texture2D, }, + Dxgi::Common::{DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_SAMPLE_DESC}, }; -use crate::*; +use crate::{ + AtlasKey, AtlasTextureId, AtlasTextureKind, AtlasTile, Bounds, DevicePixels, PlatformAtlas, + Size, platform::AtlasTextureList, +}; pub(crate) struct DirectXAtlas(Mutex); struct DirectXAtlasState { device: ID3D11Device, device_context: ID3D11DeviceContext, - monochrome_textures: Vec, - polychrome_textures: Vec, - // path_textures: Vec, + monochrome_textures: AtlasTextureList, + polychrome_textures: AtlasTextureList, tiles_by_key: FxHashMap, } @@ -30,8 +30,8 @@ struct DirectXAtlasTexture { bytes_per_pixel: u32, allocator: BucketedAtlasAllocator, texture: ID3D11Texture2D, - rtv: [Option; 1], view: [Option; 1], + live_atlas_keys: u32, } impl DirectXAtlas { @@ -41,27 +41,10 @@ impl DirectXAtlas { device_context, monochrome_textures: Default::default(), polychrome_textures: Default::default(), - // path_textures: Default::default(), tiles_by_key: Default::default(), })) } - pub(crate) fn get_texture_drawing_info( - &self, - id: AtlasTextureId, - ) -> (Size, [Option; 1]) { - let lock = self.0.lock(); - let tex = lock.texture(id); - let size = tex.allocator.size(); - ( - Size { - width: size.width as f32, - height: size.height as f32, - }, - tex.rtv.clone(), - ) - } - pub(crate) fn get_texture_view( &self, id: AtlasTextureId, @@ -84,9 +67,8 @@ impl DirectXAtlas { let textures = match texture_kind { AtlasTextureKind::Monochrome => &mut lock.monochrome_textures, AtlasTextureKind::Polychrome => &mut lock.polychrome_textures, - // AtlasTextureKind::Path => &mut lock.path_textures, }; - for texture in textures { + for texture in textures.iter_mut() { texture.clear(); } } @@ -118,7 +100,30 @@ impl PlatformAtlas for DirectXAtlas { } fn remove(&self, key: &AtlasKey) { - todo!() + let mut lock = self.0.lock(); + + let Some(id) = lock.tiles_by_key.remove(key).map(|tile| tile.texture_id) else { + return; + }; + + let textures = match id.kind { + AtlasTextureKind::Monochrome => &mut lock.monochrome_textures, + AtlasTextureKind::Polychrome => &mut lock.polychrome_textures, + }; + + let Some(texture_slot) = textures.textures.get_mut(id.index as usize) else { + return; + }; + + if let Some(mut texture) = texture_slot.take() { + texture.decrement_ref_count(); + if texture.is_unreferenced() { + textures.free_list.push(texture.id.index as usize); + lock.tiles_by_key.remove(key); + } else { + *texture_slot = Some(texture); + } + } } } @@ -128,20 +133,23 @@ impl DirectXAtlasState { size: Size, texture_kind: AtlasTextureKind, ) -> Option { - let textures = match texture_kind { - AtlasTextureKind::Monochrome => &mut self.monochrome_textures, - AtlasTextureKind::Polychrome => &mut self.polychrome_textures, - // AtlasTextureKind::Path => &mut self.path_textures, - }; + { + let textures = match texture_kind { + AtlasTextureKind::Monochrome => &mut self.monochrome_textures, + AtlasTextureKind::Polychrome => &mut self.polychrome_textures, + }; - textures - .iter_mut() - .rev() - .find_map(|texture| texture.allocate(size)) - .or_else(|| { - let texture = self.push_texture(size, texture_kind); - texture.allocate(size) - }) + if let Some(tile) = textures + .iter_mut() + .rev() + .find_map(|texture| texture.allocate(size)) + { + return Some(tile); + } + } + + let texture = self.push_texture(size, texture_kind); + texture.allocate(size) } fn push_texture( @@ -173,11 +181,7 @@ impl DirectXAtlasState { pixel_format = DXGI_FORMAT_B8G8R8A8_UNORM; bind_flag = D3D11_BIND_SHADER_RESOURCE; bytes_per_pixel = 4; - } // AtlasTextureKind::Path => { - // pixel_format = DXGI_FORMAT_R16_FLOAT; - // bind_flag = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; - // bytes_per_pixel = 2; - // } + } } let texture_desc = D3D11_TEXTURE2D_DESC { Width: size.width.0 as u32, @@ -202,21 +206,11 @@ impl DirectXAtlasState { } let texture = texture.unwrap(); - let textures = match kind { + let texture_list = match kind { AtlasTextureKind::Monochrome => &mut self.monochrome_textures, AtlasTextureKind::Polychrome => &mut self.polychrome_textures, - // AtlasTextureKind::Path => &mut self.path_textures, - }; - let rtv = match kind { - // AtlasTextureKind::Path => unsafe { - // let mut view: Option = None; - // self.device - // .CreateRenderTargetView(&texture, None, Some(&mut view)) - // .unwrap(); - // [view] - // }, - _ => [None], }; + let index = texture_list.free_list.pop(); let view = unsafe { let mut view = None; self.device @@ -226,17 +220,22 @@ impl DirectXAtlasState { }; let atlas_texture = DirectXAtlasTexture { id: AtlasTextureId { - index: textures.len() as u32, + index: index.unwrap_or(texture_list.textures.len()) as u32, kind, }, bytes_per_pixel, allocator: etagere::BucketedAtlasAllocator::new(size.into()), texture, - rtv, view, + live_atlas_keys: 0, }; - textures.push(atlas_texture); - textures.last_mut().unwrap() + if let Some(ix) = index { + texture_list.textures[ix] = Some(atlas_texture); + texture_list.textures.get_mut(ix).unwrap().as_mut().unwrap() + } else { + texture_list.textures.push(Some(atlas_texture)); + texture_list.textures.last_mut().unwrap().as_mut().unwrap() + } } fn texture(&self, id: AtlasTextureId) -> &DirectXAtlasTexture { @@ -245,7 +244,7 @@ impl DirectXAtlasState { crate::AtlasTextureKind::Polychrome => &self.polychrome_textures, // crate::AtlasTextureKind::Path => &self.path_textures, }; - &textures[id.index as usize] + textures[id.index as usize].as_ref().unwrap() } } @@ -265,6 +264,7 @@ impl DirectXAtlasTexture { }, padding: 0, }; + self.live_atlas_keys += 1; Some(tile) } @@ -292,4 +292,12 @@ impl DirectXAtlasTexture { ); } } + + fn decrement_ref_count(&mut self) { + self.live_atlas_keys -= 1; + } + + fn is_unreferenced(&mut self) -> bool { + self.live_atlas_keys == 0 + } }