138 lines
3.7 KiB
C++
138 lines
3.7 KiB
C++
#pragma once
|
|
#include "DeerRender/Log.h"
|
|
#include "DeerRender/Tools/Memory.h"
|
|
#include "DeerRender/Tools/Path.h"
|
|
#include "DeerRender/Tools/TypeDefs.h"
|
|
|
|
#include <cxxabi.h>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
namespace Deer {
|
|
template <typename T>
|
|
class ResourceManager;
|
|
typedef uint32_t StorageType;
|
|
|
|
template <typename DataSource>
|
|
class StorageBackend {
|
|
public:
|
|
template <typename T>
|
|
static Scope<T> load(StorageType storageId);
|
|
};
|
|
|
|
template <typename T>
|
|
class Resource {
|
|
public:
|
|
int32_t getResourceId() const { return resourceId; }
|
|
StorageType getStorageId() const { return ResourceManager<T>::getStorageId(*this); }
|
|
|
|
bool isValid() const { return ResourceManager<T>::isValid(*this); }
|
|
T& getData() { return ResourceManager<T>::getResourceData(*this); }
|
|
|
|
static Resource<T> unsafeFromId(int32_t id) {
|
|
Resource<T> res;
|
|
res.resourceId = id;
|
|
return res;
|
|
}
|
|
|
|
inline explicit operator bool() const { return resourceId >= 0; }
|
|
|
|
private:
|
|
int32_t resourceId = -1;
|
|
friend ResourceManager<T>;
|
|
};
|
|
|
|
template <typename T>
|
|
class ResourceBuilder {
|
|
public:
|
|
using BaseDataType = char;
|
|
static Scope<T> buildResource(const BaseDataType& baseData) {
|
|
static_assert(sizeof(T) == 0, "ResourceBuilder must be specialized for this type T");
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
template <typename T>
|
|
class ResourceManager {
|
|
private:
|
|
struct ResourceData {
|
|
public:
|
|
ResourceData(Scope<T> _data, StorageType _storageId) : data(_data), storageId(_storageId) {}
|
|
Scope<T> data;
|
|
StorageType storageId;
|
|
};
|
|
|
|
static std::vector<ResourceData> resources;
|
|
static std::unordered_map<StorageType, Resource<T>> resourceCache;
|
|
|
|
public:
|
|
template <typename DataSource>
|
|
static Resource<T> loadResource(StorageType storageId) {
|
|
if (resourceCache.contains(storageId))
|
|
return resourceCache[storageId];
|
|
|
|
using ResourceBaseType = typename ResourceBuilder<T>::BaseDataType;
|
|
Scope<T> data;
|
|
|
|
Scope<ResourceBaseType> baseData = StorageBackend<DataSource>::template load<ResourceBaseType>(storageId);
|
|
data = ResourceBuilder<T>::buildResource(*baseData.get());
|
|
|
|
Resource<T> resource = Resource<T>::unsafeFromId(resources.size());
|
|
resources.push_back({storageId, std::move(data)});
|
|
resourceCache[storageId] = resource;
|
|
|
|
return resource;
|
|
}
|
|
|
|
static Resource<T> getResource(StorageType storageId) {
|
|
if (resourceCache.contains(storageId))
|
|
return resourceCache[storageId];
|
|
|
|
return Resource<T>();
|
|
}
|
|
|
|
static Resource<T> loadResourceFromData(const typename ResourceBuilder<T>::BaseDataType& resourceData, StorageType storageId) {
|
|
if (resourceCache.contains(storageId))
|
|
return resourceCache[storageId];
|
|
|
|
Scope<T> data = ResourceBuilder<T>::buildResource(resourceData);
|
|
|
|
Resource<T> resource = Resource<T>::unsafeFromId(resources.size());
|
|
resources.push_back({std::move(data), storageId});
|
|
resourceCache[storageId] = resource;
|
|
|
|
return resource;
|
|
}
|
|
|
|
static void unloadResources() {
|
|
resourceCache.clear();
|
|
resources.clear();
|
|
}
|
|
|
|
static inline bool isValid(Resource<T> res) {
|
|
return res.resourceId >= 0 && res.resourceId < static_cast<int32_t>(resources.size());
|
|
}
|
|
|
|
static inline StorageType getStorageId(Resource<T> res) {
|
|
if (!isValid(res))
|
|
return 0;
|
|
|
|
return resources[res.resourceId].storageId;
|
|
}
|
|
|
|
static T& getResourceData(Resource<T> res) {
|
|
return *resources[res.resourceId].data;
|
|
}
|
|
};
|
|
|
|
template <typename T>
|
|
std::vector<typename ResourceManager<T>::ResourceData> ResourceManager<T>::resources;
|
|
template <typename T>
|
|
std::unordered_map<StorageType, Resource<T>> ResourceManager<T>::resourceCache;
|
|
} // namespace Deer
|
|
|
|
// BUILTIN RESOURCE IDS
|
|
|
|
#define RESOURCE_CUBE_ID 0x1
|
|
#define RESOURCE_SPHERE_ID 0x2
|
|
#define RESOURCE_BASIC_SHADER_ID 0x3 |