From: Mikko Rasa Date: Mon, 8 Sep 2014 20:50:35 +0000 (+0300) Subject: Implement automatic unloading when a total size limit is exceeded X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=4d7f66ea28c788e12f700216b9c53af9e71b8390 Implement automatic unloading when a total size limit is exceeded --- diff --git a/source/pixelformat.cpp b/source/pixelformat.cpp index b8180b2f..7647717a 100644 --- a/source/pixelformat.cpp +++ b/source/pixelformat.cpp @@ -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) diff --git a/source/pixelformat.h b/source/pixelformat.h index 590ab97e..4da1a151 100644 --- a/source/pixelformat.h +++ b/source/pixelformat.h @@ -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); diff --git a/source/resource.h b/source/resource.h index 625c9f93..b3bce17e 100644 --- a/source/resource.h +++ b/source/resource.h @@ -1,6 +1,7 @@ #ifndef MSP_GL_RESOURCE_H_ #define MSP_GL_RESOURCE_H_ +#include #include 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; }; diff --git a/source/resourcemanager.cpp b/source/resourcemanager.cpp index 059c2924..8b647f31 100644 --- a/source/resourcemanager.cpp +++ b/source/resourcemanager.cpp @@ -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_usedsecond.data_size*(frame-i->second.last_used); + if(!best || impactsecond; + 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() diff --git a/source/resourcemanager.h b/source/resourcemanager.h index 07b0aaf0..60f61a42 100644 --- a/source/resourcemanager.h +++ b/source/resourcemanager.h @@ -1,6 +1,7 @@ #ifndef MSP_GL_RESOURCEMANAGER_H_ #define MSP_GL_RESOURCEMANAGER_H_ +#include #include #include #include @@ -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 diff --git a/source/texture.h b/source/texture.h index 5566dccb..79d79dbd 100644 --- a/source/texture.h +++ b/source/texture.h @@ -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 diff --git a/source/texture1d.cpp b/source/texture1d.cpp index bcebca49..f700d013 100644 --- a/source/texture1d.cpp +++ b/source/texture1d.cpp @@ -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 diff --git a/source/texture1d.h b/source/texture1d.h index b4cf0d0b..ea673c3b 100644 --- a/source/texture1d.h +++ b/source/texture1d.h @@ -28,6 +28,7 @@ private: public: virtual AsyncLoader *load(IO::Seekable &) { return 0; } + virtual UInt64 get_data_size() const; virtual void unload() { } }; diff --git a/source/texture2d.cpp b/source/texture2d.cpp index 2da1c252..e237e504 100644 --- a/source/texture2d.cpp +++ b/source/texture2d.cpp @@ -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); diff --git a/source/texture2d.h b/source/texture2d.h index a37e2a4d..eba3286f 100644 --- a/source/texture2d.h +++ b/source/texture2d.h @@ -86,6 +86,7 @@ private: public: virtual Resource::AsyncLoader *load(IO::Seekable &); + virtual UInt64 get_data_size() const; virtual void unload(); }; diff --git a/source/texture3d.cpp b/source/texture3d.cpp index 3846ef1c..61c745bb 100644 --- a/source/texture3d.cpp +++ b/source/texture3d.cpp @@ -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 diff --git a/source/texture3d.h b/source/texture3d.h index 6c087a2d..fa4c050f 100644 --- a/source/texture3d.h +++ b/source/texture3d.h @@ -63,6 +63,7 @@ private: public: virtual AsyncLoader *load(IO::Seekable &) { return 0; } + virtual UInt64 get_data_size() const; virtual void unload() { } }; diff --git a/source/texturecube.cpp b/source/texturecube.cpp index b071e854..7f5250ee 100644 --- a/source/texturecube.cpp +++ b/source/texturecube.cpp @@ -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(t) diff --git a/source/texturecube.h b/source/texturecube.h index 1c0d6724..fe343c73 100644 --- a/source/texturecube.h +++ b/source/texturecube.h @@ -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() { } };