diff --git a/src/Window.cpp b/src/Window.cpp index 148979eca..b1318b67b 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -141,8 +141,15 @@ void Window::update(int deltaTime) if(Settings::getInstance()->getBool("DrawFramerate")) { std::stringstream ss; + + // fps ss << std::fixed << std::setprecision(1) << (1000.0f * (float)mFrameCountElapsed / (float)mFrameTimeElapsed) << "fps, "; ss << std::fixed << std::setprecision(2) << ((float)mFrameTimeElapsed / (float)mFrameCountElapsed) << "ms"; + + // vram + float vramUsageMb = (TextureResource::getTotalMemUsage() + Font::getTotalMemUsage()) / 1000.0f / 1000.0f; + ss << "\nVRAM: " << vramUsageMb << "mb"; + mFrameDataString = ss.str(); } diff --git a/src/resources/Font.cpp b/src/resources/Font.cpp index 9676c30da..d1150bd7d 100644 --- a/src/resources/Font.cpp +++ b/src/resources/Font.cpp @@ -27,6 +27,34 @@ void Font::initLibrary() } } +size_t Font::getMemUsage() const +{ + if(!textureID) + return 0; + + return textureWidth * textureHeight * 4; +} + +size_t Font::getTotalMemUsage() +{ + size_t total = 0; + + auto it = sFontMap.begin(); + while(it != sFontMap.end()) + { + if(it->second.expired()) + { + it = sFontMap.erase(it); + continue; + } + + total += it->second.lock()->getMemUsage(); + it++; + } + + return total; +} + Font::Font(int size, const std::string& path) : fontScale(1.0f), mSize(size), mPath(path) { reload(ResourceManager::getInstance()); diff --git a/src/resources/Font.h b/src/resources/Font.h index 30f623450..c0008515c 100644 --- a/src/resources/Font.h +++ b/src/resources/Font.h @@ -78,6 +78,9 @@ public: static std::shared_ptr getFromTheme(const ThemeData::ThemeElement* elem, unsigned int properties, const std::shared_ptr& orig); + size_t getMemUsage() const; // returns an approximation of VRAM used by this font's texture (in bytes) + static size_t getTotalMemUsage(); // returns an approximation of total VRAM used by font textures (in bytes) + private: static int getDpiX(); static int getDpiY(); diff --git a/src/resources/TextureResource.cpp b/src/resources/TextureResource.cpp index 4965da6a5..af87506b6 100644 --- a/src/resources/TextureResource.cpp +++ b/src/resources/TextureResource.cpp @@ -8,6 +8,7 @@ #include "SVGResource.h" std::map< TextureResource::TextureKeyType, std::weak_ptr > TextureResource::sTextureMap; +std::list< std::weak_ptr > TextureResource::sTextureList; TextureResource::TextureResource(const std::string& path, bool tile) : mTextureID(0), mPath(path), mTextureSize(Eigen::Vector2i::Zero()), mTile(tile) @@ -125,20 +126,51 @@ std::shared_ptr TextureResource::get(const std::string& path, b // probably // don't add it to our map because 2 svgs might be rasterized at different sizes tex = std::shared_ptr(new SVGResource(path, tile)); + sTextureList.push_back(tex); // add it to our list though rm->addReloadable(tex); tex->reload(rm); return tex; }else{ + // normal texture tex = std::shared_ptr(new TextureResource(path, tile)); + sTextureMap[key] = std::weak_ptr(tex); + sTextureList.push_back(tex); + rm->addReloadable(tex); + tex->reload(ResourceManager::getInstance()); + return tex; } - - sTextureMap[key] = std::weak_ptr(tex); - rm->addReloadable(tex); - tex->reload(ResourceManager::getInstance()); - return tex; } bool TextureResource::isInitialized() const { return mTextureID != 0; } + +size_t TextureResource::getMemUsage() const +{ + if(!mTextureID || mTextureSize.x() == 0 || mTextureSize.y() == 0) + return 0; + + return mTextureSize.x() * mTextureSize.y() * 4; +} + +size_t TextureResource::getTotalMemUsage() +{ + size_t total = 0; + + auto it = sTextureList.begin(); + while(it != sTextureList.end()) + { + if((*it).expired()) + { + // remove expired textures from the list + it = sTextureList.erase(it); + continue; + } + + total += (*it).lock()->getMemUsage(); + it++; + } + + return total; +} diff --git a/src/resources/TextureResource.h b/src/resources/TextureResource.h index 4617ace9e..578fb7913 100644 --- a/src/resources/TextureResource.h +++ b/src/resources/TextureResource.h @@ -30,6 +30,9 @@ public: // Warning: will NOT correctly reinitialize when this texture is reloaded (e.g. ES starts/stops playing a game). void initFromPixels(const unsigned char* dataRGBA, size_t width, size_t height); + size_t getMemUsage() const; // returns an approximation of the VRAM used by this texture (in bytes) + static size_t getTotalMemUsage(); // returns an approximation of total VRAM used by textures (in bytes) + protected: TextureResource(const std::string& path, bool tile); void deinit(); @@ -40,6 +43,9 @@ protected: private: GLuint mTextureID; + typedef std::pair TextureKeyType; - static std::map< TextureKeyType, std::weak_ptr > sTextureMap; + static std::map< TextureKeyType, std::weak_ptr > sTextureMap; // map of textures, used to prevent duplicate textures + + static std::list< std::weak_ptr > sTextureList; // list of all textures, used for memory approximations };