Try to use priority queue
This commit is contained in:
parent
6b3441d2a0
commit
85011791e4
@ -28,11 +28,13 @@
|
||||
#include <algorithm>
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
STKTexManager::STKTexManager() : m_pbo(0), m_thread_size(0), m_tlt_added(0)
|
||||
STKTexManager::STKTexManager() : m_pbo(0), m_thread_size(0)
|
||||
{
|
||||
#if !(defined(SERVER_ONLY) || defined(USE_GLES2))
|
||||
if (CVS->supportsThreadedTextureLoading())
|
||||
{
|
||||
pthread_mutex_init(&m_threaded_load_textures_mutex, NULL);
|
||||
pthread_cond_init(&m_cond_request, NULL);
|
||||
m_thread_size = HardwareStats::getNumProcessors();
|
||||
m_thread_size = core::clamp(m_thread_size, 1, 8);
|
||||
static const unsigned max_pbo_size = 32 * 1024 * 1024;
|
||||
@ -52,7 +54,8 @@ STKTexManager::STKTexManager() : m_pbo(0), m_thread_size(0), m_tlt_added(0)
|
||||
for (int i = 0; i < m_thread_size; i++)
|
||||
{
|
||||
m_all_tex_loaders.push_back(new ThreadedTexLoader(each_capacity,
|
||||
offset, pbo_ptr + offset));
|
||||
offset, pbo_ptr + offset, &m_threaded_load_textures_mutex,
|
||||
&m_cond_request, this));
|
||||
offset += each_capacity;
|
||||
}
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
@ -65,8 +68,12 @@ STKTexManager::STKTexManager() : m_pbo(0), m_thread_size(0), m_tlt_added(0)
|
||||
STKTexManager::~STKTexManager()
|
||||
{
|
||||
removeTexture(NULL/*texture*/, true/*remove_all*/);
|
||||
for (ThreadedTexLoader* ttl : m_all_tex_loaders)
|
||||
delete ttl;
|
||||
if (CVS->supportsThreadedTextureLoading())
|
||||
{
|
||||
pthread_cond_destroy(&m_cond_request);
|
||||
for (ThreadedTexLoader* ttl : m_all_tex_loaders)
|
||||
delete ttl;
|
||||
}
|
||||
} // ~STKTexManager
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -137,8 +144,7 @@ video::ITexture* STKTexManager::getTexture(const std::string& path, bool srgb,
|
||||
}
|
||||
if (new_texture->useThreadedLoading())
|
||||
{
|
||||
m_all_tex_loaders[m_tlt_added++ % m_thread_size]
|
||||
->addTexture(new_texture);
|
||||
addThreadedLoadTexture(new_texture);
|
||||
}
|
||||
}
|
||||
uploadBatch();
|
||||
@ -252,14 +258,12 @@ core::stringw STKTexManager::reloadTexture(const irr::core::stringw& name)
|
||||
p.second->reload();
|
||||
if (p.second->useThreadedLoading())
|
||||
{
|
||||
m_all_tex_loaders[m_tlt_added++ % m_thread_size]
|
||||
->addTexture(p.second);
|
||||
addThreadedLoadTexture(p.second);
|
||||
uploadBatch();
|
||||
}
|
||||
Log::info("STKTexManager", "%s reloaded",
|
||||
p.second->getName().getPtr());
|
||||
}
|
||||
m_tlt_added = 0;
|
||||
return L"All textures reloaded.";
|
||||
}
|
||||
|
||||
@ -281,8 +285,7 @@ core::stringw STKTexManager::reloadTexture(const irr::core::stringw& name)
|
||||
p.second->reload();
|
||||
if (p.second->useThreadedLoading())
|
||||
{
|
||||
m_all_tex_loaders[m_tlt_added++ % m_thread_size]
|
||||
->addTexture(p.second);
|
||||
addThreadedLoadTexture(p.second);
|
||||
uploadBatch();
|
||||
}
|
||||
result += tex_name.c_str();
|
||||
@ -290,7 +293,6 @@ core::stringw STKTexManager::reloadTexture(const irr::core::stringw& name)
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_tlt_added = 0;
|
||||
}
|
||||
if (result.empty())
|
||||
return L"Texture(s) not found!";
|
||||
@ -301,7 +303,6 @@ core::stringw STKTexManager::reloadTexture(const irr::core::stringw& name)
|
||||
// ----------------------------------------------------------------------------
|
||||
void STKTexManager::reset()
|
||||
{
|
||||
m_tlt_added = 0;
|
||||
#if !(defined(SERVER_ONLY) || defined(USE_GLES2))
|
||||
if (!CVS->isAZDOEnabled()) return;
|
||||
for (auto p : m_all_textures)
|
||||
@ -341,6 +342,7 @@ void STKTexManager::uploadBatch()
|
||||
bool uploaded = false;
|
||||
for (ThreadedTexLoader* ttl : m_all_tex_loaders)
|
||||
{
|
||||
ttl->lock();
|
||||
if (ttl->finishedLoading())
|
||||
{
|
||||
if (!uploaded)
|
||||
@ -350,6 +352,10 @@ void STKTexManager::uploadBatch()
|
||||
}
|
||||
ttl->handleCompletedTextures();
|
||||
}
|
||||
else
|
||||
{
|
||||
ttl->unlock();
|
||||
}
|
||||
}
|
||||
if (uploaded)
|
||||
{
|
||||
@ -367,7 +373,14 @@ void STKTexManager::uploadBatch()
|
||||
glDeleteSync(sync);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
for (ThreadedTexLoader* ttl : m_all_tex_loaders)
|
||||
ttl->unlockCompletedTextures();
|
||||
ttl->unlock();
|
||||
}
|
||||
#endif
|
||||
} // uploadBatch
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool STKTexManager::SmallestTexture::operator()
|
||||
(const STKTexture *a, const STKTexture *b) const
|
||||
{
|
||||
return a->getTextureSize() > b->getTextureSize();
|
||||
} // SmallestTexture::operator
|
||||
|
@ -23,8 +23,10 @@
|
||||
#include "utils/singleton.hpp"
|
||||
|
||||
#include "irrString.h"
|
||||
#include <pthread.h>
|
||||
|
||||
#include <string>
|
||||
#include <queue>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
@ -50,7 +52,17 @@ private:
|
||||
|
||||
int m_thread_size;
|
||||
|
||||
unsigned m_tlt_added;
|
||||
class SmallestTexture
|
||||
{
|
||||
public:
|
||||
bool operator() (const STKTexture *a, const STKTexture *b) const;
|
||||
};
|
||||
std::priority_queue<STKTexture*, std::vector<STKTexture*>,
|
||||
SmallestTexture> m_threaded_load_textures;
|
||||
|
||||
pthread_mutex_t m_threaded_load_textures_mutex;
|
||||
|
||||
pthread_cond_t m_cond_request;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
STKTexture* findTextureInFileSystem(const std::string& filename,
|
||||
@ -138,6 +150,22 @@ public:
|
||||
} // getTexture
|
||||
// ------------------------------------------------------------------------
|
||||
void uploadBatch();
|
||||
// ------------------------------------------------------------------------
|
||||
STKTexture* getThreadedLoadTexture()
|
||||
{ return m_threaded_load_textures.top(); }
|
||||
// ------------------------------------------------------------------------
|
||||
void addThreadedLoadTexture(STKTexture* t)
|
||||
{
|
||||
pthread_mutex_lock(&m_threaded_load_textures_mutex);
|
||||
m_threaded_load_textures.push(t);
|
||||
pthread_cond_signal(&m_cond_request);
|
||||
pthread_mutex_unlock(&m_threaded_load_textures_mutex);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
void removeThreadedLoadTexture() { m_threaded_load_textures.pop(); }
|
||||
// ------------------------------------------------------------------------
|
||||
bool isThreadedLoadTexturesEmpty()
|
||||
{ return m_threaded_load_textures.empty(); }
|
||||
|
||||
}; // STKTexManager
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "graphics/threaded_tex_loader.hpp"
|
||||
#include "graphics/stk_texture.hpp"
|
||||
#include "graphics/stk_tex_manager.hpp"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
@ -26,69 +27,70 @@ void* ThreadedTexLoader::startRoutine(void *obj)
|
||||
ThreadedTexLoader* ttl = (ThreadedTexLoader*)obj;
|
||||
while (!ttl->m_destroy)
|
||||
{
|
||||
if (ttl->finishedLoading())
|
||||
pthread_mutex_lock(&ttl->m_mutex);
|
||||
bool finished = ttl->finishedLoading();
|
||||
pthread_mutex_unlock(&ttl->m_mutex);
|
||||
if (finished)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ttl->m_threaded_loading_textures.lock();
|
||||
bool queue_empty = ttl->m_threaded_loading_textures.getData().empty();
|
||||
ttl->m_completed_textures.lock();
|
||||
bool no_unloaded_tex = ttl->m_completed_textures.getData().empty();
|
||||
ttl->m_completed_textures.unlock();
|
||||
bool no_unloaded_tex = ttl->m_completed_textures.empty();
|
||||
pthread_mutex_lock(ttl->m_texture_queue_mutex);
|
||||
bool queue_empty = ttl->m_stktm->isThreadedLoadTexturesEmpty();
|
||||
bool waiting = queue_empty && no_unloaded_tex;
|
||||
while (waiting)
|
||||
{
|
||||
pthread_cond_wait(&ttl->m_cond_request,
|
||||
ttl->m_threaded_loading_textures.getMutex());
|
||||
waiting = ttl->m_threaded_loading_textures.getData().empty();
|
||||
pthread_cond_wait(ttl->m_cond_request, ttl->m_texture_queue_mutex);
|
||||
waiting = ttl->m_stktm->isThreadedLoadTexturesEmpty();
|
||||
}
|
||||
if (queue_empty)
|
||||
{
|
||||
if (ttl->m_waiting_timeout++ > 10)
|
||||
{
|
||||
ttl->m_finished_loading.setAtomic(true);
|
||||
pthread_mutex_lock(&ttl->m_mutex);
|
||||
ttl->m_finished_loading = true;
|
||||
ttl->m_tex_size_loaded = 0;
|
||||
ttl->m_waiting_timeout = 0;
|
||||
pthread_mutex_unlock(&ttl->m_mutex);
|
||||
}
|
||||
ttl->m_threaded_loading_textures.unlock();
|
||||
pthread_mutex_unlock(ttl->m_texture_queue_mutex);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
ttl->m_waiting_timeout = 0;
|
||||
}
|
||||
STKTexture* target_tex = ttl->m_threaded_loading_textures.getData()[0];
|
||||
STKTexture* target_tex = ttl->m_stktm->getThreadedLoadTexture();
|
||||
if (target_tex->getTextureSize() + ttl->m_tex_size_loaded >
|
||||
ttl->m_tex_capacity)
|
||||
{
|
||||
ttl->m_finished_loading.setAtomic(true);
|
||||
pthread_mutex_lock(&ttl->m_mutex);
|
||||
ttl->m_finished_loading = true;
|
||||
ttl->m_tex_size_loaded = 0;
|
||||
ttl->m_waiting_timeout = 0;
|
||||
ttl->m_threaded_loading_textures.unlock();
|
||||
pthread_mutex_unlock(&ttl->m_mutex);
|
||||
pthread_mutex_unlock(ttl->m_texture_queue_mutex);
|
||||
continue;
|
||||
}
|
||||
ttl->m_threaded_loading_textures.getData().erase
|
||||
(ttl->m_threaded_loading_textures.getData().begin());
|
||||
ttl->m_threaded_loading_textures.unlock();
|
||||
ttl->m_stktm->removeThreadedLoadTexture();
|
||||
pthread_mutex_unlock(ttl->m_texture_queue_mutex);
|
||||
target_tex->threadedReload(ttl->m_pbo_ptr + ttl->m_tex_size_loaded);
|
||||
target_tex->cleanThreadedLoader();
|
||||
ttl->m_tex_size_loaded += target_tex->getTextureSize();
|
||||
ttl->m_completed_textures.lock();
|
||||
ttl->m_completed_textures.getData().push_back(target_tex);
|
||||
ttl->m_completed_textures.unlock();
|
||||
ttl->m_completed_textures.push_back(target_tex);
|
||||
}
|
||||
pthread_exit(NULL);
|
||||
return NULL;
|
||||
} // startRoutine
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void ThreadedTexLoader::handleCompletedTextures()
|
||||
{
|
||||
#if !(defined(SERVER_ONLY) || defined(USE_GLES2))
|
||||
m_completed_textures.lock();
|
||||
m_locked = true;
|
||||
assert(m_locked);
|
||||
size_t offset = 0;
|
||||
for (STKTexture* stkt : m_completed_textures.getData())
|
||||
for (STKTexture* stkt : m_completed_textures)
|
||||
{
|
||||
assert(!stkt->useThreadedLoading());
|
||||
glBindTexture(GL_TEXTURE_2D, stkt->getOpenGLTextureName());
|
||||
@ -99,6 +101,6 @@ void ThreadedTexLoader::handleCompletedTextures()
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
offset += stkt->getTextureSize();
|
||||
}
|
||||
m_completed_textures.getData().clear();
|
||||
m_completed_textures.clear();
|
||||
#endif
|
||||
} // handleCompletedTextures
|
||||
|
@ -19,12 +19,13 @@
|
||||
#define HEADER_THREADED_TEX_LOADER_HPP
|
||||
|
||||
#include "utils/no_copy.hpp"
|
||||
#include "utils/synchronised.hpp"
|
||||
#include "utils/types.hpp"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <vector>
|
||||
|
||||
class STKTexture;
|
||||
class STKTexManager;
|
||||
|
||||
class ThreadedTexLoader : public NoCopy
|
||||
{
|
||||
@ -35,58 +36,63 @@ private:
|
||||
|
||||
uint8_t* m_pbo_ptr;
|
||||
|
||||
pthread_mutex_t m_mutex;
|
||||
|
||||
pthread_mutex_t* m_texture_queue_mutex;
|
||||
|
||||
pthread_cond_t* m_cond_request;
|
||||
|
||||
STKTexManager* m_stktm;
|
||||
|
||||
unsigned m_tex_size_loaded, m_waiting_timeout;
|
||||
|
||||
pthread_t m_thread;
|
||||
|
||||
pthread_cond_t m_cond_request;
|
||||
bool m_finished_loading, m_destroy, m_locked;
|
||||
|
||||
Synchronised<bool> m_finished_loading;
|
||||
|
||||
bool m_destroy, m_locked;
|
||||
|
||||
Synchronised<std::vector<STKTexture*> >
|
||||
m_threaded_loading_textures, m_completed_textures;
|
||||
std::vector<STKTexture*> m_completed_textures;
|
||||
|
||||
public:
|
||||
// ------------------------------------------------------------------------
|
||||
static void* startRoutine(void *obj);
|
||||
// ------------------------------------------------------------------------
|
||||
ThreadedTexLoader(unsigned capacity, size_t offset, uint8_t* pbo_ptr)
|
||||
ThreadedTexLoader(unsigned capacity, size_t offset, uint8_t* pbo_ptr,
|
||||
pthread_mutex_t* mutex, pthread_cond_t* cond,
|
||||
STKTexManager* stktm)
|
||||
: m_tex_capacity(capacity), m_pbo_offset(offset),
|
||||
m_pbo_ptr(pbo_ptr), m_tex_size_loaded(0),
|
||||
m_waiting_timeout(0), m_finished_loading(false),
|
||||
m_destroy(false), m_locked(false)
|
||||
m_pbo_ptr(pbo_ptr), m_texture_queue_mutex(mutex),
|
||||
m_cond_request(cond), m_stktm(stktm),
|
||||
m_tex_size_loaded(0), m_waiting_timeout(0),
|
||||
m_finished_loading(false), m_destroy(false),
|
||||
m_locked(false)
|
||||
{
|
||||
pthread_cond_init(&m_cond_request, NULL);
|
||||
pthread_mutex_init(&m_mutex, NULL);
|
||||
pthread_create(&m_thread, NULL, &startRoutine, this);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
~ThreadedTexLoader()
|
||||
{
|
||||
m_destroy = true;
|
||||
pthread_cond_destroy(&m_cond_request);
|
||||
pthread_mutex_destroy(&m_mutex);
|
||||
pthread_join(m_thread, NULL);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
void addTexture(STKTexture* t)
|
||||
{
|
||||
m_threaded_loading_textures.lock();
|
||||
m_threaded_loading_textures.getData().push_back(t);
|
||||
pthread_cond_signal(&m_cond_request);
|
||||
m_threaded_loading_textures.unlock();
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
bool finishedLoading() const { return m_finished_loading.getAtomic(); }
|
||||
bool finishedLoading() const { return m_finished_loading; }
|
||||
// ------------------------------------------------------------------------
|
||||
void handleCompletedTextures();
|
||||
// ------------------------------------------------------------------------
|
||||
void unlockCompletedTextures()
|
||||
void lock()
|
||||
{
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
m_locked = true;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
void unlock()
|
||||
{
|
||||
if (!m_locked) return;
|
||||
m_locked = false;
|
||||
m_finished_loading.setAtomic(false);
|
||||
m_completed_textures.unlock();
|
||||
m_finished_loading = false;
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
}
|
||||
|
||||
}; // ThreadedTexLoader
|
||||
|
Loading…
Reference in New Issue
Block a user