use std::collections::HashMap;
use std::sync::Arc;
use wgpu::{Device, Queue, Texture, TextureView, Sampler};
use image::DynamicImage;
use crate::runtime::{AssetManager, AssetResult};
use super::texture::{create_texture_from_image, create_placeholder_texture};
pub struct CachedTexture {
pub texture: Texture,
pub view: TextureView,
pub sampler: Sampler,
}
impl CachedTexture {
pub fn from_image(image: &DynamicImage, device: &Device, queue: &Queue) -> AssetResult<Self> {
let texture = create_texture_from_image(device, queue, image)?;
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
label: Some("Texture Sampler"),
address_mode_u: wgpu::AddressMode::ClampToEdge,
address_mode_v: wgpu::AddressMode::ClampToEdge,
address_mode_w: wgpu::AddressMode::ClampToEdge,
mag_filter: wgpu::FilterMode::Linear,
min_filter: wgpu::FilterMode::Linear,
mipmap_filter: wgpu::FilterMode::Nearest,
..Default::default()
});
Ok(Self {
texture,
view,
sampler,
})
}
fn from_texture(texture: Texture, device: &Device) -> Self {
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
label: Some("Placeholder Sampler"),
..Default::default()
});
Self {
texture,
view,
sampler,
}
}
}
pub struct TextureCache {
cache: HashMap<String, CachedTexture>,
device: Arc<Device>,
queue: Arc<Queue>,
placeholder: CachedTexture,
}
impl TextureCache {
pub fn new(device: Arc<Device>, queue: Arc<Queue>) -> Self {
let placeholder_texture = create_placeholder_texture(&device, &queue, [255, 0, 255, 255]);
let placeholder = CachedTexture::from_texture(placeholder_texture, &device);
Self {
cache: HashMap::new(),
device,
queue,
placeholder,
}
}
pub fn get_or_load(
&mut self,
texture_path: &str,
asset_manager: &mut AssetManager,
) -> &CachedTexture {
if texture_path.is_empty() {
return &self.placeholder;
}
if self.cache.contains_key(texture_path) {
return &self.cache[texture_path];
}
let image = match asset_manager.load_image(texture_path) {
Ok(img) => img,
Err(e) => {
log::warn!("Failed to load image '{}': {}", texture_path, e);
return &self.placeholder;
}
};
let cached_texture = match CachedTexture::from_image(&image, &self.device, &self.queue) {
Ok(tex) => tex,
Err(e) => {
log::warn!("Failed to create texture '{}': {}", texture_path, e);
return &self.placeholder;
}
};
self.cache.insert(texture_path.to_string(), cached_texture);
log::info!("✅ 텍스처 GPU 업로드: {}", texture_path);
&self.cache[texture_path]
}
pub fn placeholder(&self) -> &CachedTexture {
&self.placeholder
}
pub fn clear(&mut self) {
self.cache.clear();
log::info!("TextureCache 초기화");
}
}