Implement initial Unity-style asset library cache

This commit is contained in:
2026-04-02 03:03:36 +08:00
parent 619856ab22
commit 4c167bec0e
29 changed files with 4818 additions and 73 deletions

View File

@@ -1,6 +1,7 @@
#include <XCEngine/Core/Asset/ResourceManager.h>
#include <XCEngine/Core/Asset/ResourceHandle.h>
#include <XCEngine/Core/Asset/ResourceTypes.h>
#include <XCEngine/Core/IO/ResourceFileSystem.h>
#include <XCEngine/Resources/Material/MaterialLoader.h>
#include <XCEngine/Resources/Mesh/MeshLoader.h>
#include <XCEngine/Resources/Shader/ShaderLoader.h>
@@ -31,6 +32,10 @@ ResourceManager& ResourceManager::Get() {
}
void ResourceManager::Initialize() {
if (m_asyncLoader) {
return;
}
m_asyncLoader = Core::MakeUnique<AsyncLoader>();
m_asyncLoader->Initialize(2);
@@ -42,12 +47,23 @@ void ResourceManager::Initialize() {
void ResourceManager::Shutdown() {
UnloadAll();
m_asyncLoader->Shutdown();
m_asyncLoader.reset();
if (m_asyncLoader) {
m_asyncLoader->Shutdown();
m_asyncLoader.reset();
}
m_assetDatabase.Shutdown();
ResourceFileSystem::Get().Shutdown();
}
void ResourceManager::SetResourceRoot(const Containers::String& rootPath) {
m_resourceRoot = rootPath;
if (!m_resourceRoot.Empty()) {
ResourceFileSystem::Get().Initialize(rootPath);
m_assetDatabase.Initialize(rootPath);
} else {
ResourceFileSystem::Get().Shutdown();
m_assetDatabase.Shutdown();
}
}
const Containers::String& ResourceManager::GetResourceRoot() const {
@@ -111,7 +127,8 @@ IResource* ResourceManager::FindInCache(ResourceGUID guid) {
void ResourceManager::AddToCache(ResourceGUID guid, IResource* resource) {
std::lock_guard lock(m_mutex);
resource->m_guid = guid;
m_resourceCache.Insert(guid, resource);
m_memoryUsage += resource->GetMemorySize();
m_cache.Add(guid, resource);
@@ -128,6 +145,7 @@ void ResourceManager::Unload(ResourceGUID guid) {
if (it != nullptr) {
IResource* resource = *it;
m_resourceCache.Erase(guid);
m_guidToPath.Erase(guid);
m_memoryUsage -= resource->GetMemorySize();
resource->Release();
}
@@ -135,13 +153,16 @@ void ResourceManager::Unload(ResourceGUID guid) {
void ResourceManager::UnloadAll() {
std::lock_guard lock(m_mutex);
for (size_t i = 0; i < m_resourceCache.Size(); ++i) {
// This is a simplified approach - we'd need a way to iterate
// For now, just clear everything
const auto cachedResources = m_resourceCache.GetPairs();
for (const auto& pair : cachedResources) {
if (pair.second != nullptr) {
pair.second->Release();
}
}
m_resourceCache.Clear();
m_refCounts.Clear();
m_guidToPath.Clear();
m_memoryUsage = 0;
}
@@ -209,6 +230,10 @@ void ResourceManager::ReloadResource(ResourceGUID guid) {
if (pathIt == nullptr) {
return;
}
const Containers::String path = *pathIt;
auto* typeIt = m_resourceCache.Find(guid);
(void)typeIt;
}
Containers::Array<Containers::String> ResourceManager::GetResourcePaths() const {
@@ -226,11 +251,60 @@ void ResourceManager::UnloadGroup(const Containers::Array<ResourceGUID>& guids)
if (it != nullptr) {
IResource* resource = *it;
m_resourceCache.Erase(guid);
m_guidToPath.Erase(guid);
m_memoryUsage -= resource->GetMemorySize();
resource->Release();
}
}
}
void ResourceManager::RefreshAssetDatabase() {
if (!m_resourceRoot.Empty()) {
m_assetDatabase.Refresh();
}
}
bool ResourceManager::TryGetAssetRef(const Containers::String& path, ResourceType resourceType, AssetRef& outRef) const {
return m_assetDatabase.TryGetAssetRef(path, resourceType, outRef);
}
LoadResult ResourceManager::LoadResource(const Containers::String& path,
ResourceType type,
ImportSettings* settings) {
const ResourceGUID guid = ResourceGUID::Generate(path);
if (IResource* cached = FindInCache(guid)) {
return LoadResult(cached);
}
IResourceLoader* loader = FindLoader(type);
if (loader == nullptr) {
Debug::Logger::Get().Warning(Debug::LogCategory::FileSystem,
Containers::String("No loader found for resource type: ") +
GetResourceTypeName(type));
return LoadResult(false, "Loader not found");
}
Containers::String loadPath = path;
AssetDatabase::ResolvedAsset resolvedAsset;
if (!m_resourceRoot.Empty() &&
m_assetDatabase.EnsureArtifact(path, type, resolvedAsset) &&
resolvedAsset.artifactReady) {
loadPath = resolvedAsset.artifactMainPath;
}
LoadResult result = loader->Load(loadPath, settings);
if (!result || result.resource == nullptr) {
Debug::Logger::Get().Error(Debug::LogCategory::FileSystem,
Containers::String("Failed to load resource: ") + path + " - " + result.errorMessage);
return result;
}
result.resource->m_path = path;
AddToCache(guid, result.resource);
m_guidToPath.Insert(guid, path);
return result;
}
} // namespace Resources
} // namespace XCEngine