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 3f555763 authored by Jakob Weiss's avatar Jakob Weiss

Minor fixes

* texturemanager documentation and parameter fix
* imagerepresetation conversion fix for channel number mismatch
parent 65ba33a1
......@@ -97,6 +97,11 @@ namespace campvis {
else if (const ImageRepresentationGL* tester = dynamic_cast<const ImageRepresentationGL*>(source)) {
// converting from GL representation
GenericImageRepresentationLocal<BASETYPE, NUMCHANNELS>* toReturn = nullptr;
// Cannot convert if channels don't match
if (tester->getParent()->getNumChannels() != NUMCHANNELS)
return nullptr;
GLJobProc.enqueueJobBlocking([&]() {
if (cgt::Texture::calcMatchingPixelDataType(tester->getTexture()->getInternalFormat()) != TypeTraits<BASETYPE, NUMCHANNELS>::glDataType)
LDEBUGC("CAMPVis.core.datastructures.GenericLocalConversion", "Performing conversion between data types, you may lose information or the resulting data may show other unexpected features.");
......
......@@ -80,8 +80,7 @@ void cgt::TextureManager::performGarbageCollection()
std::stringstream dbgOut;
dbgOut.imbue(std::locale(std::cout.getloc(), new PointSeparator(1)));
dbgOut << texturePoolMemory_ << " Bytes of in texture pool, additionally " << activeAllocatedMemory_ << " Bytes still in use.";
dbgOut << "releasing texture pool with " << texturePool_.size() << " textures...";
dbgOut << texturePoolMemory_ << " Bytes of in texture pool, additionally " << activeAllocatedMemory_ << " Bytes still in use." << std::endl;
size_t releasedBytes = 0;
std::stringstream ss;
......@@ -139,6 +138,10 @@ GLuint cgt::TextureManager::generateId(GLenum type, const cgt::svec3 & dimension
{
cache_key_t cacheKey{ type, dimensions.x, dimensions.y, dimensions.z, internalFormat };
cgtAssert(cgt::hmul(dimensions) > 0, "At least one dimension is zero!");
cgtAssert(type == GL_TEXTURE_1D && dimensions.y == 1 && dimensions.z == 1, "1D texture but higher dimensions are not 1!");
cgtAssert(type == GL_TEXTURE_2D && dimensions.z == 1, "2D texture but z is not 1!");
#ifdef ENABLE_TEXTURE_POOL
std::lock_guard<std::mutex> scope_lock(accessMutex_);
......@@ -158,19 +161,19 @@ GLuint cgt::TextureManager::generateId(GLenum type, const cgt::svec3 & dimension
switch (type) {
case GL_TEXTURE_1D:
glTexImage1D(type, 0, internalFormat, static_cast<GLsizei>(dimensions.x), 0,
glTexImage1D(type, 0, internalFormat, static_cast<GLsizei>(dimensions.x), 0,
Texture::calcMatchingPixelFormat(internalFormat), Texture::calcMatchingPixelDataType(internalFormat), nullptr);
break;
case GL_TEXTURE_1D_ARRAY: // fallthrough
case GL_TEXTURE_2D:
glTexImage2D(type, 0, internalFormat, static_cast<GLsizei>(dimensions.x), static_cast<GLsizei>(dimensions.y), 0,
glTexImage2D(type, 0, internalFormat, static_cast<GLsizei>(dimensions.x), static_cast<GLsizei>(dimensions.y), 0,
Texture::calcMatchingPixelFormat(internalFormat), Texture::calcMatchingPixelDataType(internalFormat), nullptr);
break;
case GL_TEXTURE_2D_ARRAY: // fallthrough
case GL_TEXTURE_3D:
glTexImage3D(type, 0, internalFormat, static_cast<GLsizei>(dimensions.x), static_cast<GLsizei>(dimensions.y), static_cast<GLsizei>(dimensions.z), 0,
glTexImage3D(type, 0, internalFormat, static_cast<GLsizei>(dimensions.x), static_cast<GLsizei>(dimensions.y), static_cast<GLsizei>(dimensions.z), 0,
Texture::calcMatchingPixelFormat(internalFormat), Texture::calcMatchingPixelDataType(internalFormat), nullptr);
break;
}
......
......@@ -11,7 +11,16 @@
#include <tuple>
namespace cgt {
/**
* Implements a texture manager which caches deleted textures for reuse.
* This is closely tied to the \a Texture class, as the texture class calls TextureManager::generateId and TextureManager::releaseId
* in its init() and destructor.
*
* Once the TextureManager singleton is created, it will invoke garbage collection events in intervals configured by garbageCollectionDelayMs.
* On every garbage collection event, the lifetime of all cached textures will be incremented. If the lifetime of any texture exceeds \a garbageLifetime,
* the texture will be marked for garbage collection. At the end of the garbage collection event, a job will be enqueued in the \a OpenGlJobProcessor
* to asynchronously release the textures within a valid OpenGL context.
*/
class TextureManager : public Singleton<TextureManager>, public RunnableWithConditionalWait {
public:
TextureManager();
......@@ -26,11 +35,32 @@ namespace cgt {
/**
* Forces the texture pool to be cleared synchronously. This method is threadsafe.
*
* Can be called
*/
void forceClearPool();
/**
* Generates a texture with an already associated buffer with the specified properties,
* either by re-using a cached texture or by creating a new one using glGenTextures and glTexImage[1|2|3]D
*
* \param type the texture type, i.e. GL_TEXTURE_1D, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_3D
* \param dimensions the size of the texture buffer
* \param internalFormat the internal format of the texture buffer, see https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage2D.xhtml
* \return the opengl texture id, see https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGenTextures.xhtml
*/
GLuint generateId(GLenum type, const cgt::svec3& dimensions, GLenum internalFormat);
/**
* Releases a texture id with the specified properties into the texture pool. TextureManager will
* take care of releasing the texture, either at a garbage collection event or by re-assigning it upon a
* call to \a generateId().
*
* \param id the opengl texture id, either from a call to \a generateId or glGenTextures
* \param type the texture type, i.e. GL_TEXTURE_1D, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_3D
* \param dimensions the size of the texture buffer
* \param internalFormat the internal format of the texture buffer, see https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage2D.xhtml
*/
void releaseId(GLuint id, GLenum type, const cgt::svec3& dimensions, GLenum internalFormat);
/// \see Runnable::run()
......@@ -51,10 +81,11 @@ namespace cgt {
using cache_key_t = cache_key;
/// GC will be performed regularly at this interval, in [ms]
const size_t garbageCollectionDelayMs = 5000;
const size_t garbageCollectionDelayMs = 1000;
/// cached objects will be collected after this many GC attempts
const int garbageLifetime = 3;
/// cached objects will be collected after this many GC attempts. This translates to
/// a real-world lifetime of garbageLifeTime * garbageCollectionDelayMs milliseconds
const int garbageLifetime = 10;
/// Compute the memory size from the cache entry key
static constexpr size_t textureByteSize(const cache_key_t& key);
......
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