[gl] Refactor texture pool cleanup
Texture pool now allocates a block of 64 textures per time. Each block contains a TextureObject which handles GL object lifetime. Blocks can be added or removed according to the following rules: 1. If pool is empty, created a new block upon first call (lazy load); 2. Iterate blocks to find an available texture ID: - If found, remove that from the list of available IDs for that block and return its ID. - Othewise, allocate a new block and grab an available ID from that. 3. When releasing a texture ID, check if the associated block is free. If no IDs are currently in use, then abandon its TextureObject and remove the block from the pool.
This commit is contained in:
@@ -1,38 +1,44 @@
|
||||
#include <mbgl/gl/texture_pool.hpp>
|
||||
|
||||
#include <mbgl/gl/gl_object_store.hpp>
|
||||
#include <mbgl/util/thread_context.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
const GLsizei TextureMax = 64;
|
||||
|
||||
namespace mbgl {
|
||||
namespace gl {
|
||||
|
||||
GLuint TexturePool::getTextureID() {
|
||||
if (texture_ids.empty()) {
|
||||
GLuint new_texture_ids[TextureMax];
|
||||
MBGL_CHECK_ERROR(glGenTextures(TextureMax, new_texture_ids));
|
||||
for (GLuint id = 0; id < TextureMax; id++) {
|
||||
texture_ids.insert(new_texture_ids[id]);
|
||||
}
|
||||
}
|
||||
|
||||
GLuint id = 0;
|
||||
|
||||
if (!texture_ids.empty()) {
|
||||
std::set<GLuint>::iterator id_iterator = texture_ids.begin();
|
||||
id = *id_iterator;
|
||||
texture_ids.erase(id_iterator);
|
||||
if (pools.empty()) pools.emplace_back();
|
||||
|
||||
for (auto& impl : pools) {
|
||||
if (impl.ids.empty()) continue;
|
||||
auto it = impl.ids.begin();
|
||||
GLuint id = *it;
|
||||
impl.ids.erase(it);
|
||||
return id;
|
||||
}
|
||||
|
||||
// All texture IDs are in use.
|
||||
pools.emplace_back();
|
||||
auto it = pools.back().ids.begin();
|
||||
GLuint id = *it;
|
||||
pools.back().ids.erase(it);
|
||||
return id;
|
||||
}
|
||||
|
||||
void TexturePool::removeTextureID(GLuint texture_id) {
|
||||
texture_ids.insert(texture_id);
|
||||
// TODO: We need to find a better way to deal with texture pool cleanup
|
||||
void TexturePool::releaseTextureID(GLuint id) {
|
||||
for (auto it = pools.begin(); it != pools.end(); ++it) {
|
||||
for (GLsizei i = 0; i < gl::TexturePoolHolder::TextureMax; ++i) {
|
||||
if (it->pool[i] == id) {
|
||||
it->ids.push_back(id);
|
||||
if (GLsizei(it->ids.size()) == gl::TexturePoolHolder::TextureMax) {
|
||||
util::ThreadContext::getGLObjectStore()->abandon(std::move(it->pool));
|
||||
pools.erase(it);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gl
|
||||
|
||||
@@ -3,20 +3,36 @@
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/gl/gl.hpp>
|
||||
#include <mbgl/gl/gl_object_store.hpp>
|
||||
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace mbgl {
|
||||
namespace gl {
|
||||
|
||||
class TexturePool : private util::noncopyable {
|
||||
|
||||
public:
|
||||
GLuint getTextureID();
|
||||
void removeTextureID(GLuint texture_id);
|
||||
void releaseTextureID(GLuint);
|
||||
|
||||
private:
|
||||
std::set<GLuint> texture_ids;
|
||||
class Impl : private util::noncopyable {
|
||||
public:
|
||||
Impl() : ids(gl::TexturePoolHolder::TextureMax) {
|
||||
pool.create();
|
||||
std::copy(pool.getIDs().begin(), pool.getIDs().end(), ids.begin());
|
||||
}
|
||||
|
||||
Impl(Impl&& o) : pool(std::move(o.pool)), ids(std::move(o.ids)) {}
|
||||
Impl& operator=(Impl&& o) { pool = std::move(o.pool); ids = std::move(o.ids); return *this; }
|
||||
|
||||
gl::TexturePoolHolder pool;
|
||||
std::vector<GLuint> ids;
|
||||
};
|
||||
|
||||
std::vector<Impl> pools;
|
||||
};
|
||||
|
||||
} // namespace gl
|
||||
|
||||
@@ -15,7 +15,7 @@ Raster::Raster(gl::TexturePool& texturePool_)
|
||||
|
||||
Raster::~Raster() {
|
||||
if (textured) {
|
||||
texturePool.removeTextureID(textureID);
|
||||
texturePool.releaseTextureID(textureID);
|
||||
textureID = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user