Notice: If you are member of any public project or group, please make sure that your GitLab username is not the same as the LRZ identifier/Kennung (see https://gitlab.lrz.de/profile/account). Please change your username if necessary. For more information see the section "Public projects / Öffentliche Projekte" at https://doku.lrz.de/display/PUBLIC/GitLab . Thank you!

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

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
......@@ -40,6 +40,7 @@ SET(CGT_SOURCES
shadermanager.cpp
stopwatch.cpp
texture.cpp
texturemanager.cpp
texturereader.cpp
texturereadertga.cpp
textureunit.cpp
......
......@@ -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
......@@ -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
......@@ -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; }
......
#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
}
#ifndef TEXTUREMANAGER_H__
#define TEXTUREMANAGER_H__
#include "cgt/cgt_gl.h"
#include "cgt/singleton.h"
#include "cgt/vector.h"
#include <mutex>
#include <map>
#include <tuple>
namespace cgt {
class TextureManager : public Singleton<TextureManager> {
public:
TextureManager();
~TextureManager();
GLuint generateId(GLenum type, const cgt::svec3& dimensions, GLenum internalFormat);
void releaseId(GLuint id, GLenum type, const cgt::svec3& dimensions, GLenum internalFormat);
private:
std::mutex accessMutex_;
std::multimap<std::tuple<GLenum, size_t, size_t, size_t, GLenum>, GLuint> texturePool_;
};
}
#define TexMgr cgt::Singleton<cgt::TextureManager>::getRef()
#endif // TEXTUREMANAGER_H__
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment