Skip to content

Commit

Permalink
Add ResourceLibrary class and refactor TextureManager
Browse files Browse the repository at this point in the history
We want to reuse the TextureManager logic in a few other places in our
engine for handling assets. Create a ResourceLibrary template class and
then refactor TextureManager to use it instead of code customized just
for textures.
  • Loading branch information
meisekimiu committed Feb 6, 2024
1 parent 1b8b2ea commit 098dd61
Show file tree
Hide file tree
Showing 9 changed files with 167 additions and 87 deletions.
21 changes: 5 additions & 16 deletions src/graphics/Texture2D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,14 @@
Adagio::Texture2D::Texture2D(Adagio::TextureHandle handle,
Adagio::TextureHandle secret,
unsigned int width,
unsigned int height) {
this->handle = handle;
this->secret = secret;
this->width = width;
this->height = height;
}
unsigned int height) : Asset<TextureHandle, TextureDimensions>(
handle, secret,
{width, height}) {}

unsigned int Adagio::Texture2D::getHeight() {
return height;
return metadata.height;
}

unsigned int Adagio::Texture2D::getWidth() {
return width;
}

Adagio::TextureHandle Adagio::Texture2D::getSecretId() {
return secret;
}

bool Adagio::Texture2D::isValid() {
return handle != 0;
return metadata.width;
}
19 changes: 7 additions & 12 deletions src/graphics/Texture2D.h
Original file line number Diff line number Diff line change
@@ -1,26 +1,21 @@
#ifndef GL_ADAGIO_TEXTURE2D_H
#define GL_ADAGIO_TEXTURE2D_H

#include "../resource/Asset.h"
#include "TextureDimensions.h"

namespace Adagio {
typedef unsigned int TextureHandle;

class Texture2D {
class Texture2D : public Asset<TextureHandle, TextureDimensions> {
public:
explicit Texture2D(Asset<TextureHandle, TextureDimensions> asset);

explicit Texture2D(TextureHandle handle, TextureHandle secret, unsigned int width, unsigned int height);

TextureHandle handle;

unsigned int getWidth();

unsigned int getHeight();

TextureHandle getSecretId();

bool isValid();

private:
TextureHandle secret;
unsigned int width;
unsigned int height;
};
}
#endif //GL_ADAGIO_TEXTURE2D_H
3 changes: 2 additions & 1 deletion src/graphics/TextureLoader.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
#ifndef GL_ADAGIO_TEXTURELOADER_H
#define GL_ADAGIO_TEXTURELOADER_H

#include "../resource/ResourceLibrary.h"
#include "TextureDimensions.h"

namespace Adagio {
template<typename T>
struct TextureLoader {
struct TextureLoader : public AssetLoader<T, TextureDimensions> {
virtual std::pair<T, TextureDimensions> load(const char *resource) = 0;

virtual void unload(T texture) = 0;
Expand Down
49 changes: 7 additions & 42 deletions src/graphics/TextureManager-impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,60 +2,25 @@
#define GL_ADAGIO_TEXTUREMANAGER_IMPL_H
namespace Adagio {
template<typename T>
TextureManager<T>::TextureManager(TextureLoader<T> *loader) {
textureLoader = loader;
textureLibrary.reserve(64);
nextSecret = 1;
TextureManager<T>::TextureManager(TextureLoader<T> *loader) : library(loader) {
}

template<typename T>
Texture2D TextureManager<T>::load(std::string resource) {
if (loadedFilenames.find(resource) != loadedFilenames.end()) {
TextureHandle handle = loadedFilenames[resource] - 1;
auto internalTexture = textureLibrary[handle];
return Texture2D(handle + 1,
internalTexture.secret,
internalTexture.dimensions.width,
internalTexture.dimensions.height);
}
auto internalTexture = textureLoader->load(resource.c_str());
auto dimensions = internalTexture.second;
TextureHandle secret = nextSecret++;
TextureHandle id;
if (!freeHandles.empty()) {
id = freeHandles.back();
freeHandles.pop_back();
textureLibrary[id - 1] = {secret, dimensions, internalTexture.first};
} else {
id = textureLibrary.size() + 1;
textureLibrary.push_back({secret, dimensions, internalTexture.first});
}
loadedFilenames[resource] = id;
Texture2D handle(id, secret, dimensions.width, dimensions.height);
return handle;
auto asset = library.load(resource);
TextureDimensions metadata = asset.getMetadata();
return Texture2D(asset.handle, asset.getSecretId(), metadata.width, metadata.height);
// TODO: Probably use pointers instead for polymorphism
}

template<typename T>
void TextureManager<T>::unload(Adagio::Texture2D texture) {
auto internalTexture = textureLibrary[texture.handle - 1];
internalTexture.secret = 0;
textureLoader->unload(internalTexture.texture);
freeHandles.push_back(texture.handle);
for (auto it = loadedFilenames.begin(); it != loadedFilenames.end(); it++) {
if (it->second == texture.handle) {
loadedFilenames.erase(it);
break;
}
}
library.unload(texture);
}

template<typename T>
T TextureManager<T>::useTexture(Adagio::Texture2D texture) {
auto internalTexture = textureLibrary[texture.handle - 1];
if (texture.getSecretId() != internalTexture.secret) {
throw std::invalid_argument("Unloaded texture used.");
}
return internalTexture.texture;
return library.useResource(texture);
}
}
#endif //GL_ADAGIO_TEXTUREMANAGER_IMPL_H
19 changes: 3 additions & 16 deletions src/graphics/TextureManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,11 @@
#define GL_ADAGIO_TEXTUREMANAGER_H

#include <string>
#include <vector>
#include <unordered_map>
#include "TextureLoader.h"
#include "Texture2D.h"
#include "TextureLoader.h"
#include "../resource/ResourceLibrary.h"

namespace Adagio {
template<typename T>
struct TextureWithSecret {
TextureHandle secret;
TextureDimensions dimensions;
T texture;
};

template<typename T>
class TextureManager {
public:
Expand All @@ -27,12 +19,7 @@ namespace Adagio {
T useTexture(Texture2D texture);

private:
TextureLoader<T> *textureLoader;
std::vector<TextureWithSecret<T>> textureLibrary;
std::vector<TextureHandle> freeHandles;
std::unordered_map<std::string, TextureHandle> loadedFilenames;

TextureHandle nextSecret;
ResourceLibrary<T, TextureDimensions, TextureHandle> library;
};
}

Expand Down
34 changes: 34 additions & 0 deletions src/resource/Asset.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#ifndef GL_ADAGIO_ASSET_H
#define GL_ADAGIO_ASSET_H

namespace Adagio {
template<typename HandleType, typename MetadataType>
class Asset {
public:
explicit Asset(HandleType handle, HandleType secret, const MetadataType &metadata) {
this->handle = handle;
this->secret = secret;
this->metadata = metadata;
}

HandleType handle;

HandleType getSecretId() const {
return secret;
}

[[nodiscard]] bool isValid() const {
return secret != 0;
}

MetadataType getMetadata() const {
return metadata;
}

protected:
HandleType secret;
MetadataType metadata;
};
}

#endif //GL_ADAGIO_ASSET_H
15 changes: 15 additions & 0 deletions src/resource/AssetLoader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef GL_ADAGIO_ASSETLOADER_H
#define GL_ADAGIO_ASSETLOADER_H

#include <utility>

namespace Adagio {
template<typename InternalAssetType, typename MetadataType>
struct AssetLoader {
virtual std::pair<InternalAssetType, MetadataType> load(const char *resource) = 0;

virtual void unload(InternalAssetType asset) = 0;
};
}

#endif //GL_ADAGIO_ASSETLOADER_H
13 changes: 13 additions & 0 deletions src/resource/InternalAssetWithSecret.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef GL_ADAGIO_INTERNALASSETWITHSECRET_H
#define GL_ADAGIO_INTERNALASSETWITHSECRET_H

namespace Adagio {
template<typename InternalAssetType, typename MetadataType, typename HandleType>
struct InternalAssetWithSecret {
HandleType secret;
MetadataType metadata;
InternalAssetType asset;
};
}

#endif //GL_ADAGIO_INTERNALASSETWITHSECRET_H
81 changes: 81 additions & 0 deletions src/resource/ResourceLibrary.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#ifndef GL_ADAGIO_RESOURCELIBRARY_H
#define GL_ADAGIO_RESOURCELIBRARY_H

#include <stdexcept>
#include <string>
#include <unordered_map>
#include <vector>
#include "Asset.h"
#include "AssetLoader.h"
#include "InternalAssetWithSecret.h"

namespace Adagio {
template<typename InternalAssetType, typename MetadataType, typename HandleType>
class ResourceLibrary {
typedef Asset<HandleType, MetadataType> ResourceType;
typedef InternalAssetWithSecret<InternalAssetType, MetadataType, HandleType> ResourceWithSecret;
typedef AssetLoader<InternalAssetType, MetadataType> LoaderType;

public:
explicit ResourceLibrary(AssetLoader<InternalAssetType, MetadataType> *loader) {
this->loader = loader;
library.reserve(64);
nextSecret = 1;
}

ResourceType load(std::string resource) {
if (loadedFilenames.find(resource) != loadedFilenames.end()) {
HandleType handle = loadedFilenames[resource] - 1;
ResourceWithSecret internalAsset = library[handle];
return Asset<HandleType, MetadataType>(handle + 1,
internalAsset.secret,
internalAsset.metadata);
}
auto internalTexture = loader->load(resource.c_str());
auto dimensions = internalTexture.second;
HandleType secret = nextSecret++;
HandleType id;
if (!freeHandles.empty()) {
id = freeHandles.back();
freeHandles.pop_back();
library[id - 1] = {secret, dimensions, internalTexture.first};
} else {
id = library.size() + 1;
library.push_back({secret, dimensions, internalTexture.first});
}
loadedFilenames[resource] = id;
Asset<HandleType, MetadataType> handle(id, secret, dimensions);
return handle;
}

void unload(const ResourceType &asset) {
ResourceWithSecret internalTexture = library[asset.handle - 1];
internalTexture.secret = 0;
loader->unload(internalTexture.asset);
freeHandles.push_back(asset.handle);
for (auto it = loadedFilenames.begin(); it != loadedFilenames.end(); it++) {
if (it->second == asset.handle) {
loadedFilenames.erase(it);
break;
}
}
}

InternalAssetType useResource(const ResourceType &asset) {
ResourceWithSecret internalTexture = library[asset.handle - 1];
if (asset.getSecretId() != internalTexture.secret) {
throw std::invalid_argument("Unloaded texture used.");
}
return internalTexture.asset;
}

private:
AssetLoader<InternalAssetType, MetadataType> *loader;
std::vector<ResourceWithSecret> library;
std::vector<HandleType> freeHandles;
std::unordered_map<std::string, HandleType> loadedFilenames;

HandleType nextSecret;
};
}
#endif //GL_ADAGIO_RESOURCELIBRARY_H

0 comments on commit 098dd61

Please sign in to comment.