This commit is contained in:
Junkui Zhang 2025-07-14 14:24:47 +08:00
parent d0a2257472
commit 2319cd8211

View file

@ -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
}
}