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;
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::vector<AssetID> SHResourceManager::loadedAssetData;
@ -30,30 +31,65 @@ namespace SHADE
void SHResourceManager::Unload(AssetID assetId)
{
// Search each library for the asset ID and try to free it
Handle handle;
for (auto& typedHandleMap : handlesMap)
{
if (typedHandleMap.second.contains(assetId))
{
// Save handle for later
handle = typedHandleMap.second[assetId];
// Dispose
typedFreeFuncMap[typedHandleMap.first](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()
{
SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
if (gfxSystem == nullptr)
throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed.");
gfxSystem->BuildMeshBuffers();
gfxSystem->BuildTextures();
SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
if (gfxSystem == nullptr)
throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed.");
gfxSystem->BuildMeshBuffers();
gfxSystem->BuildTextures();
// Free CPU Resources
for (auto assetId : loadedAssetData)
// Free CPU Resources
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>
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:
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
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 */
@ -77,6 +107,7 @@ namespace SHADE
// Handles
static SHResourceHub resourceHub;
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;
// Pointers to temp CPU resources
static std::vector<AssetID> loadedAssetData;
@ -92,7 +123,7 @@ namespace SHADE
/// </typeparam>
/// <returns>Reference to the AssetHandleMap of the specified type.</returns>
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 */
AssetHandleMap& typedHandleMap = getAssetHandleMap<ResourceType>();
if (typedHandleMap.contains(assetId))
return Handle<ResourceType>(typedHandleMap[assetId]);
auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap<ResourceType>();
if (typedHandleMap.get().contains(assetId))
return Handle<ResourceType>(typedHandleMap.get()[assetId]);
/* Otherwise, we need to load it! */
// Meshes
@ -66,7 +66,9 @@ namespace SHADE
assetData->indices.size(),
assetData->indices.data()
);
typedHandleMap.emplace(assetId, Handle(meshHandle));
Handle genericHandle = Handle(meshHandle);
typedHandleMap.get().emplace(assetId, genericHandle);
typedAssetIdMap.get().emplace(genericHandle, assetId);
return meshHandle;
}
// Textures
@ -95,7 +97,7 @@ namespace SHADE
assetData->format,
assetData->mipOffsets
);
typedHandleMap.emplace(assetId, Handle(texHandle));
typedHandleMap.get().emplace(assetId, Handle(texHandle));
return texHandle;
}
}
@ -103,19 +105,22 @@ namespace SHADE
template<typename ResourceType>
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>)
{
static_assert(true, "Unsupported Resource Type specified for SHResourceManager.");
}
/* Attempt to get existing loaded asset */
AssetHandleMap& typedHandleMap = getAssetHandleMap<ResourceType>();
if (typedHandleMap.contains(assetId))
auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap<ResourceType>();
if (typedHandleMap.get().contains(assetId))
{
// Dispose
static_cast<Handle<ResourceType>>(typedHandleMap[assetId]).Free();
typedHandleMap.erase(assetId);
Handle handle = typedHandleMap.get()[assetId];
Handle<ResourceType> typedHandle = static_cast<Handle<ResourceType>>(handle);
typedHandle.Free();
typedAssetIdMap.get().erase(handle);
typedHandleMap.get().erase(assetId);
}
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 */
/*-----------------------------------------------------------------------------------*/
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
(
typeid(ResourceType),
[](AssetID assetId)
TYPE,
[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]));
}
}