Skip to content

Commit

Permalink
Texture ID cache to boost mvsim performance
Browse files Browse the repository at this point in the history
  • Loading branch information
jlblancoc committed Dec 9, 2024
1 parent 950b2f0 commit e7ecc04
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 12 deletions.
2 changes: 2 additions & 0 deletions doc/source/doxygen-docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
# Version 2.14.7: UNRELEASED
- Changes in apps:
- rosbag2rawlog (ROS1): Implement conversion of NavSatFix -> mrpt::obs::CObservationGPS
- Changes in libraries:
- mrpt::opengl::Texture now caches "texture names" (OpenGL texture IDs) via image data, boosting performance of MVSim boot up time.
- Build system:
- `mrpt-*-config.cmake` files now enforce the search of cmake dependencies in CONFIG mode, to avoid being foolish by deprecated `FindXXX()` lying around.

Expand Down
2 changes: 1 addition & 1 deletion libs/opengl/include/mrpt/opengl/Texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ class Texture

// Normally users should not need to call these, but they are exposed just in
// case they are useful someday.
texture_name_t getNewTextureNumber();
texture_name_t getNewTextureNumber(const uint8_t* optionalRgbDataForAssociation);
void releaseTextureName(const texture_name_t& t);

} // namespace mrpt::opengl
2 changes: 1 addition & 1 deletion libs/opengl/src/CRenderizableShaderTexturedTriangles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ void CRenderizableShaderTexturedTriangles::assignImage(const CImage& img)

m_glTexture.unloadTexture();

// Make a copy:
// Make a shallow copy:
m_textureImage = img;
m_textureImageAssigned = true;

Expand Down
76 changes: 66 additions & 10 deletions libs/opengl/src/Texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "opengl-precomp.h" // Precompiled header
//
#include <mrpt/containers/bimap.h>
#include <mrpt/core/get_env.h>
#include <mrpt/core/lock_helper.h>
#include <mrpt/opengl/Texture.h>
Expand Down Expand Up @@ -57,8 +58,8 @@ class TextureResourceHandler
return o;
}

/// Return [textureName, textureUnit]
texture_name_t generateTextureID()
/// Return textureName
texture_name_t generateTextureID(const uint8_t* rgbDataForAssociation)
{
#if MRPT_HAS_OPENGL_GLUT || MRPT_HAS_EGL
auto lck = mrpt::lockHelper(m_texturesMtx);
Expand All @@ -71,6 +72,8 @@ class TextureResourceHandler
CHECK_OPENGL_ERROR_IN_DEBUG();
m_textureReservedFrom[textureID] = std::this_thread::get_id();

if (rgbDataForAssociation) m_textureToRGBdata.insert(textureID, rgbDataForAssociation);

if (MRPT_OPENGL_VERBOSE)
std::cout << "[mrpt generateTextureID] textureName:" << textureID << std::endl;

Expand All @@ -80,6 +83,21 @@ class TextureResourceHandler
#endif
}

std::optional<texture_name_t> checkIfTextureAlreadyExists(const mrpt::img::CImage& rgb)
{
#if MRPT_HAS_OPENGL_GLUT || MRPT_HAS_EGL
auto lck = mrpt::lockHelper(m_texturesMtx);

auto it = m_textureToRGBdata.getInverseMap().find(rgb.asCvMatRef().data);
if (it != m_textureToRGBdata.getInverseMap().end())
return it->second;
else
return {};
#else
return {};
#endif
}

void releaseTextureID(unsigned int texName)
{
#if MRPT_HAS_OPENGL_GLUT || MRPT_HAS_EGL
Expand Down Expand Up @@ -109,19 +127,36 @@ class TextureResourceHandler
void processDestroyQueue()
{
#if MRPT_HAS_OPENGL_GLUT || MRPT_HAS_EGL
if (auto itLst = m_destroyQueue.find(std::this_thread::get_id()); itLst != m_destroyQueue.end())
if (auto itLst = m_destroyQueue.find(std::this_thread::get_id());
itLst != m_destroyQueue.end() && !itLst->second.empty())
{
auto& lst = itLst->second;

// Delete in OpenGL:
glDeleteTextures(lst.size(), lst.data());
CHECK_OPENGL_ERROR_IN_DEBUG();

// delete in rgb data container too:
for (const auto id : lst)
{
if (m_textureToRGBdata.hasKey(id)) m_textureToRGBdata.erase_by_key(id);
}

if (MRPT_OPENGL_VERBOSE)
{
std::cout << "[mrpt processDestroyQueue] threadId=" << std::this_thread::get_id()
<< " destroyed " << lst.size() << "\n";
}
lst.clear();
m_destroyQueue.erase(itLst);
}
if (MRPT_OPENGL_VERBOSE)
if (!m_destroyQueue.empty() && MRPT_OPENGL_VERBOSE)
{
std::cout << "[mrpt processDestroyQueue] threadId=" << std::this_thread::get_id()
<< ". At output: ";
<< ". Remaining at output: ";
for (const auto& lst : m_destroyQueue)
std::cout << "[" << lst.first << "]=" << lst.second.size() << " ";
std::cout << "[" << lst.first << "]=" << lst.second.size() << " textures ";
std::cout << "\n";
}
#endif
}
Expand All @@ -130,14 +165,20 @@ class TextureResourceHandler
std::mutex m_texturesMtx;
std::map<GLuint, std::thread::id> m_textureReservedFrom;
std::map<std::thread::id, std::vector<GLuint>> m_destroyQueue;
mrpt::containers::bimap<GLuint, const uint8_t*> m_textureToRGBdata;
GLint m_maxTextureUnits;
#endif
};

std::optional<texture_name_t> checkIfTextureAlreadyExists(const mrpt::img::CImage& rgb)
{
return TextureResourceHandler::Instance().checkIfTextureAlreadyExists(rgb);
}

/// Returns: [texture name, texture unit]
texture_name_t mrpt::opengl::getNewTextureNumber()
texture_name_t mrpt::opengl::getNewTextureNumber(const uint8_t* optionalRgbDataForAssociation)
{
return TextureResourceHandler::Instance().generateTextureID();
return TextureResourceHandler::Instance().generateTextureID(optionalRgbDataForAssociation);
}

void mrpt::opengl::releaseTextureName(const texture_name_t& t)
Expand Down Expand Up @@ -247,6 +288,21 @@ void Texture::internalAssignImage_2D(
in_rgb->forceLoad(); // just in case they are lazy-load imgs
if (in_alpha) in_alpha->forceLoad();

// Check if we already have this texture loaded in GPU and avoid creating
// duplicated texture ID:
const auto existingTextureId = checkIfTextureAlreadyExists(*in_rgb);
if (existingTextureId.has_value())
{
get() = existingTextureId.value();
get()->unit = textureUnit;

if (MRPT_OPENGL_VERBOSE)
std::cout << "[mrpt internalAssignImage_2D] Reusing existing textureName:" << get()->name
<< "\n";

return;
}

mrpt::img::CImage rgb;

switch (in_rgb->getPixelDepth())
Expand Down Expand Up @@ -290,7 +346,7 @@ void Texture::internalAssignImage_2D(
if (in_alpha) alpha = mrpt::img::CImage(*in_alpha, mrpt::img::SHALLOW_COPY);

// allocate texture names:
get() = getNewTextureNumber();
get() = getNewTextureNumber(in_rgb->asCvMatRef().data);
get()->unit = textureUnit;

// activate the texture unit first before binding texture
Expand Down Expand Up @@ -536,7 +592,7 @@ void Texture::assignCubeImages(const std::array<mrpt::img::CImage, 6>& imgs, int
}

// allocate texture "name" (ID):
get() = getNewTextureNumber();
get() = getNewTextureNumber(nullptr); /* no cached img for cube textures */

// activate the texture unit first before binding texture
bindAsCubeTexture();
Expand Down

0 comments on commit e7ecc04

Please sign in to comment.