Added SHResourceManager and Generic Handle #104

Merged
Pycorax merged 3 commits from SP3-13-ResourceManager into main 2022-10-21 17:11:51 +08:00
3 changed files with 118 additions and 27 deletions
Showing only changes of commit e5628fbed8 - Show all commits

View File

@ -21,6 +21,7 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHResourceHub SHResourceManager::resourceHub; SHResourceHub SHResourceManager::resourceHub;
std::unordered_map<std::type_index, std::unordered_map<AssetID, Handle<void>>> SHResourceManager::handlesMap; std::unordered_map<std::type_index, std::unordered_map<AssetID, Handle<void>>> SHResourceManager::handlesMap;
std::unordered_map<std::type_index, SHADE::SHResourceManager::HandleAssetMap> SHResourceManager::assetIdMap;
std::unordered_map<std::type_index, std::function<void(AssetID)>> SHResourceManager::typedFreeFuncMap; std::unordered_map<std::type_index, std::function<void(AssetID)>> SHResourceManager::typedFreeFuncMap;
std::vector<AssetID> SHResourceManager::loadedAssetData; std::vector<AssetID> SHResourceManager::loadedAssetData;
@ -30,30 +31,65 @@ namespace SHADE
void SHResourceManager::Unload(AssetID assetId) void SHResourceManager::Unload(AssetID assetId)
{ {
// Search each library for the asset ID and try to free it // Search each library for the asset ID and try to free it
Handle handle;
for (auto& typedHandleMap : handlesMap) for (auto& typedHandleMap : handlesMap)
{ {
if (typedHandleMap.second.contains(assetId)) if (typedHandleMap.second.contains(assetId))
{ {
// Save handle for later
handle = typedHandleMap.second[assetId];
// Dispose // Dispose
typedFreeFuncMap[typedHandleMap.first](assetId); typedFreeFuncMap[typedHandleMap.first](assetId);
typedHandleMap.second.erase(assetId); typedHandleMap.second.erase(assetId);
} }
} }
// No handles were found
if (!handle)
return;
for (auto& typedAssetIdsMap : assetIdMap)
{
if (typedAssetIdsMap.second.contains(handle))
{
// Dispose
typedAssetIdsMap.second.erase(handle);
}
}
} }
void SHResourceManager::FinaliseChanges() void SHResourceManager::FinaliseChanges()
{ {
SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>(); SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
if (gfxSystem == nullptr) if (gfxSystem == nullptr)
throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed."); throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed.");
gfxSystem->BuildMeshBuffers(); gfxSystem->BuildMeshBuffers();
gfxSystem->BuildTextures(); gfxSystem->BuildTextures();
// Free CPU Resources // Free CPU Resources
for (auto assetId : loadedAssetData) for (auto assetId : loadedAssetData)
{
SHAssetManager::Unload(assetId);
}
loadedAssetData.clear();
}
/*-----------------------------------------------------------------------------------*/
/* Query Functions */
/*-----------------------------------------------------------------------------------*/
std::optional<AssetID> SHResourceManager::GetAssetID(Handle<void> handle)
{
const Handle GENERIC_HANDLE = Handle(handle);
// Search each library for the asset ID and try to free it
for (auto& typedAssetIdsMap : assetIdMap)
{
if (typedAssetIdsMap.second.contains(GENERIC_HANDLE))
{ {
SHAssetManager::Unload(assetId); return typedAssetIdsMap.second[GENERIC_HANDLE];
} }
loadedAssetData.clear(); }
return {};
} }
} }

View File

@ -65,11 +65,41 @@ namespace SHADE
/// </summary> /// </summary>
static void FinaliseChanges(); static void FinaliseChanges();
/*---------------------------------------------------------------------------------*/
/* Query Functions */
/*---------------------------------------------------------------------------------*/
/// <summary>
/// Retrieves the AssetID associated with a specified Handle.
/// Faster than the untemplated version.
/// </summary>
/// <typeparam name="ResourceType">Type of resource to get the ID of.</typeparam>
/// <param name="handle">Handle to get the AssetID of.</param>
/// <return>
/// AssetID for the specified Handle. If the Handle is invalid, there will be no
/// value.
/// </return>
template<typename T>
static std::optional<AssetID> GetAssetID(Handle<T> handle);
/// <summary>
/// Retrieves the AssetID associated with a specified Handle.
/// Compared to the templated version, this function is slower as it requires
/// searching through the storage of all resource types.
/// </summary>
/// <param name="handle">Handle to get the AssetID of.</param>
/// <return>
/// AssetID for the specified Handle. If the Handle is invalid, there will be no
/// value.
/// </return>
static std::optional<AssetID> GetAssetID(Handle<void> handle);
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
using AssetHandleMap = std::unordered_map<AssetID, Handle<void>>; using AssetHandleMap = std::unordered_map<AssetID, Handle<void>>;
using HandleAssetMap = std::unordered_map<Handle<void>, AssetID>;
using AssetHandleMapRef = std::reference_wrapper<AssetHandleMap>;
using HandleAssetMapRef = std::reference_wrapper<HandleAssetMap>;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
@ -77,6 +107,7 @@ namespace SHADE
// Handles // Handles
static SHResourceHub resourceHub; static SHResourceHub resourceHub;
static std::unordered_map<std::type_index, AssetHandleMap> handlesMap; static std::unordered_map<std::type_index, AssetHandleMap> handlesMap;
static std::unordered_map<std::type_index, HandleAssetMap> assetIdMap;
static std::unordered_map<std::type_index, std::function<void(AssetID)>> typedFreeFuncMap; static std::unordered_map<std::type_index, std::function<void(AssetID)>> typedFreeFuncMap;
// Pointers to temp CPU resources // Pointers to temp CPU resources
static std::vector<AssetID> loadedAssetData; static std::vector<AssetID> loadedAssetData;
@ -92,7 +123,7 @@ namespace SHADE
/// </typeparam> /// </typeparam>
/// <returns>Reference to the AssetHandleMap of the specified type.</returns> /// <returns>Reference to the AssetHandleMap of the specified type.</returns>
template<typename ResourceType> template<typename ResourceType>
static AssetHandleMap& getAssetHandleMap(); static std::pair<AssetHandleMapRef, HandleAssetMapRef> getAssetHandleMap();
}; };
} }

View File

@ -34,9 +34,9 @@ namespace SHADE
} }
/* Attempt to get existing loaded asset */ /* Attempt to get existing loaded asset */
AssetHandleMap& typedHandleMap = getAssetHandleMap<ResourceType>(); auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap<ResourceType>();
if (typedHandleMap.contains(assetId)) if (typedHandleMap.get().contains(assetId))
return Handle<ResourceType>(typedHandleMap[assetId]); return Handle<ResourceType>(typedHandleMap.get()[assetId]);
/* Otherwise, we need to load it! */ /* Otherwise, we need to load it! */
// Meshes // Meshes
@ -66,7 +66,9 @@ namespace SHADE
assetData->indices.size(), assetData->indices.size(),
assetData->indices.data() assetData->indices.data()
); );
typedHandleMap.emplace(assetId, Handle(meshHandle)); Handle genericHandle = Handle(meshHandle);
typedHandleMap.get().emplace(assetId, genericHandle);
typedAssetIdMap.get().emplace(genericHandle, assetId);
return meshHandle; return meshHandle;
} }
// Textures // Textures
@ -95,7 +97,7 @@ namespace SHADE
assetData->format, assetData->format,
assetData->mipOffsets assetData->mipOffsets
); );
typedHandleMap.emplace(assetId, Handle(texHandle)); typedHandleMap.get().emplace(assetId, Handle(texHandle));
return texHandle; return texHandle;
} }
} }
@ -103,19 +105,22 @@ namespace SHADE
template<typename ResourceType> template<typename ResourceType>
void SHResourceManager::Unload(Handle<ResourceType> assetId) void SHResourceManager::Unload(Handle<ResourceType> assetId)
{ {
// Check if it is an usupported type // Check if it is an unsupported type
if (!std::is_same_v<ResourceType, SHMesh> && !std::is_same_v<ResourceType, SHTexture>) if (!std::is_same_v<ResourceType, SHMesh> && !std::is_same_v<ResourceType, SHTexture>)
{ {
static_assert(true, "Unsupported Resource Type specified for SHResourceManager."); static_assert(true, "Unsupported Resource Type specified for SHResourceManager.");
} }
/* Attempt to get existing loaded asset */ /* Attempt to get existing loaded asset */
AssetHandleMap& typedHandleMap = getAssetHandleMap<ResourceType>(); auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap<ResourceType>();
if (typedHandleMap.contains(assetId)) if (typedHandleMap.get().contains(assetId))
{ {
// Dispose // Dispose
static_cast<Handle<ResourceType>>(typedHandleMap[assetId]).Free(); Handle handle = typedHandleMap.get()[assetId];
typedHandleMap.erase(assetId); Handle<ResourceType> typedHandle = static_cast<Handle<ResourceType>>(handle);
typedHandle.Free();
typedAssetIdMap.get().erase(handle);
typedHandleMap.get().erase(assetId);
} }
else else
{ {
@ -124,24 +129,43 @@ namespace SHADE
} }
} }
/*-----------------------------------------------------------------------------------*/
/* Query Functions */
/*-----------------------------------------------------------------------------------*/
template<typename T>
static std::optional<AssetID> SHResourceManager::GetAssetID(Handle<T> handle)
{
const Handle GENERIC_HANDLE = Handle(handle);
auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap<T>();
if (typedAssetIdMap.get().contains(GENERIC_HANDLE))
{
return typedAssetIdMap.GetId()[GENERIC_HANDLE];
}
return {};
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
template<typename ResourceType> template<typename ResourceType>
SHResourceManager::AssetHandleMap& SHResourceManager::getAssetHandleMap() std::pair<SHResourceManager::AssetHandleMapRef, SHResourceManager::HandleAssetMapRef> SHResourceManager::getAssetHandleMap()
{ {
if (!handlesMap.contains(typeid(ResourceType))) const std::type_index TYPE = typeid(ResourceType);
if (!handlesMap.contains(TYPE))
{ {
handlesMap.emplace(typeid(ResourceType), AssetHandleMap{}); handlesMap.emplace(TYPE, AssetHandleMap{});
assetIdMap.emplace(TYPE, HandleAssetMap{});
typedFreeFuncMap.emplace typedFreeFuncMap.emplace
( (
typeid(ResourceType), TYPE,
[](AssetID assetId) [TYPE](AssetID assetId)
{ {
static_cast<Handle<ResourceType>>(SHResourceManager::handlesMap[typeid(ResourceType)][assetId]).Free(); static_cast<Handle<ResourceType>>(SHResourceManager::handlesMap[TYPE][assetId]).Free();
} }
); );
} }
return handlesMap[typeid(ResourceType)]; return std::make_pair(std::ref(handlesMap[TYPE]), std::ref(assetIdMap[TYPE]));
} }
} }