Skip to content

Commit e7ecc04

Browse files
committed
Texture ID cache to boost mvsim performance
1 parent 950b2f0 commit e7ecc04

File tree

4 files changed

+70
-12
lines changed

4 files changed

+70
-12
lines changed

doc/source/doxygen-docs/changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
# Version 2.14.7: UNRELEASED
44
- Changes in apps:
55
- rosbag2rawlog (ROS1): Implement conversion of NavSatFix -> mrpt::obs::CObservationGPS
6+
- Changes in libraries:
7+
- mrpt::opengl::Texture now caches "texture names" (OpenGL texture IDs) via image data, boosting performance of MVSim boot up time.
68
- Build system:
79
- `mrpt-*-config.cmake` files now enforce the search of cmake dependencies in CONFIG mode, to avoid being foolish by deprecated `FindXXX()` lying around.
810

libs/opengl/include/mrpt/opengl/Texture.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ class Texture
134134

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

140140
} // namespace mrpt::opengl

libs/opengl/src/CRenderizableShaderTexturedTriangles.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ void CRenderizableShaderTexturedTriangles::assignImage(const CImage& img)
211211

212212
m_glTexture.unloadTexture();
213213

214-
// Make a copy:
214+
// Make a shallow copy:
215215
m_textureImage = img;
216216
m_textureImageAssigned = true;
217217

libs/opengl/src/Texture.cpp

Lines changed: 66 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "opengl-precomp.h" // Precompiled header
1111
//
12+
#include <mrpt/containers/bimap.h>
1213
#include <mrpt/core/get_env.h>
1314
#include <mrpt/core/lock_helper.h>
1415
#include <mrpt/opengl/Texture.h>
@@ -57,8 +58,8 @@ class TextureResourceHandler
5758
return o;
5859
}
5960

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

75+
if (rgbDataForAssociation) m_textureToRGBdata.insert(textureID, rgbDataForAssociation);
76+
7477
if (MRPT_OPENGL_VERBOSE)
7578
std::cout << "[mrpt generateTextureID] textureName:" << textureID << std::endl;
7679

@@ -80,6 +83,21 @@ class TextureResourceHandler
8083
#endif
8184
}
8285

86+
std::optional<texture_name_t> checkIfTextureAlreadyExists(const mrpt::img::CImage& rgb)
87+
{
88+
#if MRPT_HAS_OPENGL_GLUT || MRPT_HAS_EGL
89+
auto lck = mrpt::lockHelper(m_texturesMtx);
90+
91+
auto it = m_textureToRGBdata.getInverseMap().find(rgb.asCvMatRef().data);
92+
if (it != m_textureToRGBdata.getInverseMap().end())
93+
return it->second;
94+
else
95+
return {};
96+
#else
97+
return {};
98+
#endif
99+
}
100+
83101
void releaseTextureID(unsigned int texName)
84102
{
85103
#if MRPT_HAS_OPENGL_GLUT || MRPT_HAS_EGL
@@ -109,19 +127,36 @@ class TextureResourceHandler
109127
void processDestroyQueue()
110128
{
111129
#if MRPT_HAS_OPENGL_GLUT || MRPT_HAS_EGL
112-
if (auto itLst = m_destroyQueue.find(std::this_thread::get_id()); itLst != m_destroyQueue.end())
130+
if (auto itLst = m_destroyQueue.find(std::this_thread::get_id());
131+
itLst != m_destroyQueue.end() && !itLst->second.empty())
113132
{
114133
auto& lst = itLst->second;
134+
135+
// Delete in OpenGL:
115136
glDeleteTextures(lst.size(), lst.data());
116137
CHECK_OPENGL_ERROR_IN_DEBUG();
138+
139+
// delete in rgb data container too:
140+
for (const auto id : lst)
141+
{
142+
if (m_textureToRGBdata.hasKey(id)) m_textureToRGBdata.erase_by_key(id);
143+
}
144+
145+
if (MRPT_OPENGL_VERBOSE)
146+
{
147+
std::cout << "[mrpt processDestroyQueue] threadId=" << std::this_thread::get_id()
148+
<< " destroyed " << lst.size() << "\n";
149+
}
117150
lst.clear();
151+
m_destroyQueue.erase(itLst);
118152
}
119-
if (MRPT_OPENGL_VERBOSE)
153+
if (!m_destroyQueue.empty() && MRPT_OPENGL_VERBOSE)
120154
{
121155
std::cout << "[mrpt processDestroyQueue] threadId=" << std::this_thread::get_id()
122-
<< ". At output: ";
156+
<< ". Remaining at output: ";
123157
for (const auto& lst : m_destroyQueue)
124-
std::cout << "[" << lst.first << "]=" << lst.second.size() << " ";
158+
std::cout << "[" << lst.first << "]=" << lst.second.size() << " textures ";
159+
std::cout << "\n";
125160
}
126161
#endif
127162
}
@@ -130,14 +165,20 @@ class TextureResourceHandler
130165
std::mutex m_texturesMtx;
131166
std::map<GLuint, std::thread::id> m_textureReservedFrom;
132167
std::map<std::thread::id, std::vector<GLuint>> m_destroyQueue;
168+
mrpt::containers::bimap<GLuint, const uint8_t*> m_textureToRGBdata;
133169
GLint m_maxTextureUnits;
134170
#endif
135171
};
136172

173+
std::optional<texture_name_t> checkIfTextureAlreadyExists(const mrpt::img::CImage& rgb)
174+
{
175+
return TextureResourceHandler::Instance().checkIfTextureAlreadyExists(rgb);
176+
}
177+
137178
/// Returns: [texture name, texture unit]
138-
texture_name_t mrpt::opengl::getNewTextureNumber()
179+
texture_name_t mrpt::opengl::getNewTextureNumber(const uint8_t* optionalRgbDataForAssociation)
139180
{
140-
return TextureResourceHandler::Instance().generateTextureID();
181+
return TextureResourceHandler::Instance().generateTextureID(optionalRgbDataForAssociation);
141182
}
142183

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

291+
// Check if we already have this texture loaded in GPU and avoid creating
292+
// duplicated texture ID:
293+
const auto existingTextureId = checkIfTextureAlreadyExists(*in_rgb);
294+
if (existingTextureId.has_value())
295+
{
296+
get() = existingTextureId.value();
297+
get()->unit = textureUnit;
298+
299+
if (MRPT_OPENGL_VERBOSE)
300+
std::cout << "[mrpt internalAssignImage_2D] Reusing existing textureName:" << get()->name
301+
<< "\n";
302+
303+
return;
304+
}
305+
250306
mrpt::img::CImage rgb;
251307

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

292348
// allocate texture names:
293-
get() = getNewTextureNumber();
349+
get() = getNewTextureNumber(in_rgb->asCvMatRef().data);
294350
get()->unit = textureUnit;
295351

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

538594
// allocate texture "name" (ID):
539-
get() = getNewTextureNumber();
595+
get() = getNewTextureNumber(nullptr); /* no cached img for cube textures */
540596

541597
// activate the texture unit first before binding texture
542598
bindAsCubeTexture();

0 commit comments

Comments
 (0)