Commit 1e8bb380 authored by Jakob Weiss's avatar Jakob Weiss
Browse files

Introduced TextureManager

Texture manager manages textures in a cache, for more efficient texture reuse. Currently only clears the cache on program exit, no garbage collection, disabled by default.
parent a23b1e70
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ SET(CGT_SOURCES
	shadermanager.cpp
	stopwatch.cpp
	texture.cpp
	texturemanager.cpp
	texturereader.cpp
	texturereadertga.cpp
	textureunit.cpp
+9 −2
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#include "cgt/shadermanager.h"
#include "cgt/singleton.h"
#include "cgt/texturereadertga.h"
#include "cgt/texturemanager.h"

#include "cgt/event/eventhandler.h"

@@ -48,8 +49,6 @@
#include <IL/ilu.h>
#endif



namespace cgt {

void init(InitFeature::Features featureset, LogLevel logLevel) {
@@ -101,6 +100,8 @@ void initGL(GLCanvas* backgroundGlContext, InitFeature::Features featureset) {
    OpenGLJobProcessor::init();
    GlContextManager::getRef().registerContextAndInitGlew(backgroundGlContext, "CGT Background Context");

    TextureManager::init();

    if (featureset & InitFeature::GPU_PROPERTIES )
        GpuCapabilities::init();
#ifdef _MSC_VER
@@ -112,6 +113,10 @@ void initGL(GLCanvas* backgroundGlContext, InitFeature::Features featureset) {
}

void deinitGL() {
    if (TextureManager::isInited()) {
        TextureManager::deinit();
    }

    if (GpuCapabilities::isInited())
        GpuCapabilities::deinit();
#ifdef _MSC_VER
@@ -123,6 +128,8 @@ void deinitGL() {

    OpenGLJobProcessor::deinit();
    GlContextManager::deinit();


}

} // namespace
+24 −5
Original line number Diff line number Diff line
@@ -32,6 +32,8 @@
#include "cgt/gpucapabilities.h"
#include "cgt/filesystem.h"

#include "texturemanager.h"

namespace cgt {

Texture::Texture(GLenum type, const cgt::ivec3& dimensions, GLint internalFormat, Filter filter /*= LINEAR*/) 
@@ -44,7 +46,7 @@ Texture::Texture(GLenum type, const cgt::ivec3& dimensions, GLint internalFormat
    , bpp_(0)
{
    init();
    uploadTexture(nullptr, calcMatchingFormat(internalFormat), calcMatchingDataType(internalFormat));
    //uploadTexture(nullptr, calcMatchingFormat(internalFormat), calcMatchingDataType(internalFormat));
}

Texture::Texture(GLenum type, const cgt::ivec3& dimensions, GLint internalFormat, GLubyte* data, GLint format, GLenum dataType, Filter filter /*= LINEAR*/) 
@@ -63,7 +65,7 @@ Texture::Texture(GLenum type, const cgt::ivec3& dimensions, GLint internalFormat

Texture::~Texture() {
    if (id_)
        glDeleteTextures(1, &id_);
        TexMgr.releaseId(id_, type_, dimensions_, internalformat_);
}


@@ -71,6 +73,8 @@ void Texture::init() {
    bpp_ = calcBpp(internalformat_);
    generateId();
    applyFilter();
    applyWrapping();
    LGL_ERROR;
}

int Texture::calcBpp(GLint format, GLenum dataType) {
@@ -320,6 +324,17 @@ int Texture::getSizeOnGPU() const {
    return bpp * hmul(dimensions_);
}

void Texture::bind() const
{
    glBindTexture(type_, id_);
}

GLuint Texture::generateId()
{
    id_ = TexMgr.generateId(type_, dimensions_, internalformat_);
    return id_;
}

void Texture::setFilter(Filter filter) {
    filter_ = filter;
    applyFilter();
@@ -372,21 +387,21 @@ void Texture::uploadTexture(const GLubyte* data, GLint format, GLenum dataType)

    switch (type_) {
        case GL_TEXTURE_1D:
            glTexImage1D(type_, 0, internalformat_, dimensions_.x, 0, format, dataType, data);
            glTexSubImage1D(type_, 0, 0, dimensions_.x, format, dataType, data);
            if (filter_ == MIPMAP)
                glGenerateMipmap(GL_TEXTURE_1D);
            break;

        case GL_TEXTURE_1D_ARRAY: // fallthrough
        case GL_TEXTURE_2D:
            glTexImage2D(type_, 0, internalformat_, dimensions_.x, dimensions_.y, 0, format, dataType, data);
            glTexSubImage2D(type_, 0, 0, 0, dimensions_.x, dimensions_.y, format, dataType, data);
            if (filter_ == MIPMAP)
                glGenerateMipmap(GL_TEXTURE_2D);
            break;

        case GL_TEXTURE_2D_ARRAY: // fallthrough
        case GL_TEXTURE_3D:
            glTexImage3D(type_, 0, internalformat_, dimensions_.x, dimensions_.y, dimensions_.z, 0, format, dataType, data);
            glTexSubImage3D(type_, 0, 0, 0, 0, dimensions_.x, dimensions_.y, dimensions_.z, format, dataType, data);
            if (filter_ == MIPMAP)
                glGenerateMipmap(GL_TEXTURE_3D);
            break;
@@ -709,5 +724,9 @@ GLenum Texture::calcMatchingDataType(GLint internalFormat) {
    }
}

void Texture::unbind() const
{
    glBindTexture(type_, 0);
}

} // namespace cgt
+3 −11
Original line number Diff line number Diff line
@@ -117,16 +117,12 @@ public:
     *
     * Note: This does not enable texturing (use enable()).
     */
    void bind() const {
        glBindTexture(type_ , id_);
    }
    void bind() const;

    /**
     * unbind the current texture from the active texture unit and target.
     */
    void unbind() const {
        glBindTexture(type_, 0);
    }
    void unbind() const;


    /**
@@ -138,11 +134,7 @@ public:
     *   Generate OpenGL texture ID
     *   @return The generated ID
     */
    GLuint generateId() {
        id_ = 0;
        glGenTextures(1, &id_);
        return id_;
    }
    GLuint generateId();

    std::string getName() const { return name_; }
    void setName(const std::string& name) { name_ = name; }
+89 −0
Original line number Diff line number Diff line
#include "texturemanager.h"
#include "texture.h"
#include "singleton.h"


cgt::TextureManager::TextureManager()
{

}

cgt::TextureManager::~TextureManager()
{
    std::lock_guard<std::mutex> scope_lock(accessMutex_);
    std::cout << "[TextureManager] releasing texture pool with " << texturePool_.size() << " textures..." << std::endl;
    for (auto& it : texturePool_) {
        std::cout << "Deleting texture of size [" << std::get<1>(it.first) << "," << std::get<2>(it.first) << "," << std::get<3>(it.first) 
            << "] of type " << std::get<0>(it.first) << " " << std::get<3>(it.first) << std::endl;
        glDeleteTextures(1, &it.second);
    }
}

GLuint cgt::TextureManager::generateId(GLenum type, const cgt::svec3 & dimensions, GLenum internalFormat)
{
#ifdef ENABLE_TEXTURE_POOL
    std::lock_guard<std::mutex> scope_lock(accessMutex_);

    GLuint id;
    auto it = texturePool_.find(std::make_tuple(type, dimensions.x, dimensions.y, dimensions.z, internalFormat));
    if (it != texturePool_.end()) {
        id = it->second;
        texturePool_.erase(it);
    }
    else {
        glGenTextures(1, &id);

        glBindTexture(type, id);

        switch (type) {
        case GL_TEXTURE_1D:
            glTexImage1D(type, 0, internalFormat, dimensions.x, 0, Texture::calcMatchingFormat(internalFormat), Texture::calcMatchingDataType(internalFormat), nullptr);
            break;

        case GL_TEXTURE_1D_ARRAY: // fallthrough
        case GL_TEXTURE_2D:
            glTexImage2D(type, 0, internalFormat, dimensions.x, dimensions.y, 0, Texture::calcMatchingFormat(internalFormat), Texture::calcMatchingDataType(internalFormat), nullptr);
            break;

        case GL_TEXTURE_2D_ARRAY: // fallthrough
        case GL_TEXTURE_3D:
            glTexImage3D(type, 0, internalFormat, dimensions.x, dimensions.y, dimensions.z, 0, Texture::calcMatchingFormat(internalFormat), Texture::calcMatchingDataType(internalFormat), nullptr);
            break;
        }
        LGL_ERROR;
    }
#else
    GLuint id;
    glGenTextures(1, &id);

    glBindTexture(type, id);

    switch (type) {
    case GL_TEXTURE_1D:
        glTexImage1D(type, 0, internalFormat, dimensions.x, 0, Texture::calcMatchingFormat(internalFormat), Texture::calcMatchingDataType(internalFormat), nullptr);
        break;

    case GL_TEXTURE_1D_ARRAY: // fallthrough
    case GL_TEXTURE_2D:
        glTexImage2D(type, 0, internalFormat, dimensions.x, dimensions.y, 0, Texture::calcMatchingFormat(internalFormat), Texture::calcMatchingDataType(internalFormat), nullptr);
        break;

    case GL_TEXTURE_2D_ARRAY: // fallthrough
    case GL_TEXTURE_3D:
        glTexImage3D(type, 0, internalFormat, dimensions.x, dimensions.y, dimensions.z, 0, Texture::calcMatchingFormat(internalFormat), Texture::calcMatchingDataType(internalFormat), nullptr);
        break;
    }
    LGL_ERROR;
#endif
    return id;
}

void cgt::TextureManager::releaseId(GLuint id, GLenum type, const cgt::svec3 & dimensions, GLenum internalFormat)
{
#ifdef ENABLE_TEXTURE_POOL
    std::lock_guard<std::mutex> scope_lock(accessMutex_);
    texturePool_.insert(std::make_pair(std::make_tuple(type, dimensions.x, dimensions.y, dimensions.z, internalFormat), id));
#else
    glDeleteTextures(1, &id);
#endif
}
Loading