@@ -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<DirectXAtlasState>);
struct DirectXAtlasState {
device: ID3D11Device,
device_context: ID3D11DeviceContext,
- monochrome_textures: Vec<DirectXAtlasTexture>,
- polychrome_textures: Vec<DirectXAtlasTexture>,
- // path_textures: Vec<DirectXAtlasTexture>,
+ monochrome_textures: AtlasTextureList<DirectXAtlasTexture>,
+ polychrome_textures: AtlasTextureList<DirectXAtlasTexture>,
tiles_by_key: FxHashMap<AtlasKey, AtlasTile>,
}
@@ -30,8 +30,8 @@ struct DirectXAtlasTexture {
bytes_per_pixel: u32,
allocator: BucketedAtlasAllocator,
texture: ID3D11Texture2D,
- rtv: [Option<ID3D11RenderTargetView>; 1],
view: [Option<ID3D11ShaderResourceView>; 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<f32>, [Option<ID3D11RenderTargetView>; 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<DevicePixels>,
texture_kind: AtlasTextureKind,
) -> Option<AtlasTile> {
- 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<ID3D11RenderTargetView> = 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
+ }
}