]> git.tdb.fi Git - libs/gl.git/commitdiff
Implement automatic unloading when a total size limit is exceeded
authorMikko Rasa <tdb@tdb.fi>
Mon, 8 Sep 2014 20:50:35 +0000 (23:50 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 8 Sep 2014 20:50:35 +0000 (23:50 +0300)
14 files changed:
source/pixelformat.cpp
source/pixelformat.h
source/resource.h
source/resourcemanager.cpp
source/resourcemanager.h
source/texture.h
source/texture1d.cpp
source/texture1d.h
source/texture2d.cpp
source/texture2d.h
source/texture3d.cpp
source/texture3d.h
source/texturecube.cpp
source/texturecube.h

index b8180b2fb75e559477c0388eddc53509f35263ba..7647717a44ad3d047e7bfbc0d386a575f5564701 100644 (file)
@@ -148,6 +148,30 @@ unsigned get_component_count(PixelFormat pf)
        }
 }
 
+unsigned get_component_size(PixelFormat pf)
+{
+       switch(pf)
+       {
+       case RGB16F:
+       case RGBA16F:
+       case LUMINANCE16F:
+       case LUMINANCE_ALPHA16F:
+               return 2;
+       case RGB32F:
+       case RGBA32F:
+       case LUMINANCE32F:
+       case LUMINANCE_ALPHA32F:
+               return 4;
+       default:
+               return 1;
+       }
+}
+
+unsigned get_pixel_size(PixelFormat pf)
+{
+       return get_component_count(pf)*get_component_size(pf);
+}
+
 void require_pixelformat(PixelFormat pf)
 {
        switch(pf)
index 590ab97eb62cd1e48821e27b9ddda71352149d48..4da1a1517ae60b45b85aea8d41b7452744326f19 100644 (file)
@@ -56,6 +56,8 @@ PixelFormat storage_pixelformat_from_graphics(Graphics::PixelFormat);
 PixelFormat get_base_pixelformat(PixelFormat);
 PixelFormat get_srgb_pixelformat(PixelFormat);
 unsigned get_component_count(PixelFormat);
+unsigned get_component_size(PixelFormat);
+unsigned get_pixel_size(PixelFormat);
 
 void require_pixelformat(PixelFormat);
 
index 625c9f93059dd122cdf2ee526d85568a839f0dce..b3bce17e32cf86b95b1ba3914dd0ab8ab1d72d40 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef MSP_GL_RESOURCE_H_
 #define MSP_GL_RESOURCE_H_
 
+#include <msp/core/inttypes.h>
 #include <msp/io/seekable.h>
 
 namespace Msp {
@@ -33,6 +34,7 @@ public:
        void set_manager(ResourceManager *);
        void *get_manager_data() const { return manager_data; }
        virtual AsyncLoader *load(IO::Seekable &) = 0;
+       virtual UInt64 get_data_size() const = 0;
        virtual void unload() = 0;
 };
 
index 059c29241335d464835bb3557bb8c6c98cc93a12..8b647f31f9ef24f5bd7d13d2ae5bb46f46b54c98 100644 (file)
@@ -9,7 +9,9 @@ namespace GL {
 ResourceManager::ResourceManager():
        policy(LOAD_ON_DEMAND),
        async_loads(true),
+       size_limit(0),
        frame(0),
+       min_retain_frames(30),
        max_retain_frames(0),
        next_unload(0),
        thread(*this)
@@ -33,6 +35,16 @@ void ResourceManager::set_async_loads(bool a)
        async_loads = a;
 }
 
+void ResourceManager::set_size_limit(UInt64 s)
+{
+       size_limit = s;
+}
+
+void ResourceManager::set_min_retain_frames(unsigned f)
+{
+       min_retain_frames = f;
+}
+
 void ResourceManager::set_max_retain_frames(unsigned f)
 {
        max_retain_frames = f;
@@ -101,8 +113,12 @@ void ResourceManager::remove_resource(Resource &r)
 void ResourceManager::tick()
 {
        LoadingThread::State thread_state = thread.get_state();
+       bool check_total_size = false;
        if(thread_state==LoadingThread::SYNC_PENDING)
+       {
                thread.sync();
+               check_total_size = true;
+       }
        else if(thread_state==LoadingThread::IDLE && !queue.empty())
        {
                ManagedResource *managed = queue.front();
@@ -128,6 +144,40 @@ void ResourceManager::tick()
                if(next_unload)
                        next_unload += max_retain_frames;
        }
+
+       if(check_total_size)
+       {
+               while(get_total_data_size()>size_limit)
+               {
+                       unsigned unload_limit = frame-min_retain_frames;
+                       ManagedResource *best = 0;
+                       UInt64 best_impact = 0;
+                       for(ResourceMap::iterator i=resources.begin(); i!=resources.end(); ++i)
+                               if(i->second.loaded && i->second.last_used<unload_limit)
+                               {
+                                       UInt64 impact = i->second.data_size*(frame-i->second.last_used);
+                                       if(!best || impact<best_impact)
+                                       {
+                                               best = &i->second;
+                                               best_impact = impact;
+                                       }
+                               }
+
+                       if(!best)
+                               break;
+
+                       best->unload();
+               }
+       }
+}
+
+UInt64 ResourceManager::get_total_data_size() const
+{
+       UInt64 total = 0;
+       for(ResourceMap::const_iterator i=resources.begin(); i!=resources.end(); ++i)
+               if(i->second.loaded)
+                       total += i->second.data_size;
+       return total;
 }
 
 
@@ -137,7 +187,8 @@ ResourceManager::ManagedResource::ManagedResource(Resource &r):
        io(0),
        loader(0),
        loaded(false),
-       last_used(0)
+       last_used(0),
+       data_size(0)
 { }
 
 void ResourceManager::ManagedResource::start_loading()
@@ -159,6 +210,7 @@ void ResourceManager::ManagedResource::finish_loading()
        loaded = true;
        delete io;
        io = 0;
+       data_size = resource->get_data_size();
 }
 
 void ResourceManager::ManagedResource::unload()
index 07b0aaf09f0574fe2ee8f6fbaea7be162f9660b7..60f61a421fe4b2b54685a2366cd339e9bfa9be2d 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef MSP_GL_RESOURCEMANAGER_H_
 #define MSP_GL_RESOURCEMANAGER_H_
 
+#include <msp/core/inttypes.h>
 #include <msp/core/mutex.h>
 #include <msp/core/semaphore.h>
 #include <msp/core/thread.h>
@@ -30,6 +31,7 @@ private:
                Resource::AsyncLoader *loader;
                bool loaded;
                unsigned last_used;
+               UInt64 data_size;
 
                ManagedResource(Resource &);
 
@@ -78,6 +80,7 @@ private:
        bool async_loads;
        ResourceMap resources;
        LoadQueue queue;
+       UInt64 size_limit;
        unsigned frame;
        unsigned min_retain_frames;
        unsigned max_retain_frames;
@@ -90,6 +93,8 @@ public:
 
        void set_loading_policy(LoadingPolicy);
        void set_async_loads(bool);
+       void set_size_limit(UInt64);
+       void set_min_retain_frames(unsigned);
        void set_max_retain_frames(unsigned);
 
        void add_resource(Resource &);
@@ -100,6 +105,7 @@ public:
        void remove_resource(Resource &);
 
        void tick();
+       UInt64 get_total_data_size() const;
 };
 
 } // namespace GL
index 5566dccb8c9a111f55336b59d6aa7b68d08c0370..79d79dbd68fbc8c8908b04f180501c6335b783ab 100644 (file)
@@ -162,6 +162,8 @@ public:
        static const Texture *current(unsigned = 0);
        static void unbind() { unbind_from(0); }
        static void unbind_from(unsigned);
+
+       virtual UInt64 get_data_size() const { return 0; }
 };
 
 } // namespace GL
index bcebca49565131eb738ba471af992cbe0e05c1a9..f700d013b5dc6a55f88196695b8a8ec83b2242b9 100644 (file)
@@ -9,6 +9,7 @@ namespace GL {
 
 Texture1D::Texture1D():
        Texture(GL_TEXTURE_1D),
+       ifmt(RGB),
        width(0),
        allocated(0)
 { }
@@ -56,5 +57,10 @@ unsigned Texture1D::get_level_size(unsigned level)
        return width>>level;
 }
 
+UInt64 Texture1D::get_data_size() const
+{
+       return id ? width*get_pixel_size(ifmt) : 0;
+}
+
 } // namespace GL
 } // namespace Msp
index b4cf0d0ba5aecc266427d93e30b1b8c9bc9d1828..ea673c3b8b8a606326e78963cdbe30b35fb3cc50 100644 (file)
@@ -28,6 +28,7 @@ private:
 
 public:
        virtual AsyncLoader *load(IO::Seekable &) { return 0; }
+       virtual UInt64 get_data_size() const;
        virtual void unload() { }
 };
 
index 2da1c25245b1064cf8da073c8e9c4d919fb9417a..e237e504176ace2bfd56ddf74597907aee397abb 100644 (file)
@@ -32,6 +32,7 @@ public:
 
 Texture2D::Texture2D(ResourceManager *m):
        Texture(GL_TEXTURE_2D, m),
+       ifmt(RGB),
        width(0),
        height(0),
        allocated(0)
@@ -139,6 +140,11 @@ Resource::AsyncLoader *Texture2D::load(IO::Seekable &io)
        return new AsyncLoader(*this, io);
 }
 
+UInt64 Texture2D::get_data_size() const
+{
+       return id ? width*height*get_component_count(ifmt) : 0;
+}
+
 void Texture2D::unload()
 {
        glDeleteTextures(1, &id);
index a37e2a4d7fd746eeb732d23483d8896115377338..eba3286fee15fddce63b67e503f551990b0bf65d 100644 (file)
@@ -86,6 +86,7 @@ private:
 
 public:
        virtual Resource::AsyncLoader *load(IO::Seekable &);
+       virtual UInt64 get_data_size() const;
        virtual void unload();
 };
 
index 3846ef1c1294e18d78b183e4208366648c76a46f..61c745bb95bf4d8ae3df56c1c94c7aec43a686f7 100644 (file)
@@ -13,6 +13,7 @@ namespace GL {
 
 Texture3D::Texture3D():
        Texture(GL_TEXTURE_3D),
+       ifmt(RGB),
        width(0),
        height(0),
        depth(0),
@@ -135,5 +136,10 @@ void Texture3D::get_level_size(unsigned level, unsigned &w, unsigned &h, unsigne
                d = 1;
 }
 
+UInt64 Texture3D::get_data_size() const
+{
+       return id ? width*height*depth*get_pixel_size(ifmt) : 0;
+}
+
 } // namespace GL
 } // namespace Msp
index 6c087a2d099f5ed2bdc0e46b320b026e6dcab6a7..fa4c050f039c38f9a0734b0f6ec11ec21082e92b 100644 (file)
@@ -63,6 +63,7 @@ private:
 
 public:
        virtual AsyncLoader *load(IO::Seekable &) { return 0; }
+       virtual UInt64 get_data_size() const;
        virtual void unload() { }
 };
 
index b071e8545df50ce665b1476b0683058a00af0590..7f5250ee99e1381195977b1a40e12b77a8220839 100644 (file)
@@ -23,6 +23,7 @@ Vector3 TextureCube::directions[6] =
 
 TextureCube::TextureCube():
        Texture(GL_TEXTURE_CUBE_MAP),
+       ifmt(RGB),
        size(0),
        allocated(0)
 {
@@ -166,6 +167,11 @@ Vector3 TextureCube::get_texel_direction(TextureCubeFace face, unsigned u, unsig
        return fv+s*sv+t*tv;
 }
 
+UInt64 TextureCube::get_data_size() const
+{
+       return id ? size*size*6*get_pixel_size(ifmt) : 0;
+}
+
 
 TextureCube::Loader::Loader(TextureCube &t):
        DataFile::DerivedObjectLoader<TextureCube, Texture::Loader>(t)
index 1c0d672428a8f098e2e8b33744b6894aab2e783d..fe343c7390630de1ad6fdc9a1f3a2cbc3ebfcdda 100644 (file)
@@ -104,6 +104,7 @@ public:
        Vector3 get_texel_direction(TextureCubeFace, unsigned, unsigned);
 
        virtual AsyncLoader *load(IO::Seekable &) { return 0; }
+       virtual UInt64 get_data_size() const;
        virtual void unload() { }
 };