#include "StdAfx.h" #include "TextureCache.h" CTextureCache::CTextureCache(size_t maxMemoryMB) : m_maxMemory(maxMemoryMB * 1024 * 1024) , m_currentMemory(0) , m_hits(0) , m_misses(0) { } CTextureCache::~CTextureCache() { Clear(); } bool CTextureCache::Get(const std::string& filename, TCachedTexture& outTexture) { std::lock_guard lock(m_mutex); auto it = m_cache.find(filename); if (it == m_cache.end()) { m_misses.fetch_add(1); return false; } // Move to back of LRU (most recently used) m_lruList.erase(it->second.second); m_lruList.push_back(filename); it->second.second = std::prev(m_lruList.end()); // Copy texture data outTexture = it->second.first; m_hits.fetch_add(1); return true; } void CTextureCache::Put(const std::string& filename, const TCachedTexture& texture) { std::lock_guard lock(m_mutex); // Check if already cached auto it = m_cache.find(filename); if (it != m_cache.end()) { // Update existing entry m_currentMemory -= it->second.first.memorySize; m_lruList.erase(it->second.second); m_cache.erase(it); } // Evict if needed while (m_currentMemory + texture.memorySize > m_maxMemory && !m_cache.empty()) { Evict(); } // Don't cache if too large if (texture.memorySize > m_maxMemory / 4) { return; // Skip caching huge textures } // Add to cache m_lruList.push_back(filename); auto lruIt = std::prev(m_lruList.end()); m_cache[filename] = {texture, lruIt}; m_currentMemory += texture.memorySize; } void CTextureCache::Clear() { std::lock_guard lock(m_mutex); m_cache.clear(); m_lruList.clear(); m_currentMemory = 0; } float CTextureCache::GetHitRate() const { size_t hits = m_hits.load(); size_t misses = m_misses.load(); size_t total = hits + misses; if (total == 0) return 0.0f; return (float)hits / (float)total; } void CTextureCache::Evict() { // Remove least recently used (front of list) if (m_lruList.empty()) return; const std::string& filename = m_lruList.front(); auto it = m_cache.find(filename); if (it != m_cache.end()) { m_currentMemory -= it->second.first.memorySize; m_cache.erase(it); } m_lruList.pop_front(); }